<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: PHP</title><link>https://academy.hsoub.com/programming/php/page/2/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: PHP</description><language>ar</language><item><title>&#x645;&#x639;&#x627;&#x644;&#x62C;&#x629; &#x627;&#x644;&#x635;&#x648;&#x631; &#x645;&#x639; &#x645;&#x643;&#x62A;&#x628;&#x629; GD &#x648;&#x645;&#x643;&#x62A;&#x628;&#x629; Imagick &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%85%D8%B9-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-gd-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-imagick-%D9%81%D9%8A-php-r1178/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/6.png.bfaa67c3a0f912a55c7f810a3c32c90c.png" /></p>

<h2>
	خرج الصورة
</h2>

<p>
	يمكن إنشاء صورة باستخدام دوال <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imagepng.php#refsect1-function.imagepng-seealso" rel="">image*‎</a> حيث * هي صيغة الملف، وهذه الدوال لها الصيغة المشتركة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_7" style="">
<span class="kwd">bool</span><span class="pln"> image___</span><span class="pun">(</span><span class="pln">resource $im </span><span class="pun">[,</span><span class="pln"> mixed $to </span><span class="pun">[</span><span class="pln"> other parameters</span><span class="pun">]]</span><span class="pln"> </span><span class="pun">)</span></pre>

<h3>
	الحفظ إلى ملف
</h3>

<p>
	يمكنك تمرير اسم الملف أو مجرى ملف مفتوح للمتغير <code>‎$to</code> إذا كنت تريد حفظ الصورة إلى ملف، إذا مررت مجرى فلا تحتاج لإغلاقه لأنّ مكتبة GD تغلقه تلقائيًا، مثلًا لحفظ ملف PNG:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_9" style="">
<span class="pln">imagepng</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/path/to/target/file.png"</span><span class="pun">);</span><span class="pln"> 

$stream </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"phar://path/to/target.phar/file.png"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"wb"</span><span class="pun">);</span><span class="pln"> 
imagepng</span><span class="pun">(</span><span class="pln">$image2</span><span class="pun">,</span><span class="pln"> $stream</span><span class="pun">);</span><span class="pln">
</span><span class="com">// لا حاجة لإغلاق المجرى</span></pre>

<p>
	تأكد عند استخدام <code>fopen</code> من أنك تستخدم الراية <code>b</code> وليس الراية <code>t</code> لأن الملف هو خرج ثنائي، ولا تحاول أن تمرر <code>fopen("php://temp", $f)‎</code> أو <code>fopen("php://memory", $f)‎</code> لأنّ الدالة تُغلق المجرى بعد الاستدعاء ولن تبقى قادرًا على استدعائه أو استخدامه لاسترداد محتوياته مثلًا.
</p>

<h3>
	الخرج كرد HTTP
</h3>

<p>
	لا تحتاج إلى تمرير شيء (أو مرر null) كوسيط ثانٍ إذا كنت تريد أن ترجع هذه الصورة مباشرةً كرد للصورة (لإنشاء بطاقات ديناميكية مثلًا)، لكنك تحتاج إلى تحديد نوع المحتوى في رد HTTP:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_11" style="">
<span class="pln">header</span><span class="pun">(</span><span class="str">"Content-Type: $mimeType"</span><span class="pun">);</span></pre>

<p>
	<code>‎$mimeType</code> هو نوع الصياغة المُرجعة في الترويسة <code>MIME</code> مثل <code>image/png</code> و<code>image/gif</code> و<code>image/jpeg</code>.
</p>

<h3>
	الكتابة إلى متغير
</h3>

<p>
	يوجد طريقتين للكتابة إلى متغير:
</p>

<ul>
<li>
		استخدام المخزن المؤقت للخرج (OB):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_13" style="">
<span class="pln">ob_start</span><span class="pun">();</span><span class="pln"> 
</span><span class="com">// ‫تمرير null للكتابة افتراضيًا في مجرى الخرج القياسي</span><span class="pln">
imagepng</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> $quality</span><span class="pun">);</span><span class="pln"> 
$binary </span><span class="pun">=</span><span class="pln"> ob_get_clean</span><span class="pun">();</span></pre>

<ul>
<li>
		استخدام مغلِّف المجرى:
	</li>
</ul>
<p>
	قد يكون لديك سبب ما لعدم استخدام المخزن المؤقت للخرج كأن يكون لديك بالفعل مخزن مؤقت قيد التشغيل لذا تحتاج إلى بديل، يمكنك تسجيل مغلَّف مجرى جديد باستخدام الدالة <code>stream_wrapper_register</code> لذا يمكنك تمرير مجرى إلى دالة إظهار الصورة واستعادته لاحقًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_15" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">GlobalStream</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $var</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> stream_open</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $path</span><span class="pun">){</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="kwd">var</span><span class="pln"> </span><span class="pun">=&amp;</span><span class="pln"> $GLOBALS</span><span class="pun">[</span><span class="pln">parse_url</span><span class="pun">(</span><span class="pln">$path</span><span class="pun">)[</span><span class="str">"host"</span><span class="pun">]];</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> stream_write</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $data</span><span class="pun">){</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">var</span><span class="pln"> </span><span class="pun">.=</span><span class="pln"> $data</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

stream_wrapper_register</span><span class="pun">(</span><span class="str">"global"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">GlobalStream</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">

$image </span><span class="pun">=</span><span class="pln"> imagecreatetruecolor</span><span class="pun">(</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln">
imagefill</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> imagecolorallocate</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">));</span><span class="pln">

$stream </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"global://myImage"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">
imagepng</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">,</span><span class="pln"> $stream</span><span class="pun">);</span><span class="pln">
echo base64_encode</span><span class="pun">(</span><span class="pln">$myImage</span><span class="pun">);</span></pre>

<p>
	في هذا المثال يكتب الصنف <code>GlobalStream</code> أي دخل إلى المتغير المرجعي (أي الكتابة بشكل غير مباشر إلى المتغير العام للاسم المعطى)، يمكن استرجاع المتغير العام لاحقًا بشكلٍ مباشر.
</p>

<p>
	يجب الانتباه إلى عدة أمور:
</p>

<ul>
<li>
		صنف مغلِّف المجرى المنفَّذ بشكلٍ كامل يجب أن يشبه <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="https://www.php.net/manual/en/stream.streamwrapper.example-1.php" rel="external nofollow">هذا الصنف</a> لكن وفقًا للاختبارات باستخدام تابع <code>‎__call</code> السحري فإنّه من الممكن استدعاء <code>stream_open</code> و<code>stream_write</code> و<code>stream_close</code> فقط من الدوال الداخلية.
	</li>
	<li>
		لا توجد رايات مطلوبة في استدعاء <code>fopen</code> لكن يجب أن تمرر سلسلة فارغة على الأقل، لأنّ الدالة <code>fopen</code> تتوقع مثل هذا المعامل، حتى لو لم تستخدمها في تنفيذ <code>stream_open</code> يبقى هذا المعامل مطلوبًا.
	</li>
	<li>
		تستدعى الدالة <code>stream_write</code> عدة مرات وفقًا للاختبارات، تذكر أن تستخدم إسناد الدمج <code>‎.=‎</code> وليس إسناد المتغير المباشر <code>=</code>.
	</li>
</ul>
<p>
	مثال: في وسم <code>&lt;img&gt;</code> في HTML، يمكن توفير صورة بشكلٍ مباشر بدلًا من استخدام رابط خارجي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_17" style="">
<span class="pln">echo </span><span class="str">'&lt;img src="data:image/png;base64,'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> base64_encode</span><span class="pun">(</span><span class="pln">$binary</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">'"&gt;'</span><span class="pun">;</span></pre>

<h2>
	إنشاء صورة
</h2>

<p>
	نستخدم الدالة <code>imagecreatetruecolor</code> لإنشاء صورة فارغة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_19" style="">
<span class="pln">$img </span><span class="pun">=</span><span class="pln"> imagecreatetruecolor</span><span class="pun">(</span><span class="pln">$width</span><span class="pun">,</span><span class="pln"> $height</span><span class="pun">);</span></pre>

<p>
	المتغير <code>‎$img‎</code> هو متغير مورد الآن بعرض <code>‎$width</code> وطول <code>‎$height</code> بكسل، لاحظ أنّ العرض يُحسب من اليسار إلى اليمين والطول من الأعلى إلى الأسفل.
</p>

<p>
	يمكن أن يُنشأ أيضًا مورد الصورة من <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="https://www.php.net/manual/en/ref.image.php" rel="external nofollow">دوال إنشاء الصورة</a> مثل <code>imagecreatefrompng</code> و<code>imagecreatefromjpeg</code> ودوال <code>imagecreatefrom*‎</code> أخرى.
</p>

<p>
	قد تُحرَّر موارد الصورة لاحقًا عندما لا توجد مراجع إليها، لكن لتحرير الذاكرة بشكلٍ مباشر (قد يكون هذا مهمًا عند معالجة عدة صور كبيرة) يمكننا استخدام <code>imagedestroy()‎</code> على الصورة عندما لا تبقى حاجة لاستخدامها وتكون هذه ممارسة جيدة.
</p>

<pre class="ipsCode">
imagedestroy($image);
</pre>

<h3>
	تحويل صورة
</h3>

<p>
	إنّ الصور التي تُنشأ من تحويل الصور لا تعدّل الصورة حتى تُخرجها، لذا يمكن أن يكون محوِّل الصورة ببساطة عبارة عن ثلاثة أسطر من الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_22" style="">
<span class="kwd">function</span><span class="pln"> convertJpegToPng</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $filename</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $outputFile</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $im </span><span class="pun">=</span><span class="pln"> imagecreatefromjpeg</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">);</span><span class="pln">
    imagepng</span><span class="pun">(</span><span class="pln">$im</span><span class="pun">,</span><span class="pln"> $outputFile</span><span class="pun">);</span><span class="pln">
    imagedestroy</span><span class="pun">(</span><span class="pln">$im</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	اقتصاص الصورة وتغيير حجمها
</h2>

<p>
	يمكنك استخدام الدالة <code>imagecopyresampled</code> إذا كان لديك صورة وتريد إنشاء صورة جديدة بأبعاد جديدة، أنشئ أولًا صورة جديدة بالأبعاد المرغوبة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_24" style="">
<span class="com">// صورة جديدة</span><span class="pln">
$dst_img </span><span class="pun">=</span><span class="pln"> imagecreatetruecolor</span><span class="pun">(</span><span class="pln">$width</span><span class="pun">,</span><span class="pln"> $height</span><span class="pun">);</span></pre>

<p>
	خزّن الصورة الأصلية في متغير، يمكنك القيام بذلك باستخدام إحدى دوال <code>createimagefrom*‎</code> حيث يمكن أن تكون <code>*</code> هي <code>jpeg</code> أو <code>gif</code> أو<code>png</code> أو<code>string</code>، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_26" style="">
<span class="com">// الصورة الأصلية</span><span class="pln">
$src_img</span><span class="pun">=</span><span class="pln">imagecreatefromstring</span><span class="pun">(</span><span class="pln">file_get_contents</span><span class="pun">(</span><span class="pln">$original_image_path</span><span class="pun">));</span></pre>

<p>
	ثم استخدم الدالة <code>imagecopyresampled</code> لنسخ كل الصورة الأصلية (أو جزء منها) <code>(src_img)</code> إلى الصورة الجديدة <code>(dst_img)</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_28" style="">
<span class="pln">imagecopyresampled</span><span class="pun">(</span><span class="pln">$dst_img</span><span class="pun">,</span><span class="pln"> $src_img</span><span class="pun">,</span><span class="pln">
    $dst_x </span><span class="pun">,</span><span class="pln">$dst_y</span><span class="pun">,</span><span class="pln"> $src_x</span><span class="pun">,</span><span class="pln"> $src_y</span><span class="pun">,</span><span class="pln">
    $dst_width</span><span class="pun">,</span><span class="pln"> $dst_height</span><span class="pun">,</span><span class="pln"> $src_width</span><span class="pun">,</span><span class="pln"> $src_height</span><span class="pun">);</span></pre>

<p>
	لضبط أبعاد <code>src_*‎</code> و<code>‎dst_*‎</code>، استخدم الصورة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="60956" data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="https://academy.hsoub.com/uploads/monthly_2021_03/01.jpg.72555703933692e961cc9370a0f510ac.jpg" rel=""><img alt="01.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="60956" data-unique="qzh83l27d" src="https://academy.hsoub.com/uploads/monthly_2021_03/01.thumb.jpg.b349ffa1b520e56e189983beba526aaa.jpg"></a>
</p>

<p>
	إذا كنت تريد الآن نسخ كامل الصورة المصدر (الأصلية) إلى كامل منطقة الهدف (بدون اقتصاص):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_30" style="">
<span class="pln">$src_x </span><span class="pun">=</span><span class="pln"> $src_y </span><span class="pun">=</span><span class="pln"> $dst_x </span><span class="pun">=</span><span class="pln"> $dst_y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

</span><span class="com">// عرض الصورة الجديدة</span><span class="pln">
$dst_width </span><span class="pun">=</span><span class="pln"> $width</span><span class="pun">;</span><span class="pln">

</span><span class="com">// طول الصورة الجديدة</span><span class="pln">
$dst_height </span><span class="pun">=</span><span class="pln"> $height</span><span class="pun">;</span><span class="pln">

</span><span class="com">// عرض الصورة الأصلية</span><span class="pln">
$src_width </span><span class="pun">=</span><span class="pln"> imagesx</span><span class="pun">(</span><span class="pln">$src_img</span><span class="pun">);</span><span class="pln">

</span><span class="com">// طول الصورة الأصلية</span><span class="pln">
$src_height </span><span class="pun">=</span><span class="pln"> imagesy</span><span class="pun">(</span><span class="pln">$src_img</span><span class="pun">);</span></pre>

<h2>
	مكتبة Imagick
</h2>

<h3>
	التثبيت
</h3>

<ul>
<li>
		باستخدام <code>apt</code> في الأنظمة المعتمدة على Debian:
	</li>
</ul>
<pre class="ipsCode">
sudo apt-get install php5-imagick
</pre>

<ul>
<li>
		باستخدام <code>Homebrew</code> في أنظمة <code>OSX/macOs</code>:
	</li>
</ul>
<pre class="ipsCode">
brew install imagemagick
</pre>

<ul>
<li>
		باستخدام الإصدارات الثنائية: التعليمات في <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="%E2%80%8Fhttps://www.imagemagick.org/script/download.php#macosx%E2%80%8F" rel="">موقع imagemagick</a>.
	</li>
</ul>
<h3>
	الاستخدام
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_32" style="">
<span class="pun">&lt;?</span><span class="pln">php
$imagen </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Imagick</span><span class="pun">(</span><span class="str">'imagen.jpg'</span><span class="pun">);</span><span class="pln">
</span><span class="com">// ‫إذا وضعت قيمة المعامل 0 ستتم المحافظة على نسبة العرض</span><span class="pln">
$imagen</span><span class="pun">-&gt;</span><span class="pln">thumbnailImage</span><span class="pun">(</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">

echo $imagen</span><span class="pun">;</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h3>
	تحويل صورة إلى سلسلة نصية بالأساس 64
</h3>

<p>
	يُظهر هذا المثال كيفية تحويل صورة إلى سلسلة نصية بالأساس 64 (أي سلسلة نصية يمكنك استخدامها مباشرةً في السمة <code>src</code> لوسم <code>img</code>)، يستخدم هذا المثال مكتبة <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="%E2%80%8Fhttps://www.php.net/manual/en/intro.imagick.php%E2%80%8F" rel="">Imagick</a> لكن يمكن استخدام مكتبات أخرى مثل <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="%E2%80%8Fhttps://www.php.net/manual/en/intro.image.php" rel="">GD</a>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3990_34" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// (1)</span><span class="pln">
$img </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Imagick</span><span class="pun">(</span><span class="str">'image.jpg'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// (2)</span><span class="pln">
$img</span><span class="pun">-&gt;</span><span class="pln">resizeImage</span><span class="pun">(</span><span class="lit">320</span><span class="pun">,</span><span class="pln"> </span><span class="lit">240</span><span class="pun">);</span><span class="pln">

</span><span class="com">// (3)</span><span class="pln">
$imgBuff </span><span class="pun">=</span><span class="pln"> $img</span><span class="pun">-&gt;</span><span class="pln">getimageblob</span><span class="pun">();</span><span class="pln">

</span><span class="com">// (4)</span><span class="pln">
$img</span><span class="pun">-&gt;</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">

</span><span class="com">// (5)</span><span class="pln">
$img </span><span class="pun">=</span><span class="pln"> base64_encode</span><span class="pun">(</span><span class="pln">$imgBuff</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">"&lt;img alt='Embedded Image' src='data:image/jpeg;base64,$img' /&gt;"</span><span class="pun">;</span></pre>

<p>
	في الموضع (1) يُحمَّل الملف <code>image.jpg</code> للمعالجة، مسار الملف نسبي إلى ملف <code>‎.php‎</code> المتضمن هذه الشيفرة لذا في هذا المثال يجب أن يكون ملف <code>image.jpg</code> في نفس مجلد السكربت.
</p>

<p>
	في الموضع (2) يتغير حجم الصورة للحجم المُعطى كطول وعرض وإذا أردت تغيير دقة الصورة أيضًا مع تغيير الحجم يمكنك استخدام الدالة <code>‎$img-&gt;resampleimage(320, 240)‎</code>، لاحظ أنّه يمكنك ضبط المعامل الثاني إلى 0 للمحافظة على نسبة عرض الصورة.
</p>

<p>
	في الموضع (3) تُرجع الدالة تمثيل الصورة على شكل سلسلة نصية غير مشفرة.
</p>

<p>
	في الموضع (4) يُزال المورد <code>image.jpg</code> من الكائن <code>‎$img‎</code> ويُدمَّر الكائن مما يحرر موارد النظام المحجوزة لمعالجة الصورة.
</p>

<p>
	في الموضع (5) تُنشأ نسخة بتشفير الأساس 64 من السلسلة النصية السابقة غير المشفرة ثم تُعرَض كصورة في الصفحة، لاحظ أنّه قد يتغير الجزء <code>image/jpeg</code> في السمة <code>src</code> وذلك بالاعتماد على نوع الصورة التي تستخدمها (png أوjpeg مثلًا).
</p>

<p>
	ترجمة -وبتصرف- للفصول [Image Processing with GD - Imagick] من كتاب <a data-ss1616975446="1" data-ss1616975645="1" data-ss1616975689="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-machine-learning-%D9%81%D9%8A-php-r1179/" rel="">مدخل إلى تعلم الآلة (Machine learning) في PHP </a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%88%D8%A7%D8%B6%D9%8A%D8%B9-%D9%85%D8%AA%D9%81%D8%B1%D9%82%D8%A9-%D9%85%D9%87%D9%85%D8%A9-%D9%84%D9%83%D9%84-%D9%85%D8%A8%D8%B1%D9%85%D8%AC-php-r1177/" rel="">اصطلاحات ومواضيع متفرقة مهمة لكل مبرمج PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1178</guid><pubDate>Tue, 30 Mar 2021 13:02:00 +0000</pubDate></item><item><title>&#x627;&#x635;&#x637;&#x644;&#x627;&#x62D;&#x627;&#x62A; &#x648;&#x645;&#x648;&#x627;&#x636;&#x64A;&#x639; &#x645;&#x62A;&#x641;&#x631;&#x642;&#x629; &#x645;&#x647;&#x645;&#x629; &#x644;&#x643;&#x644; &#x645;&#x628;&#x631;&#x645;&#x62C; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%88%D8%A7%D8%B6%D9%8A%D8%B9-%D9%85%D8%AA%D9%81%D8%B1%D9%82%D8%A9-%D9%85%D9%87%D9%85%D8%A9-%D9%84%D9%83%D9%84-%D9%85%D8%A8%D8%B1%D9%85%D8%AC-php-r1177/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/5.png.08bad1909bb092c15ff47a4f0db137ea.png" /></p>

<h2>
	وسوم PHP
</h2>

<p>
	يجب أن تستخدم دائمًا الوسوم <code>‎&lt;?php ?&gt;‎</code> أو وسوم الطباعة القصيرة <code>‎&lt;?= ?&gt;‎</code>، ويجب ألا تُستخدم الاختلافات الأخرى (خاصةً الوسوم القصيرة <code>&lt;? ?&gt;</code>) لأنّ مديري النظام يعطلونها عادةً.
</p>

<p>
	يجب تجاهل صيغة الإغلاق <code>‎?&gt;‎</code> عندما لا نتوقع أن ينتج الملف خرجًا لتجنب الخرج غير المقصود الذي يمكن أن يسبب مشاكل عندما يحلل العميل الملف خاصةً أنّ بعض المتصفحات تفشل في التعرف على وسم <code>‎&lt;!DOCTYPE</code> وتنشّط نمط التجاوزات <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://en.wikipedia.org/wiki/Quirks_mode" rel="">Quirks Mode</a>.
</p>

<p>
	مثال عن سكربت PHP بسيط:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_7" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Hello World"</span><span class="pun">;</span></pre>

<p>
	مثال عن ملف تعريف صنف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_9" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال عن PHP مضمن في HTML:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_11" style="">
<span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"nav"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="pun">&lt;?</span><span class="pln">php </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$navItems </span><span class="kwd">as</span><span class="pln"> $navItem</span><span class="pun">):</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
        </span><span class="tag">&lt;li&gt;</span><span class="pln">&lt;a href="</span><span class="pun">&lt;?=</span><span class="pln"> htmlspecialchars</span><span class="pun">(</span><span class="pln">$navItem</span><span class="pun">-&gt;</span><span class="pln">url</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">"&gt;
            </span><span class="pun">&lt;?=</span><span class="pln"> htmlspecialchars</span><span class="pun">(</span><span class="pln">$navItem</span><span class="pun">-&gt;</span><span class="pln">label</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
        </span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
    </span><span class="pun">&lt;?</span><span class="pln">php endforeach</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;/ul&gt;</span></pre>

<h2>
	فوائد المولّدات (Generators)
</h2>

<p>
	تقدّم <a href="https://wiki.hsoub.com/PHP" rel="external">PHP </a>5.5 المولّدات والكلمة المفتاحية <code>yield</code> التي تسمح لنا بكتابة شيفرة غير متزامنة تبدو أشبه بالشيفرة المتزامنة، يعدّ التعبير <code>yield</code> مسؤولًا عن إعادة التحكم إلى الشيفرة المستدعاة وتوفير نقطة استئناف من هناك، يمكنك إرسال قيمة مع تعليمة <code>yield</code>، القيمة المرجعة من هذا التعبير إما <code>null</code> أو القيمة الممررة إلى <code>Generator::send()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_13" style="">
<span class="kwd">function</span><span class="pln"> reverse_range</span><span class="pun">(</span><span class="pln">$i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫مجرد وجود الكلمة المفتاحية `yield` في هذه الدالة يجعلها مولّد</span><span class="pln">
    </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‎$i‎ هي القيمة المُحتفظ بها بين الاستئنافات</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="kwd">yield</span><span class="pln"> $i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(--</span><span class="pln">$i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$gen </span><span class="pun">=</span><span class="pln"> reverse_range</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> $gen</span><span class="pun">-&gt;</span><span class="pln">current</span><span class="pun">();</span><span class="pln">

</span><span class="com">// الإرسال أيضًا يستأنف المولِّد</span><span class="pln">
$gen</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">(</span><span class="str">"injected!"</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$gen </span><span class="kwd">as</span><span class="pln"> $val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// المرور على كامل محتويات المولّد مما يجعله يستأنف عند كل تكرار</span><span class="pln">
    echo $val</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// 5injected!4321</span></pre>

<p>
	يمكن استخدام هذه الآلية بتنفيذ نمط مشترك (coroutine) لانتظار كائنات <code>Awaitable</code> المُعادة من المولِّد (بتسجيل المولّد نفسه كرد نداء للحل) ومواصلة تنفيذ المولّد بمجرد إنهاء كائن <code>Awaitable</code>.
</p>

<h2>
	استخدام حلقة حدث من مكتبة Icicle
</h2>

<p>
	تستخدم مكتبة <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://github.com/icicleio/icicle" rel="">Icicle</a> كائنات <code>Awaitable</code> ومولّدات لإنشاء نمط مشترك.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_15" style="">
<span class="kwd">require</span><span class="pln"> __DIR__ </span><span class="pun">.</span><span class="pln"> </span><span class="str">'/vendor/autoload.php'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Icicle</span><span class="pln">\Awaitable</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Icicle</span><span class="pln">\Coroutine\Coroutine</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Icicle</span><span class="pln">\Loop</span><span class="pun">;</span><span class="pln">

$generator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">float</span><span class="pln"> $time</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫ضبط المتغير ‎$start إلى القيمة المعادة من الدالة microtime()‎? بعد ‎$time ثانية تقريبًا</span><span class="pln">
        $start </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">yield</span><span class="pln"> </span><span class="typ">Awaitable</span><span class="pln">\resolve</span><span class="pun">(</span><span class="pln">microtime</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">))-&gt;</span><span class="pln">delay</span><span class="pun">(</span><span class="pln">$time</span><span class="pun">);</span><span class="pln">
        echo </span><span class="str">"Sleep time: "</span><span class="pun">,</span><span class="pln"> microtime</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> $start</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// ‫رمي استثناء من كائن Awaitable المرفوض إلى النمط المشترك</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">yield</span><span class="pln"> </span><span class="typ">Awaitable</span><span class="pln">\reject</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">'Rejected awaitable'</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Throwable</span><span class="pln"> $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫التقاط سبب رفض awaitable</span><span class="pln">
        echo </span><span class="str">"Caught exception: "</span><span class="pun">,</span><span class="pln"> $e</span><span class="pun">-&gt;</span><span class="pln">getMessage</span><span class="pun">(),</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">yield</span><span class="pln"> </span><span class="typ">Awaitable</span><span class="pln">\resolve</span><span class="pun">(</span><span class="str">'Coroutine completed'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// يبقى النمط المشترك ساكنًا لمدة 1.2 ثانية ثم ينتهي معيدًا سلسلة نصية</span><span class="pln">
$coroutine </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Coroutine</span><span class="pun">(</span><span class="pln">$generator</span><span class="pun">(</span><span class="lit">1.2</span><span class="pun">));</span><span class="pln">
$coroutine</span><span class="pun">-&gt;</span><span class="kwd">done</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $data</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="typ">Loop</span><span class="pln">\run</span><span class="pun">();</span></pre>

<h2>
	إنتاج عمليات غير معطَّلة مع proc_open()‎
</h2>

<p>
	لا تدعم PHP تنفيذ الشيفرة بشكلٍ متزامن إلا إذا ثبَّت الإضافات مثل <code>pthread</code>، يمكن تجاوز هذا أحيانًا باستخدام الدوال <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.proc-open.php" rel=""><code>proc_open()‎</code></a> و<a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.stream-set-blocking.php" rel=""><code>stream_set_blocking()‎</code></a>­ وقراءة خرجهم بشكلٍ غير متزامن.
</p>

<p>
	يمكننا تنفيذ الشيفرة كعمليات فرعية متعددة إذا قسمناها إلى أجزاء أصغر، ثمّ يمكننا جعل كل عملية فرعية غير معطَّلة باستخدام دالة <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.stream-set-blocking.php" rel=""><code>stream_set_blocking()‎</code></a> أي أنّه يمكننا إنتاج عدة عمليات فرعية ثم التحقق من خرجها في حلقة (بشكل مشابه لحلقة حدث) والانتظار حتى تنتهي جميعها.
</p>

<p>
	يمكن أن يكون لدينا مثلًا عملية فرعية صغيرة تنفّذ حلقة وتتوقف في كل تكرار بشكلٍ عشوائي لمدة 100- 1000 ميلي ثانية (لاحظ أنّ التأخير هو نفسه لكل عملية فرعية).
</p>

<pre class="ipsCode">
&lt;?php
// subprocess.php
$name = $argv[1];
$delay = rand(1, 10) * 100;
printf("$name delay: ${delay}ms\n");

for ($i = 0; $i &lt; 5; $i++) {
    usleep($delay * 1000);
    printf("$name: $i\n");
}
</pre>

<p>
	ثم ستنتج العملية الرئيسية عمليات فرعية وتقرأ خرجها، ويمكننا تقسيمه إلى كتل أصغر:
</p>

<ul>
<li>
		إنتاج عمليات فرعية باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttp://php.net/manual/en/function.proc-open.php" rel=""><code>proc_open()‎</code></a>.
	</li>
	<li>
		جعل كل عملية فرعية غير معطَّلة باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttp://php.net/manual/en/function.stream-set-blocking.php%E2%80%8F" rel=""><code>stream_set_blocking()‎</code></a>.
	</li>
	<li>
		تنفيذ حلقة حتى تنتهي كل العمليات الفرعية باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.proc-get-status.php" rel=""><code>proc_get_status()‎</code></a>.
	</li>
	<li>
		إغلاق مقابض الملف بشكل صحيح مع أنبوب الخرج لكل عملية فرعية باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.fclose.php" rel=""><code>fclose()‎</code></a> وإغلاق مقابض العملية باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.proc-close.php" rel=""><code>proc_close()‎</code></a>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_17" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// non-blocking-proc_open.php</span><span class="pln">
</span><span class="com">// واصفات الملف لكل عملية فرعية</span><span class="pln">
$descriptors </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="pun">᠎᠎</span><span class="lit">0</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'pipe'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'r'</span><span class="pun">],</span><span class="pln"> </span><span class="com">// stdin</span><span class="pln">
    </span><span class="lit">1</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'pipe'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">],</span><span class="pln"> </span><span class="com">// stdout</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

$pipes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
$processes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إنتاج عملية فرعية</span><span class="pln">
    $proc </span><span class="pun">=</span><span class="pln"> proc_open</span><span class="pun">(</span><span class="str">'php subprocess.php proc'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $i</span><span class="pun">,</span><span class="pln"> $descriptors</span><span class="pun">,</span><span class="pln"> $procPipes</span><span class="pun">);</span><span class="pln">
    $processes</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $proc</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// جعل العملية الفرعية غير معطَّلة (أنبوب الخرج فقط)</span><span class="pln">
    stream_set_blocking</span><span class="pun">(</span><span class="pln">$procPipes</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    $pipes</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $procPipes</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// تنفيذ حلقة حتى تنتهي كل العمليات الفرعية</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">array_filter</span><span class="pun">(</span><span class="pln">$processes</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$proc</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> proc_get_status</span><span class="pun">(</span><span class="pln">$proc</span><span class="pun">)[</span><span class="str">'running'</span><span class="pun">];</span><span class="pln"> </span><span class="pun">}))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        usleep</span><span class="pun">(</span><span class="lit">10</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 100ms</span><span class="pln">
        </span><span class="com">// ‫قراءة كل الخرج الممكن (الخرج غير المقروء يُخزَّن مؤقتًا)</span><span class="pln">
        $str </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">(</span><span class="pln">$pipes</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="lit">1024</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            printf</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// إغلاق كل الأنابيب والعمليات</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    fclose</span><span class="pun">(</span><span class="pln">$pipes</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">
    proc_close</span><span class="pun">(</span><span class="pln">$processes</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يحتوي الخرج على مزيج من العمليات الفرعية الثلاث بما أننا نقرأها باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/fread" rel=""><code>fread()‎</code></a>، لاحظ أنّه في المثال انتهت العملية <code>proc1</code> قبل العمليتين الباقيتين بكثير.
</p>

<pre class="ipsCode">
$ php non-blocking-proc_open.php
proc1 delay: 200ms
proc2 delay: 1000ms
proc3 delay: 800ms
proc1: 0
proc1: 1
proc1: 2
proc1: 3
proc3: 0
proc1: 4
proc2: 0
proc3: 1
proc2: 1
proc3: 2
proc2: 2
proc3: 3
proc2: 3
proc3: 4
proc2: 4
</pre>

<h2>
	قراءة منفذ تسلسلي مع إضافة حدث ودخل/خرج مباشر
</h2>

<p>
	إنّ مجاري الدخل والخرج المباشرة (DIO) غير معروفة الآن من قِبل الإضافة حدث <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/book.event.php" rel="">Event</a>، فلا توجد طريقة نظيفة للحصول على واصف الملف مغلفًا ضمن موارد الدخل والخرج المباشرة، إلا أنّ هناك حل بديل:
</p>

<ul>
<li>
		فتح مجرى للمنفذ باستخدام <code>fopen()‎</code>.
	</li>
	<li>
		جعل المجرى غير معطّل باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.stream-set-blocking.php" rel=""><code>stream_set_blocking();‎</code></a>.
	</li>
	<li>
		الحصول على واصف ملف رقمي من المجرى باستخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.stream-set-blocking.php" rel=""><code>EventUtil::getSocketFd();‎</code></a>.
	</li>
	<li>
		تمرير واصف الملف الرقمي إلى الدالة <code>dio_fdopen()‎</code> والحصول على مورد دخل/خرج مباشر.
	</li>
	<li>
		إضافة حدث مع رد نداء للتنصت على الأحداث المقروءة على واصف الملف.
	</li>
	<li>
		تُصرَف البيانات المتاحة في رد النداء وتُعالج وفقًا لمنطق تطبيقك.
	</li>
</ul>
<p>
	الملف <code>dio.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_19" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Scanner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫مسار المنفذ مثل  ‎/dev/pts/5</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $port</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// واصف الملف الرقمي</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $fd</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// EventBase</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $base</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// مورد دخل/خرج مباشر </span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $dio</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// حدث</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $e_open</span><span class="pun">;</span><span class="pln"> 
    </span><span class="com">// حدث</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $e_read</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct </span><span class="pun">(</span><span class="pln">$port</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">port </span><span class="pun">=</span><span class="pln"> $port</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EventBase</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __destruct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">-&gt;</span><span class="kwd">exit</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">e_open</span><span class="pun">)</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">e_open</span><span class="pun">-&gt;</span><span class="pln">free</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">e_read</span><span class="pun">)</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">e_read</span><span class="pun">-&gt;</span><span class="pln">free</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">dio</span><span class="pun">)</span><span class="pln">
            dio_close</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">dio</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $stream </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">port</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rb'</span><span class="pun">);</span><span class="pln">
        stream_set_blocking</span><span class="pun">(</span><span class="pln">$stream</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">fd </span><span class="pun">=</span><span class="pln"> </span><span class="typ">EventUtil</span><span class="pun">::</span><span class="pln">getSocketFd</span><span class="pun">(</span><span class="pln">$stream</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">fd </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            fprintf</span><span class="pun">(</span><span class="pln">STDERR</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Failed attach to port, events: %d\n"</span><span class="pun">,</span><span class="pln"> $events</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">e_open </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Event</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">fd</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Event</span><span class="pun">::</span><span class="pln">WRITE</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'_onOpen'</span><span class="pun">]);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">e_open</span><span class="pun">-&gt;</span><span class="pln">add</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">-&gt;</span><span class="pln">dispatch</span><span class="pun">();</span><span class="pln">
        fclose</span><span class="pun">(</span><span class="pln">$stream</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> _onOpen</span><span class="pun">(</span><span class="pln">$fd</span><span class="pun">,</span><span class="pln"> $events</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">e_open</span><span class="pun">-&gt;</span><span class="kwd">del</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">dio </span><span class="pun">=</span><span class="pln"> dio_fdopen</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">fd</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// استدعاء دوال دخل/خرج مباشر هنا</span><span class="pln">
        dio_tcsetattr</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">dio</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            </span><span class="str">'baud'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">9600</span><span class="pun">,</span><span class="pln">
            </span><span class="str">'bits'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln">
            </span><span class="str">'stop'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
            </span><span class="str">'parity'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="pun">]);</span><span class="pln">

        $this</span><span class="pun">-&gt;</span><span class="pln">e_read </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Event</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">fd</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Event</span><span class="pun">::</span><span class="pln">READ </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Event</span><span class="pun">::</span><span class="pln">PERSIST</span><span class="pun">,</span><span class="pln">
        </span><span class="pun">[</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'_onRead'</span><span class="pun">]);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">e_read</span><span class="pun">-&gt;</span><span class="pln">add</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> _onRead</span><span class="pun">(</span><span class="pln">$fd</span><span class="pun">,</span><span class="pln"> $events</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$data </span><span class="pun">=</span><span class="pln"> dio_read</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">dio</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            var_dump</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="com">// تغيير وسيط المنفذ</span><span class="pln">
$scanner </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Scanner</span><span class="pun">(</span><span class="str">'/dev/pts/5'</span><span class="pun">);</span><span class="pln">
$scanner</span><span class="pun">-&gt;</span><span class="pln">run</span><span class="pun">();</span></pre>

<p>
	الاختبار: نفّذ التعليمة التالية في الطرفية A:
</p>

<pre class="ipsCode">
$ socat -d -d pty,raw,echo=0 pty,raw,echo=0
2016/12/01 18:04:06 socat[16750] N PTY is /dev/pts/5
2016/12/01 18:04:06 socat[16750] N PTY is /dev/pts/8
2016/12/01 18:04:06 socat[16750] N starting data transfer loop with FDs [5,5] and [7,7]
</pre>

<p>
	قد يختلف الخرج، استخدم الطرفيات الزائفة من أول سطرين (<code>‎/dev/pts/5‎</code> و<code>‎/dev/pts/8</code> بالتحديد).
</p>

<p>
	نفّذ في الطرفية B السكربت السابق، قد تحتاج إلى صلاحيات الجذر:
</p>

<pre class="ipsCode">
$ sudo php dio.php
</pre>

<p>
	أرسل من الطرفية C سلسلة نصية إلى الطرفية الزائفة الأولى:
</p>

<pre class="ipsCode">
$ echo test &gt; /dev/pts/8
</pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(1) "t"
string(1) "e"
string(1) "s"
string(1) "t"
string(1) "
"
</pre>

<h2>
	عميل HTTP بالاعتماد على الإضافة Event
</h2>

<p>
	إليك مثال عن صنف عميل HTTP بالاعتماد على الإضافة <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://pecl.php.net/package/event%E2%80%8F" rel="">Event</a>، يسمح هذا الصنف بجدولة عدد من طلبات HTTP ثم تنفيذها بشكلٍ غير متزامن.
</p>

<p>
	ملف <code>http-client.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_21" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyHttpClient</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫متغير من الصنف EventBase</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $base</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// مصفوفة كائنات من الصنف EventHttpConnection</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $connections </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EventBase</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫دالة لإرسال كل الطلبات المعلقة (أحداث)، تُرجع void</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">-&gt;</span><span class="pln">dispatch</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __destruct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫تدمير كائنات الاتصال بشكلٍ صريح، لا تنتظر كانس المهملات (GC) وإلا قد يتحرر كائن EventBase باكرًا</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">connections </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// (1)</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> addRequest</span><span class="pun">(</span><span class="pln">$address</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">,</span><span class="pln"> array $headers</span><span class="pun">,</span><span class="pln">
$cmd </span><span class="pun">=</span><span class="pln"> </span><span class="typ">EventHttpRequest</span><span class="pun">::</span><span class="pln">CMD_GET</span><span class="pun">,</span><span class="pln"> $resource </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/'</span><span class="pun">){</span><span class="pln">
        $conn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EventHttpConnection</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">);</span><span class="pln">
        $conn</span><span class="pun">-&gt;</span><span class="pln">setTimeout</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
        $req </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EventHttpRequest</span><span class="pun">([</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'_requestHandler'</span><span class="pun">],</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="kwd">base</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$headers </span><span class="kwd">as</span><span class="pln"> $k </span><span class="pun">=&gt;</span><span class="pln"> $v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $req</span><span class="pun">-&gt;</span><span class="pln">addHeader</span><span class="pun">(</span><span class="pln">$k</span><span class="pun">,</span><span class="pln"> $v</span><span class="pun">,</span><span class="pln"> </span><span class="typ">EventHttpRequest</span><span class="pun">::</span><span class="pln">OUTPUT_HEADER</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        $req</span><span class="pun">-&gt;</span><span class="pln">addHeader</span><span class="pun">(</span><span class="str">'Host'</span><span class="pun">,</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln"> </span><span class="typ">EventHttpRequest</span><span class="pun">::</span><span class="pln">OUTPUT_HEADER</span><span class="pun">);</span><span class="pln">
        $req</span><span class="pun">-&gt;</span><span class="pln">addHeader</span><span class="pun">(</span><span class="str">'Connection'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'close'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">EventHttpRequest</span><span class="pun">::</span><span class="pln">OUTPUT_HEADER</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">-&gt;</span><span class="pln">makeRequest</span><span class="pun">(</span><span class="pln">$req</span><span class="pun">,</span><span class="pln"> $cmd</span><span class="pun">,</span><span class="pln"> $resource</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">connections </span><span class="pun">[]=</span><span class="pln"> $conn</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> $req</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// (2)</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> _requestHandler</span><span class="pun">(</span><span class="pln">$req</span><span class="pun">,</span><span class="pln"> $unused</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_null</span><span class="pun">(</span><span class="pln">$req</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            echo </span><span class="str">"Timed out\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $response_code </span><span class="pun">=</span><span class="pln"> $req</span><span class="pun">-&gt;</span><span class="pln">getResponseCode</span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$response_code </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                echo </span><span class="str">"Connection refused\n"</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln"> elseif </span><span class="pun">(</span><span class="pln">$response_code </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                echo </span><span class="str">"Unexpected response: $response_code\n"</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                echo </span><span class="str">"Success: $response_code\n"</span><span class="pun">;</span><span class="pln">
                $buf </span><span class="pun">=</span><span class="pln"> $req</span><span class="pun">-&gt;</span><span class="pln">getInputBuffer</span><span class="pun">();</span><span class="pln">
                echo </span><span class="str">"Body:\n"</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$s </span><span class="pun">=</span><span class="pln"> $buf</span><span class="pun">-&gt;</span><span class="pln">readLine</span><span class="pun">(</span><span class="typ">EventBuffer</span><span class="pun">::</span><span class="pln">EOL_ANY</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                    echo $s</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$address </span><span class="pun">=</span><span class="pln"> </span><span class="str">"my-host.local"</span><span class="pun">;</span><span class="pln">
$port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pun">;</span><span class="pln">
$headers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="str">'User-Agent'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My-User-Agent/1.0'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">];</span><span class="pln">

$client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyHttpClient</span><span class="pun">();</span><span class="pln">

</span><span class="com">// إضافة طلبات معلقة</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $client</span><span class="pun">-&gt;</span><span class="pln">addRequest</span><span class="pun">(</span><span class="pln">$address</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">,</span><span class="pln"> $headers</span><span class="pun">,</span><span class="pln">
</span><span class="typ">EventHttpRequest</span><span class="pun">::</span><span class="pln">CMD_GET</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/test.php?a='</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $i</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// إرسال طلبات معلقة</span><span class="pln">
$client</span><span class="pun">-&gt;</span><span class="pln">run</span><span class="pun">();</span></pre>

<p>
	في الموضع (1) نضيف طلب HTTP معلق، معاملاته هي:
</p>

<ul>
<li>
		‎$address: اسم المضيف أو IP، سلسلة نصية.
	</li>
	<li>
		‎$port: رقم المنفذ، عدد صحيح.
	</li>
	<li>
		‎$headers: ترويسات HTTP إضافية، مصفوفة.
	</li>
	<li>
		‎$cmd: ثابت <code>EventHttpRequest::CMD_*‎</code>، عدد صحيح.
	</li>
	<li>
		‎$resource: مورد طلب HTTP مثل '‎/page?a=b&amp;c=d'، سلسلة نصية. القيمة المعادة إما <code>EventHttpRequest</code> أو <code>false</code>.
	</li>
</ul>
<p>
	في الموضع (2) نضيف دالة لمعالجة طلب HTTP، معاملاتها:
</p>

<ul>
<li>
		‎$req، كائن من الصنف <code>EventHttpRequest</code>.
	</li>
	<li>
		‎$unused، خليط من المعاملات.
	</li>
</ul>
<p>
	تعيد هذه الدالة <code>void</code>.
</p>

<p>
	الملف <code>test.php</code>، مثال عن سكربت من جهة الخادم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_23" style="">
<span class="pun">&lt;?</span><span class="pln">php
echo </span><span class="str">'GET: '</span><span class="pun">,</span><span class="pln"> var_export</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln"> PHP_EOL</span><span class="pun">;</span><span class="pln">
echo </span><span class="str">'User-Agent: '</span><span class="pun">,</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'HTTP_USER_AGENT'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="str">'(none)'</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">;</span></pre>

<p>
	الاستخدام:
</p>

<pre class="ipsCode">
php http-client.php
</pre>

<p>
	مثال عن الخرج:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_25" style="">
<span class="typ">Success</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200</span><span class="pln">
</span><span class="typ">Body</span><span class="pun">:</span><span class="pln">
GET</span><span class="pun">:</span><span class="pln"> array </span><span class="pun">(</span><span class="pln">
    </span><span class="str">'a'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">)</span><span class="pln">
</span><span class="typ">User</span><span class="pun">-</span><span class="typ">Agent</span><span class="pun">:</span><span class="pln"> </span><span class="typ">My</span><span class="pun">-</span><span class="typ">User</span><span class="pun">-</span><span class="typ">Agent</span><span class="pun">/</span><span class="lit">1.0</span><span class="pln">
</span><span class="typ">Success</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200</span><span class="pln">
</span><span class="typ">Body</span><span class="pun">:</span><span class="pln">
GET</span><span class="pun">:</span><span class="pln"> array </span><span class="pun">(</span><span class="pln">
    </span><span class="str">'a'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'0'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">)</span><span class="pln">
</span><span class="typ">User</span><span class="pun">-</span><span class="typ">Agent</span><span class="pun">:</span><span class="pln"> </span><span class="typ">My</span><span class="pun">-</span><span class="typ">User</span><span class="pun">-</span><span class="typ">Agent</span><span class="pun">/</span><span class="lit">1.0</span><span class="pln">
</span><span class="typ">Success</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200</span><span class="pln">
</span><span class="typ">Body</span><span class="pun">:</span><span class="pln">
GET</span><span class="pun">:</span><span class="pln"> array </span><span class="pun">(</span><span class="pln">
    </span><span class="str">'a'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'3'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="com">// الخرج مختصر</span></pre>

<p>
	لاحظ أنّ الشيفرة صُممت للمعالجة طويلة الأمد في <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://www.php.net/manual/en/features.commandline.introduction.php" rel="">CLI SAPI</a>.
</p>

<h2>
	عميل HTTP بالاعتماد على الإضافة Ev
</h2>

<p>
	إليك مثال عن صنف عميل HTTP بالاعتماد على الإضافة <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://pecl.php.net/package/ev" rel="">Ev</a>.
</p>

<p>
	تنفذ الإضافة Ev حدث حلقة بسيط لكن قوي للأغراض العامة، إنّها لا توفر مراقبين خاصين للشبكة لكن يمكن استخدام <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttp://docs.php.net/manual/en/class.evio.php" rel="">I/O watcher</a> الخاص بالإضافة للمعالجة غير المتزامنة <a data-ss1616974531="1" data-ss1616975023="1" href="http://docs.php.net/manual/en/class.evio.php" rel="external nofollow">للمقابس</a>.
</p>

<p>
	تظهر الشيفرة التالية كيف يمكن جدولة طلبات HTTP للمعالجة التفرعية.
</p>

<p>
	ملف <code>http-client.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_27" style="">
<span class="pun">&lt;?</span><span class="pln">php
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyHttpRequest</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫كائن من الصنف MyHttpClient</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $http_client</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// سلسلة نصية</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $address</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫مورد HTTP من النوع سلسلة نصية مثل ‎/page?get=param</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $resource</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫طريقة HTTP من النوع سلسلة نصية مثل GET، ‏POST </span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $method</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// عدد صحيح</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $service_port</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// مقبس مورد</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $socket</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// مهلة الاتصال بالثانية من النوع عدد عشري </span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $timeout </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10.</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫حجم كل جزء للدالة socket_recv()‎ بالبايتات من النوع عدد صحيح</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $chunk_size </span><span class="pun">=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">?</span><span class="com">// ‫كائن من الصنف EvTimer</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $timeout_watcher</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫كائن من الصنف EvIo</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $write_watcher</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫كائن من الصنف EvIo</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $read_watcher</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫كائن من الصنف EvTimer</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $conn_watcher</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// مخزن مؤقت للبيانات القادمة من النوع سلسلة نصية</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $buffer</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// الأخطاء التي أخبرت عنها إضافة المقابس في وضع عدم التعطيل من النوع مصفوفة</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> $e_nonblocking </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="com">// ‫عُطِّلت العملية لكن وُضع واصف الملف في وضع عدم التعطيل (EAGAIN أو EWOULDBLOCK)</span><span class="pln">
        </span><span class="lit">11</span><span class="pun">,</span><span class="pln"> 
        </span><span class="com">// ‫العملية الحالية قيد التقدم (EINPROGRESS)</span><span class="pln">
        </span><span class="lit">115</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

    </span><span class="com">// (1)</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">MyHttpClient</span><span class="pln"> $client</span><span class="pun">,</span><span class="pln"> $host</span><span class="pun">,</span><span class="pln"> $resource</span><span class="pun">,</span><span class="pln"> $method</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">http_client </span><span class="pun">=</span><span class="pln"> $client</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">host </span><span class="pun">=</span><span class="pln"> $host</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">resource </span><span class="pun">=</span><span class="pln"> $resource</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">method </span><span class="pun">=</span><span class="pln"> $method</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// ‫الحصول على المنفذ من خدمة WWW</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">service_port </span><span class="pun">=</span><span class="pln"> getservbyname</span><span class="pun">(</span><span class="str">'www'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tcp'</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// ‫الحصول على عنوان IP للمضيف الهدف</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">address </span><span class="pun">=</span><span class="pln"> gethostbyname</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">host</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// ‫إنشاء مقبس TCP/IP</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">socket </span><span class="pun">=</span><span class="pln"> socket_create</span><span class="pun">(</span><span class="pln">AF_INET</span><span class="pun">,</span><span class="pln"> SOCK_STREAM</span><span class="pun">,</span><span class="pln"> SOL_TCP</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RuntimeException</span><span class="pun">(</span><span class="str">"socket_create() failed: reason: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">()));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// ‫ضبط الراية O_NONBLOCK</span><span class="pln">
        socket_set_nonblock</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">conn_watcher </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">http_client</span><span class="pun">-&gt;</span><span class="pln">getLoop</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">-&gt;</span><span class="pln">timer</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'connect'</span><span class="pun">]);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __destruct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> freeWatcher</span><span class="pun">(&amp;</span><span class="pln">$w</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$w</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $w</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
            $w </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// تحرير كل موارد الطلب</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> close</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            socket_close</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">);</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">socket </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">freeWatcher</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">timeout_watcher</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">freeWatcher</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">read_watcher</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">freeWatcher</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">write_watcher</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">freeWatcher</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">conn_watcher</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// دالة تهيئ اتصالًا بالمقبس وتعيد قيمة منطقية</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> connect</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $loop </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">http_client</span><span class="pun">-&gt;</span><span class="pln">getLoop</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">timeout_watcher </span><span class="pun">=</span><span class="pln"> $loop</span><span class="pun">-&gt;</span><span class="pln">timer</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">timeout</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'_onTimeout'</span><span class="pun">]);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">write_watcher </span><span class="pun">=</span><span class="pln"> $loop</span><span class="pun">-&gt;</span><span class="pln">io</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ev</span><span class="pun">::</span><span class="pln">WRITE</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'_onWritable'</span><span class="pun">]);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> socket_connect</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">address</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">service_port</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫رد نداء لمهلة المراقب (EvTimer)</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> _onTimeout</span><span class="pun">(</span><span class="typ">EvTimer</span><span class="pln"> $w</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $w</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// رد نداء يُستدعى عندما يصبح المقبس قابلًا للكتابة</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> _onWritable</span><span class="pun">(</span><span class="typ">EvIo</span><span class="pln"> $w</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">timeout_watcher</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
        $w</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
        $in </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            </span><span class="str">"{$this-&gt;method} {$this-&gt;resource} HTTP/1.1"</span><span class="pun">,</span><span class="pln">
            </span><span class="str">"Host: {$this-&gt;host}"</span><span class="pun">,</span><span class="pln">
</span><span class="str">'Connection: Close'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">])</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\r\n\r\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">socket_write</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">,</span><span class="pln"> $in</span><span class="pun">,</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$in</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            trigger_error</span><span class="pun">(</span><span class="str">"Failed writing $in to socket"</span><span class="pun">,</span><span class="pln"> E_USER_ERROR</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        $loop </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">http_client</span><span class="pun">-&gt;</span><span class="pln">getLoop</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">read_watcher </span><span class="pun">=</span><span class="pln"> $loop</span><span class="pun">-&gt;</span><span class="pln">io</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">,</span><span class="pln">
</span><span class="typ">Ev</span><span class="pun">::</span><span class="pln">READ</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> </span><span class="str">'_onReadable'</span><span class="pun">]);</span><span class="pln">
        </span><span class="com">// الاستمرار بتنفيذ الحلقة</span><span class="pln">
        $loop</span><span class="pun">-&gt;</span><span class="pln">run</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// رد نداء يُستدعى عندما يصبح المقبس قابلًا للقراءة</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> _onReadable</span><span class="pun">(</span><span class="typ">EvIo</span><span class="pln"> $w</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// استقبال 20 بايت في وضع عدم التعطيل</span><span class="pln">
        $ret </span><span class="pun">=</span><span class="pln"> socket_recv</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">socket</span><span class="pun">,</span><span class="pln"> $out</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> MSG_DONTWAIT</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$ret</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// إذا كان لا يزال هناك بيانات للقراءة، أضفها إلى المخزن المؤقت</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">buffer </span><span class="pun">.=</span><span class="pln"> $out</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> elseif </span><span class="pun">(</span><span class="pln">$ret </span><span class="pun">===</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// إذا قُرِأت كل البيانات</span><span class="pln">
            printf</span><span class="pun">(</span><span class="str">"\n&lt;&lt;&lt;&lt;\n%s\n&gt;&gt;&gt;&gt;"</span><span class="pun">,</span><span class="pln"> rtrim</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">buffer</span><span class="pun">));</span><span class="pln">
            fflush</span><span class="pun">(</span><span class="pln">STDOUT</span><span class="pun">);</span><span class="pln">
            $w</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// ‫التقاط EINPROGRESS، ‏EAGAIN أو EWOULDBLOCK</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">in_array</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">static</span><span class="pun">::</span><span class="pln">$e_nonblocking</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        $w</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/////////////////////////////////////</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyHttpClient</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫مصفوفة كائنات من الصنف MyHttpRequest</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $requests </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
    </span><span class="pun">?</span><span class="com">// ‫متغير من الصنف EvLoop</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $loop</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫ينفذ كل عميل HTTP حلقة حدث خاصة به</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loop </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">EvLoop</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __destruct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loop</span><span class="pun">-&gt;</span><span class="pln">stop</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫تعيد هذه الدالة كائن EvLoop</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getLoop</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">loop</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// إضافة طلبات معلقة</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> addRequest</span><span class="pun">(</span><span class="typ">MyHttpRequest</span><span class="pln"> $r</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">requests </span><span class="pun">[]=</span><span class="pln"> $r</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// إرسال كل الطلبات المعلقة</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loop</span><span class="pun">-&gt;</span><span class="pln">run</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">//// الاستخدام</span><span class="pln">
$client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyHttpClient</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $client</span><span class="pun">-&gt;</span><span class="pln">addRequest</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyHttpRequest</span><span class="pun">(</span><span class="pln">$client</span><span class="pun">,</span><span class="pln"> </span><span class="str">'my-host.local'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/test.php?a='</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $i</span><span class="pun">,</span><span class="pln"> </span><span class="str">'GET'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$client</span><span class="pun">-&gt;</span><span class="pln">run</span><span class="pun">();</span></pre>

<p>
	في الموضع (1) معاملات الدالة هي:
</p>

<ul>
<li>
		‎$client من الصنف <code>MyHttpClient</code>.
	</li>
	<li>
		‎$host اسم المضيف مثل google.co.uk، سلسلة نصية
	</li>
	<li>
		‎$resource مورد HTTP مثل <code>‎/page?a=b&amp;c=d</code>، سلسلة نصية.
	</li>
	<li>
		‎$method طريقة HTTP مثل: <code>GET</code>، <code>‏HEAD</code>، <code>‏POST</code>، <code>‏PUT</code>…، سلسلة نصية. ترمي هذه الدالة الاستثناء <code>RuntimeException</code>.
	</li>
</ul>
<p>
	الاختبار: بفرض أنّ سكربت <code><a data-ss1616974531="1" data-ss1616975023="1" href="http://my-host.local/test.php" ipsnoembed="true" rel="external nofollow">http://my-host.local/test.php</a></code> يطبع محتويات <code>‎$_GET</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_29" style="">
<span class="pun">&lt;?</span><span class="pln">php
echo </span><span class="str">'GET: '</span><span class="pun">,</span><span class="pln"> var_export</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln"> PHP_EOL</span><span class="pun">;</span></pre>

<p>
	سيكون عندها خرج الأمر <code>php http-client.php</code> مشابهًا للتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_31" style="">
<span class="pln">&lt;&lt;&lt;&lt;
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Fri, 02 Dec 2016 12:39:54 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.13-pl0-gentoo

1d
GET: array (
    'a' =&gt; '3',
)

0
&gt;&gt;&gt;&gt;
&lt;&lt;&lt;&lt;
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Fri, 02 Dec 2016 12:39:54 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.13-pl0-gentoo

1d
GET: array (
    'a' =&gt; '2',
)
0
&gt;&gt;&gt;&gt;
...

// الخرج مختصر</span></pre>

<p>
	لاحظ أنّ إضافة المقابس في PHP 5 قد تسجل تحذيرات لقيم الخطأ <code>EINPROGRESS</code> و<code>EAGAIN</code> و<code>EWOULDBLOCK</code>، من الممكن تعطيل هذه التسجيلات بكتابة الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_33" style="">
<span class="pln">error_reporting</span><span class="pun">(</span><span class="pln">E_ERROR</span><span class="pun">);</span></pre>

<h2>
	استخدام حلقة الحدث Amp
</h2>

<p>
	تستفاد مكتبة العمل <code>Amp</code> من الوعود (اسم آخر لكائنات <code>Awaitables</code>) والمولِّدات لإنشاء نمط مشترك.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_35" style="">
<span class="kwd">require</span><span class="pln"> __DIR__ </span><span class="pun">.</span><span class="pln"> </span><span class="str">'/vendor/autoload.php'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Amp</span><span class="pln">\Dns</span><span class="pun">;</span><span class="pln">

</span><span class="com">// جرب الأسرع محللنا المعرّف من قِبل النظام أو غوغل</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> queryStackOverflow</span><span class="pun">(</span><span class="pln">$recordtype</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $requests </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="typ">Dns</span><span class="pln">\query</span><span class="pun">(</span><span class="str">"stackoverflow.com"</span><span class="pun">,</span><span class="pln"> $recordtype</span><span class="pun">),</span><span class="pln">
        </span><span class="typ">Dns</span><span class="pln">\query</span><span class="pun">(</span><span class="str">"stackoverflow.com"</span><span class="pun">,</span><span class="pln"> $recordtype</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">"server"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"8.8.8.8"</span><span class="pun">]),</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

    </span><span class="com">// تعيد وعدًا ينتهي عندما ينتهي أول طلب</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">yield</span><span class="pln"> </span><span class="typ">Amp</span><span class="pln">\first</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
\Amp\run</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// الحلقة الأساسية، نمط مشترك ضمنيًا</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التحويل إلى نمط مشترك باستخدام Amp\resolve()‎</span><span class="pln">
        $promise </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Amp</span><span class="pln">\resolve</span><span class="pun">(</span><span class="pln">queryStackOverflow</span><span class="pun">(</span><span class="typ">Dns</span><span class="pln">\Record</span><span class="pun">::</span><span class="pln">NS</span><span class="pun">));</span><span class="pln">
        list</span><span class="pun">(</span><span class="pln">$ns</span><span class="pun">,</span><span class="pln"> $type</span><span class="pun">,</span><span class="pln"> $ttl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="com">// ‫نحتاج إلى نتيجة NS واحدة وليس كل النتائج</span><span class="pln">
        current</span><span class="pun">(</span><span class="kwd">yield</span><span class="pln"> </span><span class="typ">Amp</span><span class="pln">\timeout</span><span class="pun">(</span><span class="pln">$promise</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2000</span><span class="pln"> </span><span class="com">/* milliseconds */</span><span class="pun">));</span><span class="pln">
        echo </span><span class="str">"The result of the fastest server to reply to our query was $ns"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Amp</span><span class="pln">\TimeoutException $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"We've heard no answer for 2 seconds! Bye!"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Dns</span><span class="pln">\NoRecordException $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"No NS records there? Stupid DNS nameserver!"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">});</span></pre>

<h2>
	التوطين (Localization)
</h2>

<h3>
	توطين السلاسل النصية مع gettext()‎
</h3>

<p>
	<code>gettext</code> من مكتبة GNU هي إضافة PHP يجب تضمصينها ضمن ملف <code>php.ini</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_37" style="">
<span class="pln">extension</span><span class="pun">=</span><span class="pln">php_gettext</span><span class="pun">.</span><span class="pln">dll </span><span class="com">#Windows</span><span class="pln">
extension</span><span class="pun">=</span><span class="pln">gettext</span><span class="pun">.</span><span class="pln">so </span><span class="com">#Linux</span></pre>

<p>
	تنفذ دوال <code>gettext</code> واجهة برمجة تطبيقات دعم اللغة الأصلية (NLS) والتي يمكن استخدامها لتوطين تطبيقات PHP.
</p>

<p>
	يمكن إجراء السلاسل النصية للترجمة في PHP بضبط المحلية (locale) وضبط جداول الترجمة واستدعاء <code>gettext()‎</code> على أي سلسلة نصية تريد ترجمتها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_39" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// ضبط اللغة إلى الفرنسية</span><span class="pln">
putenv</span><span class="pun">(</span><span class="str">'LC_ALL= fr_FR'</span><span class="pun">);</span><span class="pln">
setlocale</span><span class="pun">(</span><span class="pln">LC_ALL</span><span class="pun">,</span><span class="pln"> </span><span class="str">'fr_FR'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫تحديد موقع جداول الترجمة للنطاق 'myPHPApp'</span><span class="pln">
bindtextdomain</span><span class="pun">(</span><span class="str">"myPHPApp"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"./locale"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫اختيار النطاق 'myPHPApp'</span><span class="pln">
textdomain</span><span class="pun">(</span><span class="str">"myPHPApp"</span><span class="pun">);</span></pre>

<p>
	الملف <code>myPHPApp.po</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_41" style="">
<span class="com">#: /Hello_world.php:56</span><span class="pln">
msgid </span><span class="str">"Hello"</span><span class="pln">
msgstr </span><span class="str">"Bonjour"</span><span class="pln">

</span><span class="com">#: /Hello_world.php:242</span><span class="pln">
msgid </span><span class="str">"How are you?"</span><span class="pln">
msgstr </span><span class="str">"Comment allez-vous?"</span></pre>

<p>
	تحمّل الدالة <code>gettext()‎</code> ملف <code>‎.po</code> بعد تصريفه أي ملف <code>‎.mo</code>، الذي يربط ملفك ليصبح سلاسل نصية مترجمة كما في الأعلى.
</p>

<p>
	بعد هذه الشيفرة البسيطة سيُنظر إلى الترجمة في الملف التالي:
</p>

<pre class="ipsCode">
./locale/fr_FR/LC_MESSAGES/myPHPApp.mo
</pre>

<p>
	عندما تستدعي <code>gettext('some string')‎</code>، إذا كانت السلسلة النصية 'some string' مُترجمة في الملف <code>‎.mo</code> ستُرجع الترجمة وإلا ستُرجع السلسلة 'some string' غير مترجمة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_43" style="">
<span class="com">// ‫طباعة النسخة المترجمة من 'Welcome to My PHP Application'</span><span class="pln">
echo gettext</span><span class="pun">(</span><span class="str">"Welcome to My PHP Application"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫أو نستخدم الاسم البديل `‎_()‎` للدالة `gettext()‎`</span><span class="pln">
echo _</span><span class="pun">(</span><span class="str">"Have a nice day"</span><span class="pun">);</span></pre>

<h2>
	معالجة الترويسات
</h2>

<h3>
	الضبط الأساسي للترويسة
</h3>

<p>
	إليك الضبط الأساسي لترويسة للانتقال إلى صفحة جديدة عند الضغط على زر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_45" style="">
<span class="kwd">if</span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_REQUEST</span><span class="pun">[</span><span class="str">'action'</span><span class="pun">]))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">switch</span><span class="pun">(</span><span class="pln">$_REQUEST</span><span class="pun">[</span><span class="str">'action'</span><span class="pun">])</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> </span><span class="com">// ضبط الترويسة بالاعتماد على أي الزر المضغوط</span><span class="pln">
        </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'getState'</span><span class="pun">:</span><span class="pln">
            header</span><span class="pun">(</span><span class="str">"Location: http://NewPageForState.com/getState.php?search="</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">'search'</span><span class="pun">]);</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'getProject'</span><span class="pun">:</span><span class="pln">
            header</span><span class="pun">(</span><span class="str">"Location: http://NewPageForProject.com/getProject.php?search="</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">'search'</span><span class="pun">]);</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">GetSearchTerm</span><span class="pun">(!</span><span class="pln">NULL</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// نماذج لإضافة ولاية أو مشروع والضغط على البحث</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> </span><span class="typ">GetSearchTerm</span><span class="pun">(</span><span class="pln">$success</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_null</span><span class="pun">(</span><span class="pln">$success</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"&lt;h4&gt;You must enter a state or project number&lt;/h4&gt;"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    echo </span><span class="str">"&lt;center&gt;&lt;strong&gt;Enter the State to search for&lt;/strong&gt;&lt;/center&gt;&lt;p&gt;&lt;/p&gt;"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// ‫استخدام `‎$_SERVER['PHP_SELF']‎` يبقينا في الصفحة حتى تقرر تعليمة `switch` أين سنذهب</span><span class="pln">
    echo </span><span class="str">"&lt;form action='"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'PHP_SELF'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"' enctype='multipart/form-data' method='POST'&gt;
&lt;input type='hidden' name='action' value='getState'&gt;
&lt;center&gt;State: &lt;input type='text' name='search' size='10'&gt;&lt;/center&gt;&lt;p&gt;&lt;/p&gt;
&lt;center&gt;&lt;input type='submit' name='submit' value='Search State'&gt;&lt;/center&gt;
&lt;/form&gt;"</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">GetSearchTermProject</span><span class="pun">(</span><span class="pln">$success</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> </span><span class="typ">GetSearchTermProject</span><span class="pun">(</span><span class="pln">$success</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"&lt;center&gt;&lt;br&gt;&lt;strong&gt;Enter the Project to search for&lt;/strong&gt;&lt;/center&gt;&lt;p&gt;&lt;/p&gt;"</span><span class="pun">;</span><span class="pln">
    echo </span><span class="str">"&lt;form action='"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'PHP_SELF'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"' enctype='multipart/form-data' method='POST'&gt;
&lt;input type='hidden' name='action' value='getProject'&gt;
&lt;center&gt;Project Number: &lt;input type='text' name='search' size='10'&gt;&lt;/center&gt;&lt;p&gt;&lt;/p&gt;
&lt;center&gt;&lt;input type='submit' name='submit' value='Search Project'&gt;&lt;/center&gt;
&lt;/form&gt;"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h2>
	كيفية كشف عنوان IP لعميل
</h2>

<h3>
	الاستخدام المناسب للترويسة HTTP<em>X</em>FORWARDED_FOR
</h3>

<p>
	يوجد متغير آخر يُستخدم بشكلٍ سيء على نطاق واسع في ضوء أحدث ثغرات <a data-ss1616974531="1" data-ss1616975023="1" href="%E2%80%8Fhttps://httpoxy.org/" rel="">httpoxy</a>، تُستخدم الترويسة <code>HTTP_X_FORWARDED_FOR</code> غالبًا لكشف عنوان IP لعميل، لكن قد يؤدي ذلك بدون أي عمليات تحقق إضافية إلى مشاكل في الأمان خاصةً عند استخدام عنوان IP هذا لاحقًا للمصادقة أو في استعلامات SQL بدون تعقيم.
</p>

<p>
	تتجاهل معظم أمثلة الشيفرة المتوفرة حقيقة أنّه يمكن أن نعد <code>HTTP_X_FORWARDED_FOR</code> معلومةً يوفرها العميل بنفسه ولذا فهي مصدر غير موثوق لاكتشاف عنوان IP العميل، تضيف بعض هذه الأمثلة تحذيرًا بشأن سوء الاستخدام المحتمل لكنها لا تزال تفتقد إلى القيام بالتحقق في شيفرتها، لذا نقدم لك مثالًا عن دالة مكتوبة في PHP عن كيفية كشف عنوان IP لعميل إذا كنت تعرف أنّ العميل يستخدم وكيلًا (proxy) وأنت تعرف أنّه يمكن الوثوق بهذا الوكيل، إذا لم تكن تعرف أي وكيل موثوق فيمكنك استخدام <code>REMOTE_ADDR</code> فقط.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6489_47" style="">
<span class="kwd">function</span><span class="pln"> get_client_ip</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// لا يوجد شيء لفعله بدون معلومات موثوقة</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_SERVER</span><span class="pun">[</span><span class="str">'REMOTE_ADDR'</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> NULL</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫الترويسة التي يستخدمها الوكيل الموثوق للإشارة إلى عنوان IP الأصلي</span><span class="pln">
    $proxy_header </span><span class="pun">=</span><span class="pln"> </span><span class="str">"HTTP_X_FORWARDED_FOR"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// (1)</span><span class="pln">
    $trusted_proxies </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="str">"2001:db8::1"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"192.168.50.1"</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">in_array</span><span class="pun">(</span><span class="pln">$_SERVER</span><span class="pun">[</span><span class="str">'REMOTE_ADDR'</span><span class="pun">],</span><span class="pln"> $trusted_proxies</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫الحصول على عنوان IP للعميل الذي يستخدم وكيل موثوق</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">array_key_exists</span><span class="pun">(</span><span class="pln">$proxy_header</span><span class="pun">,</span><span class="pln"> $_SERVER</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// (2)</span><span class="pln">
            $client_ip </span><span class="pun">=</span><span class="pln"> trim</span><span class="pun">(</span><span class="kwd">end</span><span class="pun">(</span><span class="pln">explode</span><span class="pun">(</span><span class="str">","</span><span class="pun">,</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="pln">$proxy_header</span><span class="pun">])));</span><span class="pln">

            </span><span class="com">// التحقق فقط في حالة</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="pln">$client_ip</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> $client_ip</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="com">// (3)</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫في كل الحالات الباقية REMOTE_ADDR هو عنوان IP الوحيد الذي يمكن الوثوق به</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'REMOTE_ADDR'</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> get_client_ip</span><span class="pun">();</span></pre>

<p>
	في الموضع (1) نضيف قائمة بكل الوكلاء المعروفين لمعالجة 'proxy_header' بطريقةٍ آمنةٍ.
</p>

<p>
	في الموضع (2) يمكن أن تحتوي الترويسة على عدة عناوين IP لوكلاء تمر عبرها، يمكن الوثوق فقط بعنوان IP الذي أضافه الوكيل الأخير (الموجود في القائمة).
</p>

<p>
	في الموضع (3) فشل التحقق مما يعني فوز الشخص الذي ضَبط الوكيل أو أنشأ قائمة الوكلاء الموثوقين لذا يجب إضافة معالجة للأخطاء هنا والتنبيه على خطأ الشخص المسؤول.
</p>

<p>
	ترجمة -وبتصرف- للفصول [Coding Conventions - Asynchronous programming - Localization - Headers Manipulation - How to Detect Client IP Address] من كتاب <a data-ss1616974531="1" data-ss1616975023="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%85%D8%B9-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-gd-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-imagick-%D9%81%D9%8A-php-r1178/" rel="">معالجة الصور مع مكتبة GD ومكتبة Imagick في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-cli-%D9%81%D9%8A-php-r1176/" rel="">التعامل مع واجهة سطر الأوامر (CLI) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1177</guid><pubDate>Sat, 27 Mar 2021 13:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x648;&#x627;&#x62C;&#x647;&#x629; &#x633;&#x637;&#x631; &#x627;&#x644;&#x623;&#x648;&#x627;&#x645;&#x631; (CLI) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-cli-%D9%81%D9%8A-php-r1176/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/4.png.a84fe32a2e78c515d468bf83495ba880.png" /></p>

<h2>
	معالجة خيارات البرنامج
</h2>

<p>
	يمكن معالجة خيارات البرنامج باستخدام الدالة <code>getopt()‎</code>، التي تعمل بصيغة مشابهة للأمر <code>getopt</code> في معايير POSIX مع دعم إضافي للخيارات الطويلة ذات النمط GNU.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_7" style="">
<span class="com">#!/usr/bin/php</span><span class="pln">

</span><span class="com">// تشير النقطتين إلى خيار يأخذ قيمة</span><span class="pln">
</span><span class="com">// تشير النقطتين المضاعفتين إلى قيمة يمكن إهمالها</span><span class="pln">
$shortopts </span><span class="pun">=</span><span class="pln"> </span><span class="str">"hf:v::d"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫الخيارات الطويلة ذات النمط GNU غير مطلوبة</span><span class="pln">
$longopts </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"help"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"version"</span><span class="pun">];</span><span class="pln">
$opts </span><span class="pun">=</span><span class="pln"> getopt</span><span class="pun">(</span><span class="pln">$shortopts</span><span class="pun">,</span><span class="pln"> $longopts</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫تُسند القيمة المنطقية false للخيارات التي ليس لها قيم، يجب التحقق من وجودها وليس صدقها</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"h"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"help"</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    fprintf</span><span class="pun">(</span><span class="pln">STDERR</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Here is some help!\n"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// ‫تُستدعى الخيارات الطويلة مع شرطتين: "‎--version"</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"version"</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    fprintf</span><span class="pun">(</span><span class="pln">STDERR</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s Version 223.45"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln"> $argv</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
</span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// ‫يمكن استدعاء الخيارات ذات القيم بالشكل "‎-f foo" أو ‏"‎-ffoo" أو "‎-f=foo"</span><span class="pln">
$file </span><span class="pun">=</span><span class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"f"</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $file </span><span class="pun">=</span><span class="pln"> $opts</span><span class="pun">[</span><span class="str">"f"</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    fprintf</span><span class="pun">(</span><span class="pln">STDERR</span><span class="pun">,</span><span class="pln"> </span><span class="str">"We wanted a file!"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
fprintf</span><span class="pun">(</span><span class="pln">STDOUT</span><span class="pun">,</span><span class="pln"> </span><span class="str">"File is %s"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln"> $file</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫يمكن استدعاء الخيارات ذات القيم الافتراضية بالشكل "‎-v5" أو "‎-v=5"</span><span class="pln">
$verbosity </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"v"</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $verbosity </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"v"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pun">)</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"v"</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
fprintf</span><span class="pun">(</span><span class="pln">STDOUT</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Verbosity is %d"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln"> $verbosity</span><span class="pun">);</span><span class="pln">

</span><span class="com">// تُمرَّر الخيارات التي نستدعيها عدة مرات كمصفوفة</span><span class="pln">
$debug </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"d"</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $debug </span><span class="pun">=</span><span class="pln"> is_array</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"d"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> count</span><span class="pun">(</span><span class="pln">$opts</span><span class="pun">[</span><span class="str">"d"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
fprintf</span><span class="pun">(</span><span class="pln">STDOUT</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Debug is %d"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln"> $debug</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫لا توجد طريقة تلقائية عند getopt لمعالجة الخيارات غير المتوقعة</span></pre>

<p>
	يمكن اختبار السكربت السابق بالشكل:
</p>

<pre class="ipsCode">
./test.php --help
./test.php --version
./test.php -f foo -ddd
./test.php -v -d -ffoo
./test.php -v5 -f=foo
./test.php -f foo -v 5 -d
</pre>

<p>
	لاحظ أنّ الطريقة الأخيرة لن تعمل لأنّ <code>‎-v 5</code> غير صحيحة.
</p>

<p>
	<strong>ملاحظة:</strong> يعدّ الأمر <code>getopt</code> بدءًا من الإصدار PHP 5.3.0 مستقلًا عن نظام التشغيل ويعمل أيضًا على نظام ويندوز.
</p>

<h2>
	معالجة الوسيط
</h2>

<p>
	تُمرَّر الوسائط إلى البرنامج بطريقة مشابهة لمعظم اللغات ذات النمط C، إنّ <code>‎$argc</code> عدد صحيح يعبّر عن عدد الوسائط متضمنةً اسم البرنامج و<code>‎$argv</code> مصفوفة تتضمن وسائط البرنامج. العنصر الأول من <code>‎$argv</code> هو اسم البرنامج.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_9" style="">
<span class="com">#!/usr/bin/php</span><span class="pln">
printf</span><span class="pun">(</span><span class="str">"You called the program %s with %d arguments\n"</span><span class="pun">,</span><span class="pln"> $argv</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> $argc </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
unset</span><span class="pun">(</span><span class="pln">$argv</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$argv </span><span class="kwd">as</span><span class="pln"> $i </span><span class="pun">=&gt;</span><span class="pln"> $arg</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    printf</span><span class="pun">(</span><span class="str">"Argument %d is %s\n"</span><span class="pun">,</span><span class="pln"> $i</span><span class="pun">,</span><span class="pln"> $arg</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استدعاء التطبيق السابق باستخدام <code>php example.php foo bar</code> (حيث يتضمن الملف <code>example.php</code> الشيفرة السابقة) سيؤدي إلى الخرج التالي:
</p>

<pre class="ipsCode">
You called the program example.php with 2 arguments
Argument 1 is foo
Argument 2 is bar
</pre>

<p>
	لاحظ أنّ <code>‎$argc</code> و<code>‎$argv</code> هي متغيرات عامة وليست متغيرات ذات نطاق عام عالي، ويجب استيرادها إلى النطاق المحلي باستخدام الكلمة المفتاحية <code>global</code> عندما نحتاج إلى استخدامها في دالة ما.
</p>

<p>
	يُظهر هذا المثال كيف تُجمَّع الوسائط عندما نهرب باستخدام <code>""</code> أو <code>\</code>.
</p>

<p>
	مثال عن سكربت:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_14" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">$argc</span><span class="pun">,</span><span class="pln"> $argv</span><span class="pun">);</span></pre>

<p>
	سطر الأوامر:
</p>

<pre class="ipsCode">
$ php argc.argv.php --this-is-an-option three\ words\ together or "in one quote" but\ multiple\spaces\ counted\ as\ one
int(6)
array(6) {
    [0]=&gt;
    string(13) "argc.argv.php"
    [1]=&gt;
    string(19) "--this-is-an-option"
    [2]=&gt;
    string(20) "three words together"
    [3]=&gt;
    string(2) "or"
    [4]=&gt;
    string(12) "in one quote"
    [5]=&gt;
    string(34) "but multiple spaces counted as one"
}
</pre>

<p>
	إذا نُفِّذ سكربت PHP باستخدام <code>‎-r</code>:
</p>

<pre class="ipsCode">
$ php -r 'var_dump($argv);'
array(1) {
    [0]=&gt;
    string(1) "-"
}
</pre>

<p>
	أو تُرسل الشيفرة عبر أنبوب في مجرى الدخل القياسي <code>php</code>:
</p>

<pre class="ipsCode">
$ echo '&lt;?php var_dump($argv);' | php
array(1) {
    [0]=&gt;
    string(1) "-"
}
</pre>

<h2>
	معالجة الدخل والخرج
</h2>

<p>
	إنّ الثوابت <code>STDIN</code> و<code>STDOUT</code> و<code>STDERR</code> معرَّفة مسبقًا عند التنفيذ من واجهة سطر الأوامر (CLI)، وهي مقابض للملف يمكن أن نعدّها مكافئة لنتائج تنفيذ الأوامر التالية:
</p>

<pre class="ipsCode">
STDIN = fopen("php://stdin", "r");
STDOUT = fopen("php://stdout", "w");
STDERR = fopen("php://stderr", "w");
</pre>

<p>
	يمكن استخدام الثوابت في أي مكان يكون مقبض الملف القياسي فيه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_17" style="">
<span class="com">#!/usr/bin/php</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$line </span><span class="pun">=</span><span class="pln"> fgets</span><span class="pun">(</span><span class="pln">STDIN</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $line </span><span class="pun">=</span><span class="pln"> strtolower</span><span class="pun">(</span><span class="pln">trim</span><span class="pun">(</span><span class="pln">$line</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$line</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">case</span><span class="pln"> </span><span class="str">"bad"</span><span class="pun">:</span><span class="pln">
        fprintf</span><span class="pun">(</span><span class="pln">STDERR</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s is bad"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln"> $line</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">case</span><span class="pln"> </span><span class="str">"quit"</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
        fprintf</span><span class="pun">(</span><span class="pln">STDOUT</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s is good"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln"> $line</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام عناوين المجرى المضمَّن المُشار إليها سابقًا <code>php://stdin</code> و<code>php://stdout</code> و<code>php://stderr</code> مكان أسماء الملفات في معظم الحالات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_19" style="">
<span class="pln">file_put_contents</span><span class="pun">(</span><span class="str">'php://stdout'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'This is stdout content'</span><span class="pun">);</span><span class="pln">
file_put_contents</span><span class="pun">(</span><span class="str">'php://stderr'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'This is stderr content'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// فتح المقبض والكتابة عدة مرات</span><span class="pln">
$stdout </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">'php://stdout'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">);</span><span class="pln">
fwrite</span><span class="pun">(</span><span class="pln">$stdout</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Hello world from stdout'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">);</span><span class="pln">
fwrite</span><span class="pun">(</span><span class="pln">$stdout</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Hello again'</span><span class="pun">);</span><span class="pln">

fclose</span><span class="pun">(</span><span class="pln">$stdout</span><span class="pun">);</span></pre>

<p>
	يمكن أن تستخدم أيضًا الدالة <a data-ss1616973474="1" data-ss1616973973="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.readline.php" rel="">readline()‎</a> كبديل للدخل وتستخدم <code>echo</code> أو <code>print</code> أو أي دالة من دوال طباعة السلسلة النصية كبديل للخرج.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_21" style="">
<span class="pln">$name </span><span class="pun">=</span><span class="pln"> readline</span><span class="pun">(</span><span class="str">"Please enter your name:"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Hello, {$name}."</span><span class="pun">;</span></pre>

<h2>
	الشيفرات المُعادة
</h2>

<p>
	يمكن استخدام البنية <code>exit</code> لتمرير شيفرة معادة إلى بيئة التنفيذ.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_23" style="">
<span class="com">#!/usr/bin/php</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$argv</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="str">"bad"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ستُرجَع شيفرة الخروج 0 بشكلٍ افتراضي إذا لم تُمرَّر قيمة أي أنّ <code>exit</code> نفس <code>exit(0)‎</code> وبما أنّ <code>exit</code> ليست دالة فإنّ الأقواس غير ضرورية إذا لم تُمرَّر شيفرة معادة.
</p>

<p>
	يجب أن تكون الشيفرات المُعادة في المجال بين 0 و254 (الشيفرة 255 محجوزة من قِبَل <a href="https://wiki.hsoub.com/PHP" rel="external">PHP </a>ويجب عدم استخدامها)، اصطلاحًا إنّ الخروج بالشيفرة المُرجعة 0 تُخبر البرنامج المُستدعي أنّ سكربت PHP نُفِّذ بنجاح أما الشيفرة المرجعية غير الصفرية تُخبر البرنامج المستدعي بحدوث حالة خطأ محددة.
</p>

<h2>
	قصر تنفيذ السكربت على سطر الأوامر
</h2>

<p>
	يُرجع كل من الدالة <a data-ss1616973474="1" data-ss1616973973="1" href="%E2%80%8Fhttps://www.php.net/php_sapi_name" rel="">php_sapi_name()‎</a> والثابت <code>PHP_SAPI</code> نوع الواجهة (واجهة برمجة تطبيقات الخادم <code>Server <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></code>) التي تستخدمها PHP، ويمكن استخدامها لقصر تنفيذ السكربت على سطر الأوامر عن طريق التحقق فيما إذا كان خرج الدالة يساوي <code>cli</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_25" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">php_sapi_name</span><span class="pun">()</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="str">'cli'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Executed from command line\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Executed from web browser\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الدالة <a data-ss1616973474="1" data-ss1616973973="1" href="%E2%80%8Fhttps://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_is_cli/7.x" rel=""><code>drupal_is_cli()‎</code></a> هي مثال عن دالة تكتشف فيما إذا كان السكربت قد نُفِّذ من سطر الأوامر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_27" style="">
<span class="kwd">function</span><span class="pln"> drupal_is_cli</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_SERVER</span><span class="pun">[</span><span class="str">'SERVER_SOFTWARE'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">php_sapi_name</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'cli'</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_numeric</span><span class="pun">(</span><span class="pln">$_SERVER</span><span class="pun">[</span><span class="str">'argc'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'argc'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)));</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الاختلافات السلوكية في سطر الأوامر
</h2>

<p>
	تعرض PHP عند التنفيذ من CLI بعض السلوكيات المختلفة عن السلوكيات عند التنفيذ على خادم ويب، يجب أن تتذكر هذه السلوكيات خاصةً في حالة تنفيذ نفس السكربت في البيئتين.
</p>

<ul>
<li>
		لا يتغير المجلد عند التنفيذ على خادم ويب بل يبقى مجلد العمل الحالي للسكربت نفسه دائمًا، تفترض الشيفرة <code>require("./stuff.inc");‎</code> أنّ الملف في نفس مجلد السكربت، أما في سطر الأوامر فإنّ مجلد العمل الحالي هو المجلد الذي يُستدعى منه السكربت، يجب أن تستخدم السكربتات التي ستُستدعى من سطر الأوامر مسارات مطلقة. (لاحظ أنّ الثوابت السحرية <code>__DIR__</code> و<code>__FILE__</code> تبقى تعمل كما هو متوقع وتُرجع موقع السكربت).
	</li>
	<li>
		لا يوجد مخزن مؤقت للخرج، القيم الافتراضية لموجهات الملف <code>php.ini</code> <code>‏output_buffering</code> و<code>implicit_flush</code> هي <code>false</code> و<code>true</code> على الترتيب. ويبقى المخزن المؤقت متوفرًا لكن يجب تمكينه بشكلٍ صريح وإلا سيُعرض الخرج دائمًا في الوقت الحقيقي.
	</li>
	<li>
		لا يوجد قيد زمني، يُضبط الموجه <code>max_execution_time</code> في الملف <code>php.ini</code> إلى القيمة صفر لذا لن ينتهي وقت تنفيذ السكربتات بشكلٍ افتراضي.
	</li>
	<li>
		لا توجد أخطاء HTML، إذا مكّنت الموجّه <code>html_errors</code> في ملف <code>php.ini</code> سيتجاهله سطر الأوامر.
	</li>
	<li>
		يمكن تحميل ملفات <code>php.ini</code> مختلفة، إذا كنت تستخدم PHP من CLI يمكنك تحميل ملفات <code>php.ini</code> مختلفة وهذا غير متاح عند التنفيذ على خادم ويب، يمكنك أن تعرف ما هو الملف المستخدم بتنفيذ الأمر <code>php ‎--ini‎</code>.
	</li>
</ul>
<h2>
	تنفيذ السكربت
</h2>

<p>
	في كل من لينوكس/يونكس أو ويندوز يمكن تمرير الملف كوسيط إلى PHP القابلة للتنفيذ مع خيارات ووسائط السكربت:
</p>

<pre class="ipsCode">
php ~/example.php foo bar

c:\php\php.exe c:\example.php foo bar
</pre>

<p>
	تمرر الشيفرة السابقة الوسائط <code>foo</code> و<code>bar</code> إلى الملف <code>example.php</code>.
</p>

<p>
	الطريقة المفضلة لتنفيذ السكربتات في لينوكس/يونكس هي استخدام <a data-ss1616973474="1" data-ss1616973973="1" href="%E2%80%8F%E2%80%8Ehttps://en.wikipedia.org/wiki/Shebang_(Unix)%E2%80%8E" rel="">Shebang</a> (سطر يبدأ بالسلسلة النصية "‎ #! ‎") مثل <code>‎#!/usr/bin/env php</code> في السطر الأول من الملف وضبط البت القابل للتنفيذ على الملف، بفرض أنّ السكربت في مسارك يمكنك عندها استدعاؤه مباشرةً:
</p>

<pre class="ipsCode">
example.php foo bar
</pre>

<p>
	إنّ استخدام <code>‎/usr/bin/env php‎</code> يجعل من الممكن العثور على PHP القابلة للتنفيذ باستخدام <code>PATH</code>. وفقًا لكيفية تثبيت PHP قد لا تكون موجودة في نفس المكان (مثل <code>‎/usr/bin/php‎</code> أو <code>‎/usr/local/bin/php</code>) على عكس <code>env</code> المتوفرة عادةً في <code>‎/usr/bin/env</code>.
</p>

<p>
	في ويندوز قد تحصل على نفس النتيجة بإضافة مجلد PHP والسكربت الخاص بك إلى <code>PATH</code> وتعديل <code>PATHEXT</code> ليسمح باكتشاف <code>‎.php</code> باستخدام <code>PATH</code>، الاحتمال الآخر هو إضافة ملف باسم <code>example.bat</code> أو <code>example.cmd</code> في نفس المجلد الموجود به سكربت PHP وكتابة هذا السطر فيه:
</p>

<pre class="ipsCode">
c:\php\php.exe "%~dp0example.php" %*
</pre>

<p>
	أو إذا أضفت مجلد PHP داخل <code>PATH</code>:
</p>

<pre class="ipsCode">
php "%~dp0example.php" %*
</pre>

<h2>
	حالات متقدمة لاستخدام getopt()‎
</h2>

<p>
	يظهر هذا المثال سلوك <code>getopt</code> عندما يكون دخل المستخدم غير شائع، محتويات الملف <code>getopt.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_30" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">
    getopt</span><span class="pun">(</span><span class="str">"ab:c::"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">"delta"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"epsilon:"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"zeta::"</span><span class="pun">])</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	سطر أوامر الصدفة:
</p>

<pre class="ipsCode">
$ php getopt.php -a -a -bbeta -b beta -cgamma --delta --epsilon --zeta --zeta=f -c gamma
array(6) {
    ["a"]=&gt;
    array(2) {
        [0]=&gt;
        bool(false)
        [1]=&gt;
        bool(false)
    }
    ["b"]=&gt;
    array(2) {
        [0]=&gt;
        string(4) "beta"
        [1]=&gt;
        string(4) "beta"
    }
    ["c"]=&gt;
    array(2) {
        [0]=&gt;
        string(5) "gamma"
        [1]=&gt;
        bool(false)
    }
    ["delta"]=&gt;
        bool(false)
    ["epsilon"]=&gt;
        string(6) "--zeta"
    ["zeta"]=&gt;
        string(1) "f"
}
</pre>

<p>
	يمكننا أن نلاحظ من المثال السابق:
</p>

<ul>
<li>
		تحمل الخيارات الفردية (بدون نقطتان) دائمًا القيمة المنطقية <code>false</code> إذا مُكِّنت.
	</li>
	<li>
		إذا كُرِّر خيار ما فإنّ قيمة خرج <code>getopt</code> ستصبح مصفوفة.
	</li>
	<li>
		تقبل خيارات الوسيط المطلوب (بنقطتين) فراغ واحد أو عدم وجود فراغ (مثل خيارات الوسيط الاختيارية) كفاصل.
	</li>
	<li>
		بعد وجود وسيط واحد لا يمكن ربطه بأي خيار فإنّ الخيارات التالية لن تُربط أيضًا.
	</li>
</ul>
<h2>
	تشغيل خادم ويب مدمج
</h2>

<p>
	أصبحت PHP بدءًا من الإصدار PHP 5.4 تأتي مع خادم مدمج، يمكن استخدامه لتنفيذ تطبيق بدون الحاجة لتثبيت أي خادم http مثل <code>nginx</code> أو <code>apache</code>، صُمم الخادم المدمج في بيئة المتحكم فقط لأهداف التطوير والاختبار، يمكن تنفيذه باستخدام الأمر <code>php -S</code> ولاختباره ننشئ الملف <code>index.php</code> ونكتب فيه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5819_32" style="">
<span class="pun">&lt;?</span><span class="pln">php
echo </span><span class="str">"Hello World from built-in PHP server"</span><span class="pun">;</span></pre>

<p>
	وننفذ الأمر:
</p>

<pre class="ipsCode">
php -S localhost:8080
</pre>

<p>
	يجب أن تكون الآن قادرًا على رؤية المحتوى في المتصفح، للتحقق من ذلك انتقل إلى المسار <code><a data-ss1616973474="1" data-ss1616973973="1" href="http://localhost:8080" ipsnoembed="true" rel="external nofollow">http://localhost:8080</a></code> ، ويجب أن يؤدي كل وصول إلى مدخل سجل يُكتب في الطرفية (Terminal).
</p>

<pre class="ipsCode">
[Mon Aug 15 18:20:19 2016] ::1:52455 [200]: /
</pre>

<p>
	ترجمة -وبتصرف- للفصل [Command Line Interface (CLI)‎] من كتاب <a data-ss1616973474="1" data-ss1616973973="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%88%D8%A7%D8%B6%D9%8A%D8%B9-%D9%85%D8%AA%D9%81%D8%B1%D9%82%D8%A9-%D9%85%D9%87%D9%85%D8%A9-%D9%84%D9%83%D9%84-%D9%85%D8%A8%D8%B1%D9%85%D8%AC-php-r1177/" rel="">اصطلاحات ومواضيع متفرقة مهمة لكل مبرمج PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D9%85%D9%84%D8%A7%D8%AD%D8%B8%D8%A7%D8%AA-%D8%AD%D9%88%D9%84-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%A8%D8%B1%D9%88%D8%AA%D9%88%D9%83%D9%88%D9%84-imap-%D9%81%D9%8A-php-r1175/" rel="">ملاحظات حول استعمال بروتوكول IMAP في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1176</guid><pubDate>Tue, 23 Mar 2021 13:00:00 +0000</pubDate></item><item><title>&#x645;&#x644;&#x627;&#x62D;&#x638;&#x627;&#x62A; &#x62D;&#x648;&#x644; &#x627;&#x633;&#x62A;&#x639;&#x645;&#x627;&#x644; &#x628;&#x631;&#x648;&#x62A;&#x648;&#x643;&#x648;&#x644; IMAP &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D9%84%D8%A7%D8%AD%D8%B8%D8%A7%D8%AA-%D8%AD%D9%88%D9%84-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%A8%D8%B1%D9%88%D8%AA%D9%88%D9%83%D9%88%D9%84-imap-%D9%81%D9%8A-php-r1175/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/3.png.0e4a1f3c11cd9bb46611e32be2bf4d9d.png" /></p>

<h2>
	الاتصال إلى صندوق البريد (mailbox)
</h2>

<p>
	للقيام بأي فعل مع حساب IMAP (‏Internet Message Access Protocol) تحتاج للاتصال به أولًا، ولتتصل تحتاج لتحديد بعض المعاملات المطلوبة:
</p>

<ul>
<li>
		اسم الخادم أو عنوان IP لخادم البريد (mail server).
	</li>
	<li>
		المنفذ الذي تريد الاتصال به:
		<ul>
<li>
				منفذ IMAP هو 143 أو993 (آمن).
			</li>
			<li>
				منفذ POP (‏Post Office Protocol‏) هو 110 أو995 (آمن).
			</li>
			<li>
				منفذ SMTP (‏Simple Mail Transfer Protocol) هو 25 أو465 (آمن).
			</li>
			<li>
				منفذ NNTP (‏Network News Transfer Protocol) هو 119 أو563 (آمن).
			</li>
		</ul>
</li>
	<li>
		رايات الاتصال: موضحة في الجدول التالي:
	</li>
</ul>
<table>
<thead><tr>
<th>
				الراية
			</th>
			<th>
				الوصف
			</th>
			<th>
				الخيارات
			</th>
			<th>
				القيمة الافتراضية
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				‎/service=service
			</td>
			<td>
				الخدمة التي نريد استخدامها
			</td>
			<td>
				imap,pop3,nntp, smtp
			</td>
			<td>
				imap
			</td>
		</tr>
<tr>
<td>
				‎/user=user
			</td>
			<td>
				اسم المستخدم البعيد لتسجيل الدخول على الخادم
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/authuser=user
			</td>
			<td>
				مستخدم المصادقة عن بعد، إذا حُدِّد فهذا هو اسم المستخدم الذي تُستخدم كلمة المرور الخاصة به
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/anonymous
			</td>
			<td>
				الوصول البعيد كمستخدم غريب
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/debug
			</td>
			<td>
				تسجيل بروتوكول القياس عن بعد في سجل أخطاء التطبيق
			</td>
			<td>
				 
			</td>
			<td>
				disabled
			</td>
		</tr>
<tr>
<td>
				‎/secure
			</td>
			<td>
				لا ترسل كلمة المرور كنص عادي عبر الشبكة
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/norsh
			</td>
			<td>
				‫لا تستخدم rsh أو <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> لتأسيس جلسة IMAP مسبقة الوثوقية
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">ssl</abbr>
			</td>
			<td>
				استخدم طبقة المقبس الآمنة لتشفير الجلسة
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/validate-cert
			</td>
			<td>
				‫ترخيص من خادم <abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr>/<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>
			</td>
			<td>
				 
			</td>
			<td>
				enabled
			</td>
		</tr>
<tr>
<td>
				‎/novalidate-cert
			</td>
			<td>
				‫لا تتحقق من شهادات الخادم <abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr>/<abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>، نحتاجها إذا كان الخادم يستخدم شهادات ذاتية التوقيع، استخدم هذه الراية بحذر
			</td>
			<td>
				 
			</td>
			<td>
				disabled
			</td>
		</tr>
<tr>
<td>
				‎/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr>
			</td>
			<td>
				‫فرض استخدام طريقة start-<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr> لتشفير الجلسة ورفض الاتصال بالخوادم التي لا تدعمها
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/notls
			</td>
			<td>
				لا تستخدم طريقة start-<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr> لتشفير الجلسة حتى لو كانت الخوادم تدعمها
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				‎/readonly
			</td>
			<td>
				‫طلب فتح صندوق البريد للقراءة فقط (في IMAP فقط، يتم تجاهلها مع NNTP ويعطي خطأ مع SMTP وPOP3)
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	ستبدو سلسلة الاتصال بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_7" style="">
<span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّه إذا كان أي محرف في سلسة الاتصال غير مرمّز بالترميز ASCII فيجب ترميزه باستخدام <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imap-utf7-encode.php" rel="">utf7_encode($string)‎</a>.
</p>

<p>
	نستخدم الأمر <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imap-open.php" rel="">imap open</a> للاتصال إلى صندوق البريد، يعيد هذا الأمر قيمة مورد تشير إلى مجرى:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_9" style="">
<span class="pun">&lt;?</span><span class="pln">php
$mailbox </span><span class="pun">=</span><span class="pln"> imap_open</span><span class="pun">(</span><span class="str">"{imap.example.com:993/imap/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr>/secure}"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"username"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"password"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$mailbox </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Failed to connect to server"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	تحميل الإضافة IMAP
</h2>

<p>
	نحتاج لتثبيت الإضافة IMAP حتى نتمكن من استخدام <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttp://www.php.net/imap" rel="">دوال IMAP</a> في PHP.
</p>

<p>
	التثبيت في نظام ديبيان/أبونتو مع PHP5
</p>

<pre class="ipsCode">
sudo apt-get install php5-imap
sudo php5enmod imap
</pre>

<p>
	التثبيت في نظام ديبيان/أبونتو مع PHP5
</p>

<pre class="ipsCode">
sudo apt-get install php7.0-imap
</pre>

<p>
	التثبيت في التوزيعات المعتمدة على YUM
</p>

<pre class="ipsCode">
sudo yum install php-imap
</pre>

<p>
	التثبيت في إصدارات نظام التشغيل ماك مع php5.6
</p>

<pre class="ipsCode">
brew reinstall php56 --with-imap
</pre>

<h2>
	إنشاء قائمة بكل مجلدات صندوق البريد
</h2>

<p>
	عندما تتصل بصندوق البريد الخاص بك، سترغب في إلقاء نظرة بداخله، الأمر الأول المفيد في هذه الحالة هو <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imap-list.php" rel="">imap list</a>، المعامل الأول هو المورد الذي حصلت عليه من <code>imap_open</code> والثاني هو صندوق البريد الخاص بك والثالث سلسلة بحث غامضة (نستخدم * لمطابقة أي نمط).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_12" style="">
<span class="pln">$folders </span><span class="pun">=</span><span class="pln"> imap_list</span><span class="pun">(</span><span class="pln">$mailbox</span><span class="pun">,</span><span class="pln"> </span><span class="str">"{imap.example.com:993/imap/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr>/secure}"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"*"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$folders </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Failed to list folders in mailbox"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    print_r</span><span class="pun">(</span><span class="pln">$folders</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب أن يكون الخرج مشابهًا للتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_14" style="">
<span class="typ">Array</span><span class="pln">
</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span><span class="pln">INBOX
    </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span><span class="pln">INBOX</span><span class="pun">.</span><span class="typ">Sent</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span><span class="pln">INBOX</span><span class="pun">.</span><span class="typ">Drafts</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span><span class="pln">INBOX</span><span class="pun">.</span><span class="typ">Junk</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">4</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span><span class="pln">INBOX</span><span class="pun">.</span><span class="typ">Trash</span><span class="pln">
</span><span class="pun">)</span></pre>

<p>
	يمكننا استخدام المعامل الثالث لترشيح هذه النتائج بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_16" style="">
<span class="pln">$folders </span><span class="pun">=</span><span class="pln"> imap_list</span><span class="pun">(</span><span class="pln">$mailbox</span><span class="pun">,</span><span class="pln"> </span><span class="str">"{imap.example.com:993/imap/<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr>/secure}"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"*.Sent"</span><span class="pun">);</span></pre>

<p>
	عندها ستحتوي النتيجة على المداخل التي فيها السلسلة النصية <code>‎.Sent</code> في الاسم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_18" style="">
<span class="typ">Array</span><span class="pln">
</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imap</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">:</span><span class="lit">993</span><span class="pun">/</span><span class="pln">imap</span><span class="pun">/</span><span class="pln"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">tls</abbr></span><span class="pun">/</span><span class="pln">secure</span><span class="pun">}</span><span class="pln">INBOX</span><span class="pun">.</span><span class="typ">Sent</span><span class="pln">
</span><span class="pun">)</span></pre>

<p>
	<strong>ملاحظة:</strong> سيعيد استخدام * للبحث الغامض كل التطابقات بشكلٍ متكرر، ويعيد استخدام % التطابقات في المجلد الحالي المحدد فقط.
</p>

<h2>
	البحث عن الرسائل في صندوق البريد
</h2>

<p>
	يمكنك أن تستخدم <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imap-headers.php%E2%80%8F" rel="">imap_headers</a> لتحصل على قائمة بكل الرسائل الموجودة في صندوق البريد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_20" style="">
<span class="pun">&lt;?</span><span class="pln">php
$headers </span><span class="pun">=</span><span class="pln"> imap_headers</span><span class="pun">(</span><span class="pln">$mailbox</span><span class="pun">);</span></pre>

<p>
	تكون النتيجة مصفوفة من السلاسل النصية بالنمط التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_22" style="">
<span class="pun">[</span><span class="pln">FLAG</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="pln">MESSAGE</span><span class="pun">-</span><span class="pln">ID</span><span class="pun">])[</span><span class="pln">DD</span><span class="pun">-</span><span class="pln">MM</span><span class="pun">-</span><span class="pln">YYY</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="pln">FROM ADDRESS</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="pln">SUBJECT TRUNCATED TO </span><span class="lit">25</span><span class="pln"> CHAR</span><span class="pun">]</span><span class="pln"> </span><span class="pun">([</span><span class="pln">SIZE</span><span class="pun">]</span><span class="pln"> chars</span><span class="pun">)</span></pre>

<p>
	إليك عينة عن الشكل الذي سيبدو عليه كل سطر:
</p>

<pre class="ipsCode">
A     1)19-Aug-2016 someone@example.com Message Subject (1728 chars)
D     2)19-Aug-2016 someone@example.com RE: Message Subject (22840 chars)
U     3)19-Aug-2016 someone@example.com RE: RE: Message Subject (1876 chars)
N     4)19-Aug-2016 someone@example.com RE: RE: RE: Message Subje (1741 chars)
</pre>

<table>
<thead><tr>
<th>
				الرمز
			</th>
			<th>
				الراية
			</th>
			<th>
				المعنى
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				A
			</td>
			<td>
				Answered
			</td>
			<td>
				تم الرد على هذه الرسالة
			</td>
		</tr>
<tr>
<td>
				D
			</td>
			<td>
				Deleted
			</td>
			<td>
				‫حُذفت الرسالة (ولم تُزال نهائيًا)
			</td>
		</tr>
<tr>
<td>
				F
			</td>
			<td>
				Flagged
			</td>
			<td>
				مُيِّزت هذه الرسالة للفت الانتباه
			</td>
		</tr>
<tr>
<td>
				N
			</td>
			<td>
				New
			</td>
			<td>
				الرسالة جديدة ولم تُقرأ بعد
			</td>
		</tr>
<tr>
<td>
				R
			</td>
			<td>
				Recent
			</td>
			<td>
				الرسالة جديدة ومقروءة
			</td>
		</tr>
<tr>
<td>
				U
			</td>
			<td>
				Unread
			</td>
			<td>
				الرسالة لم تُقرأ بعد
			</td>
		</tr>
<tr>
<td>
				X
			</td>
			<td>
				Draft
			</td>
			<td>
				الرسالة مسودة
			</td>
		</tr>
</tbody>
</table>
<p>
	لاحظ أنّ هذا الاستدعاء سيأخذ بعض الوقت ليُنفَّذ وقد يعيد قائمة طويلة جدًا، الخيار البديل هو تحميل الرسائل بشكلٍ منفصل وفقًا للحاجة، يُسند معرِّف لكل بريد إلكتروني من الرقم 1 (الأقدم) وحتى قيمة <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imap-num-msg.php" rel="">imap_num_msg($mailbox)‎</a>.
</p>

<p>
	يوجد عدة دوال للوصول إلى بريد إلكتروني مباشرةً، لكن أبسط طريقة هي استخدام الدالة <a data-ss1616972841="1" data-ss1616973115="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.imap-header.php" rel="">imap_header</a> التي تُرجع معلومات ترويسة مهيكلة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9745_25" style="">
<span class="pun">&lt;?</span><span class="pln">php
$header </span><span class="pun">=</span><span class="pln"> imap_headerinfo</span><span class="pun">(</span><span class="pln">$mailbox </span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
stdClass </span><span class="typ">Object</span><span class="pln">
</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">date</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Wed</span><span class="pun">,</span><span class="pln"> </span><span class="lit">19</span><span class="pln"> </span><span class="typ">Oct</span><span class="pln"> </span><span class="lit">2011</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">34</span><span class="pun">:</span><span class="lit">52</span><span class="pln"> </span><span class="pun">+</span><span class="lit">0000</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">subject</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Message</span><span class="pln"> </span><span class="typ">Subject</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">message_id</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">&lt;</span><span class="lit">04b80ceedac8e74</span><span class="pln">$51a8d50dd$0206600a@user1687763490</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">references</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">ec129beef8a113c941ad68bdaae9@example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">toaddress</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="typ">Else</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">someoneelse@example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">to</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Array</span><span class="pln">
        </span><span class="pun">(</span><span class="pln">
            </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stdClass </span><span class="typ">Object</span><span class="pln">
                </span><span class="pun">(</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">personal</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="typ">Else</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">mailbox</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> someonelse
                    </span><span class="pun">[</span><span class="pln">host</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> example</span><span class="pun">.</span><span class="pln">com
                </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">fromaddress</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">someone@example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="kwd">from</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Array</span><span class="pln">
        </span><span class="pun">(</span><span class="pln">
            </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stdClass </span><span class="typ">Object</span><span class="pln">
                </span><span class="pun">(</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">personal</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">mailbox</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> someone
                    </span><span class="pun">[</span><span class="pln">host</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> example</span><span class="pun">.</span><span class="pln">com
                </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">reply_toaddress</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">someone@example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">reply_to</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Array</span><span class="pln">
        </span><span class="pun">(</span><span class="pln">
            </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stdClass </span><span class="typ">Object</span><span class="pln">
                </span><span class="pun">(</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">personal</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">mailbox</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> someone
                    </span><span class="pun">[</span><span class="pln">host</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> example</span><span class="pun">.</span><span class="pln">com
                </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">senderaddress</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">someone@example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">sender</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Array</span><span class="pln">
        </span><span class="pun">(</span><span class="pln">
            </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stdClass </span><span class="typ">Object</span><span class="pln">
                </span><span class="pun">(</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">personal</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Some</span><span class="pln"> </span><span class="typ">One</span><span class="pln">
                    </span><span class="pun">[</span><span class="pln">mailbox</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> someone
                    </span><span class="pun">[</span><span class="pln">host</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> example</span><span class="pun">.</span><span class="pln">com
                </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Recent</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Unseen</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Flagged</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Answered</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Deleted</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Draft</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Msgno</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">MailDate</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">19</span><span class="pun">-</span><span class="typ">Oct</span><span class="pun">-</span><span class="lit">2011</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">34</span><span class="pun">:</span><span class="lit">48</span><span class="pln"> </span><span class="pun">+</span><span class="lit">0000</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Size</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1728</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">udate</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1319038488</span><span class="pln">
</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [IMAP] من كتاب <a data-ss1616972841="1" data-ss1616973115="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-cli-%D9%81%D9%8A-php-r1176/" rel="">التعامل مع واجهة سطر الأوامر (CLI) في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%B1%D8%B3%D8%A7%D9%84-%D8%A8%D8%B1%D9%8A%D8%AF-%D8%A5%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A-%D9%81%D9%8A-php-r1174/" rel="">كيفية إرسال بريد إلكتروني في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1175</guid><pubDate>Sat, 20 Mar 2021 13:00:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x631;&#x633;&#x627;&#x644; &#x628;&#x631;&#x64A;&#x62F; &#x625;&#x644;&#x643;&#x62A;&#x631;&#x648;&#x646;&#x64A; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%B1%D8%B3%D8%A7%D9%84-%D8%A8%D8%B1%D9%8A%D8%AF-%D8%A5%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A-%D9%81%D9%8A-php-r1174/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/2.png.88046fd354768d8e201a0f8c1f0cfa44.png" /></p>

<p>
	معاملات الدالة <code>mail()‎</code> في PHP:
</p>

<table>
<thead><tr>
<th>
				المعامل
			</th>
			<th>
				تفاصيل
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				string $to
			</td>
			<td>
				عنوان البريد الإلكتروني للمستقبل
			</td>
		</tr>
<tr>
<td>
				string $subject
			</td>
			<td>
				الموضوع
			</td>
		</tr>
<tr>
<td>
				string $message
			</td>
			<td>
				محتوى البريد الإلكتروني
			</td>
		</tr>
<tr>
<td>
				string $additional_headers
			</td>
			<td>
				معامل اختياري: ترويسات لإضافتها إلى البريد الإلكتروني
			</td>
		</tr>
<tr>
<td>
				string $additional_parameters
			</td>
			<td>
				معامل اختياري: وسائط لتمريرها إلى تطبيق البريد الإلكتروني المرسل المُعد في سطر الأوامر
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<h2>
	أساسيات إرسال بريد إلكتروني مع مثال
</h2>

<p>
	يتألف البريد الإلكتروني النموذجي من ثلاثة مكونات أساسية:
</p>

<ul>
<li>
		مُستقبِل (يُمثَّل كعنوان بريد إلكتروني)
	</li>
	<li>
		موضوع
	</li>
	<li>
		جسم الرسالة
	</li>
</ul>
<p>
	يمكن أن يكون إرسال بريد إلكتروني بسيطًا مثل استدعاء الدالة المضمنة <code>mail()‎</code>، تأخذ هذه الدالة حتى 5 معاملات، أول ثلاث معاملات هي المطلوبة فقط لإرسال بريد إلكتروني (ومن الشائع استخدام المعامل الرابع كما سنوضح في المثال أدناه)، المعاملات الثلاثة الأولى هي:
</p>

<ul>
<li>
		عنوان البريد الإلكتروني للمستقبل (سلسلة نصية).
	</li>
	<li>
		موضوع البريد الإلكتروني (سلسلة نصية).
	</li>
	<li>
		جسم البريد الإلكتروني (سلسلة نصية) (أي محتوى البريد الإلكتروني).
	</li>
</ul>
<p>
	الشيفرة التالية توضح مثال بسيط:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_7" style="">
<span class="pln">mail</span><span class="pun">(</span><span class="str">'recipient@example.com'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Email Subject'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'This is the email message body'</span><span class="pun">);</span></pre>

<p>
	يعدّ المثال السابق جيدًا في بعض الحالات مثل توفير القيمة في شيفرة (بدلًا من جلبها من مصدر خارجي) عند إرسال بريد إلكتروني للتنبيه في نظام داخلي. لكن من الشائع وضع المعاملات الممررة كمعاملات للدالة <code>mail()‎</code> في متغيرات لجعل الشيفرة أنظف وأسهل في الإدارة (مثلًا لإنشاء بريد إلكتروني ديناميكي بعد إرسال نموذج).
</p>

<p>
	بالإضافة إلى ذلك تقبل الدالة <code>mail()‎</code> معاملًا رابعًا يسمح لك بإضافة ترويسات في البريد الإلكتروني المرسل، يمكن أن تسمح لك هذه الترويسات بضبط:
</p>

<ul>
<li>
		اسم المرسل وعنوان البريد الإلكتروني الذي سيظهر لدى المستخدم.
	</li>
	<li>
		عنوان البريد الإلكتروني للحقل <code>Reply-To</code> والذي سيُرسل إليه رد المستخدم.
	</li>
	<li>
		ترويسات إضافية غير معيارية مثل <code>X-Mailer</code> والتي تخبر المستقبل أن هذا البريد الإلكتروني أُرسل عبر PHP.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_9" style="">
<span class="com">// ‫يمكن أن تكون ‎$to = $_POST['recipient'];‎</span><span class="pln">
$to </span><span class="pun">=</span><span class="pln"> </span><span class="str">'recipient@example.com'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫يمكن أن تكون ‎$subject = $_POST['subject'];‎</span><span class="pln">
$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Email Subject'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫يمكن أن تكون ‎$message = $_POST['message'];‎</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'This is the email message body'</span><span class="pun">;</span><span class="pln">

$headers </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'From: John Conde &lt;webmaster@example.com&gt;'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Reply-To: webmaster@example.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'X-Mailer: PHP/'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_VERSION
</span><span class="pun">]);</span></pre>

<p>
	يمكن أن يُستخدم المعامل الخامس الاختياري لتمرير رايات إضافية مثل خيارات سطر الأوامر إلى البرنامج المُعدّ ليستخدم عند إرسال بريد إلكتروني كما هو معرَّف في ضبط الإعداد <code>sendmail_path</code>، يمكن استخدامه مثلًا لضبط عنوان المرسل عند استخدام الأمر <code>sendmail/postfix</code> مع الخيار <code>‎-f</code> لإرسال بريد إلكتروني.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_11" style="">
<span class="pln">$fifth </span><span class="pun">=</span><span class="pln"> </span><span class="str">'-fno-reply@example.com'</span><span class="pun">;</span></pre>

<p>
	على الرغم من أن استخدام الدالة <code>mail()‎</code> يمكن أن يكون موثوقًا إلى حد كبير، إلا أنّه لا يوجد ما يضمن إرسال البريد الإلكتروني عند كل استدعاء لها، لذا يجب أن تلتقط القيمة المُرجعة منها لتعرف ما إذا كان هناك خطأ محتمل عند إرسال بريدك الإلكتروني، إذ أنّ الدالة ستُرجع القيمة <code>TRUE</code> إذا قُبل البريد الإلكتروني بنجاح للتسليم وإلا ستُرجع القيمة <code>FALSE</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_15" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> mail</span><span class="pun">(</span><span class="pln">$to</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $message</span><span class="pun">,</span><span class="pln"> $headers</span><span class="pun">,</span><span class="pln"> $fifth</span><span class="pun">);</span></pre>

<p>
	<strong>ملاحظة:</strong> إنّ إرجاع الدالة <code>mail()‎</code> للقيمة <code>TRUE</code> لا يعني أنّ البريد الإلكتروني أُرسل أو أنّه سيُستقبَل بنجاح، إنما فقط يدل على أنّ البريد الإلكتروني سُلِّم بنجاح إلى نظام البريد الإلكتروني الخاص بك.
</p>

<p>
	تحتاج إلى بعض الخطوات الإضافية لترسل بريد إلكتروني بصيغة HTML:
</p>

<ul>
<li>
		إضافة الترويسة <code>MIME-Version</code>.
	</li>
	<li>
		إضافة الترويسة <code>Content-Type</code>.
	</li>
	<li>
		التأكد من أنّ محتوى البريد الإلكتروني بصيغة HTML.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_17" style="">
<span class="pln">$to </span><span class="pun">=</span><span class="pln"> </span><span class="str">'recipient@example.com'</span><span class="pun">;</span><span class="pln">
$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Email Subject'</span><span class="pun">;</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;&lt;body&gt;This is the email message body&lt;/body&gt;&lt;/html&gt;'</span><span class="pun">;</span><span class="pln">
$headers </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'From: John Conde &lt;webmaster@example.com&gt;'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Reply-To: webmaster@example.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'MIME-Version: 1.0'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Content-Type: text/html; charset=ISO-8859-1'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'X-Mailer: PHP/'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_VERSION
</span><span class="pun">]);</span></pre>

<p>
	إليك مثال كامل لاستخدام الدالة <code>mail()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_19" style="">
<span class="com">// ‫أدوات تنقيح الأخطاء، شغّلها في بيئة التطوير الخاصة بك فقط.</span><span class="pln">
error_reporting</span><span class="pun">(-</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
ini_set</span><span class="pun">(</span><span class="str">'display_errors'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'On'</span><span class="pun">);</span><span class="pln">
set_error_handler</span><span class="pun">(</span><span class="str">"var_dump"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫إعدادات بريد إلكتروني خاصة يمكن أن تقلل من احتمال جعل البريد الإلكتروني الخاص بك غير مرغوب فيه وتوفر تسجيل دخول في حالة وجود صعوبات تقنية.</span><span class="pln">
ini_set</span><span class="pun">(</span><span class="str">"mail.log"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/tmp/mail.log"</span><span class="pun">);</span><span class="pln">
ini_set</span><span class="pun">(</span><span class="str">"mail.add_x_header"</span><span class="pun">,</span><span class="pln"> TRUE</span><span class="pun">);</span><span class="pln">

</span><span class="com">// مكونات بريدنا الإلكتروني</span><span class="pln">
$to </span><span class="pun">=</span><span class="pln"> </span><span class="str">'recipient@example.com'</span><span class="pun">;</span><span class="pln">
$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Email Subject'</span><span class="pun">;</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'This is the email message body'</span><span class="pun">;</span><span class="pln">
$headers </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'From: webmaster@example.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Reply-To: webmaster@example.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'X-Mailer: PHP/'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_VERSION
</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// إرسال البريد الإلكتروني</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> mail</span><span class="pun">(</span><span class="pln">$to</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $message</span><span class="pun">,</span><span class="pln"> $headers</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫التحقق من النتائج والتفاعل وفقًا لذلك.</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$result</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: http://example.com/path/to/thank-you.php'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="lit">303</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (2)</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) تكون الدالة أرجعت القيمة <code>TRUE</code> وسيُعاد التوجيه إلى صفحة <code>thank-you</code>، نستخدم النمط <code>POST/REDIRECT/GET</code> لمنع إعادة إرسال النموذج عندما يحدّث المستخدم الصفحة.
</p>

<p>
	في الموضع (2) لم يُرسل البريد الإلكتروني، تحقق من السجلات لمعرفة السبب.
</p>

<p>
	يمكنك الاطلاع أيضًا على: التوثيق الرسمي:
</p>

<ul>
<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttp://php.net/manual/en/function.mail.php" rel="">mail</a>
	</li>
	<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://www.php.net/manual/en/mail.configuration.php" rel="">إعدادات الدالة mail</a>
	</li>
</ul>
<p>
	أسئلة ذات صلة من موقع stack overflow:
</p>

<ul>
<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://stackoverflow.com/questions/24644436/php-mail-function-doesnt-complete-sending-of-e-mail" rel="">الدالة mail لا تُكمل إرسال البريد الإلكتروني</a>.
	</li>
	<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://stackoverflow.com/questions/371/how-do-you-make-sure-email-you-send-programmatically-is-not-automatically-marked" rel="">كيف تتأكد من أنّ بريدك الإلكتروني المُرسل لا يُصنف ضمن البريد الإلكتروني غير المرغوب فيه</a>.
	</li>
	<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="https://stackoverflow.com/questions/15965376/how-to-configure-xampp-to-send-mail-from-localhost/18185233#18185233" rel="external nofollow">كيف تستخدم SMTP لإرسال بريد إلكتروني</a>.
	</li>
	<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="https://stackoverflow.com/questions/5666312/php-mail-issue-with-www-data/5666682#5666682" rel="external nofollow">ضبط إعدادات مرسل البريد الإلكتروني</a>.
	</li>
</ul>
<p>
	خدمات بريد إلكتروني بديلة:
</p>

<ul>
<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://github.com/Synchro/PHPMailer" rel="">PHPMailer‏</a>
	</li>
	<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://swiftmailer.symfony.com/" rel="">SwiftMailer</a>
	</li>
	<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://pear.php.net/package/Mail" rel="">PEAR::Mail</a>
	</li>
</ul>
<p>
	مخدمات بريد إلكتروني:
</p>

<ul>
<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttp://www.pmail.com/overviews/ovw_mercury.htm%E2%80%8F" rel="">Mercury Mail (Windows)</a>
	</li>
</ul>
<p>
	مواضيع ذات صلة:
</p>

<ul>
<li>
		<a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="%E2%80%8Fhttps://en.wikipedia.org/wiki/Post/Redirect/Get" rel="">Post/Redirect/Get</a>
	</li>
</ul>
<h2>
	إرسال بريد إلكتروني يحتوي على صيغة HTML باستخدام الدالة mail()‎
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_21" style="">
<span class="pun">&lt;?</span><span class="pln">php
$to </span><span class="pun">=</span><span class="pln"> </span><span class="str">'recipent@example.com'</span><span class="pun">;</span><span class="pln">
$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Sending an HTML email using mail() in PHP'</span><span class="pun">;</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;html&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;This paragraph is bold.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;This text is italic.&lt;/i&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;'</span><span class="pun">;</span><span class="pln">

$headers </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">"From: John Conde &lt;webmaster@example.com&gt;"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Reply-To: webmaster@example.com"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"X-Mailer: PHP/"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_VERSION</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"MIME-Version: 1.0"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Content-Type: text/html; charset=UTF-8"</span><span class="pln">
</span><span class="pun">]);</span><span class="pln">

mail</span><span class="pun">(</span><span class="pln">$to</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $message</span><span class="pun">,</span><span class="pln"> $headers</span><span class="pun">);</span></pre>

<p>
	لا يختلف هذا كثيرًا عن إرسال بريد إلكتروني يحتوي على نص بسيط⁢، الاختلافات الرئيسة هي أنّ المحتوى عبارة عن ملف HTML ويوجد ترويستين إضافيتين يجب تضمينهما حتى يعرف البريد الإلكتروني للعميل أنّ البريد الإلكتروني بصيغة HTML وهما:
</p>

<ul>
<li>
		<code>MIME-Version: 1.0</code>
	</li>
	<li>
		<code>Content-Type: text/html; charset=UTF-8</code>
	</li>
</ul>
<h2>
	إرسال بريد إلكتروني مع مرفق باستخدام الدالة mail()‎
</h2>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_23" style="">
<span class="pun">&lt;?</span><span class="pln">php
$to </span><span class="pun">=</span><span class="pln"> </span><span class="str">'recipient@example.com'</span><span class="pun">;</span><span class="pln">
$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Email Subject'</span><span class="pun">;</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'This is the email message body'</span><span class="pun">;</span><span class="pln">
$attachment </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/path/to/your/file.pdf'</span><span class="pun">;</span><span class="pln">
$content </span><span class="pun">=</span><span class="pln"> file_get_contents</span><span class="pun">(</span><span class="pln">$attachment</span><span class="pun">);</span><span class="pln">

</span><span class="com">// (1)</span><span class="pln">
$content </span><span class="pun">=</span><span class="pln"> chunk_split</span><span class="pun">(</span><span class="pln">base64_encode</span><span class="pun">(</span><span class="pln">$content</span><span class="pun">));</span><span class="pln">

</span><span class="com">//(2)</span><span class="pln">
$prefix </span><span class="pun">=</span><span class="pln"> </span><span class="str">"part_"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// (3)</span><span class="pln">

</span><span class="com">// (4)</span><span class="pln">
$boundary </span><span class="pun">=</span><span class="pln"> uniqid</span><span class="pun">(</span><span class="pln">$prefix</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الترويسات</span><span class="pln">
$headers </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'From: webmaster@example.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Reply-To: webmaster@example.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'X-Mailer: PHP/'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_VERSION</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'MIME-Version: 1.0'</span><span class="pun">,</span><span class="pln">

    </span><span class="com">// معامل الحد مطلوب ويجب أن يكون ضمن علامات اقتباس</span><span class="pln">
    </span><span class="str">'Content-Type: multipart/mixed; boundary="'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $boundary </span><span class="pun">.</span><span class="pln"> </span><span class="str">'"'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Content-Transfer-Encoding: 7bit"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"This is a MIME encoded message."</span><span class="pln"> </span><span class="com">// message for restricted transports</span><span class="pln">
</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// الرسالة والمرفق</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">"--"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $boundary</span><span class="pun">,</span><span class="pln"> </span><span class="com">// (5)</span><span class="pln">
    </span><span class="str">'Content-Type: text/plain; charset="iso-8859-1"'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Content-Transfer-Encoding: 8bit"</span><span class="pun">,</span><span class="pln">
    $message</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"--"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $boundary</span><span class="pun">,</span><span class="pln"> </span><span class="com">// (6)</span><span class="pln">
    </span><span class="str">'Content-Type: application/octet-stream; name="RenamedFile.pdf"'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Content-Transfer-Encoding: base64"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Content-Disposition: attachment"</span><span class="pun">,</span><span class="pln">
    $content</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"--"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $boundary </span><span class="pun">.</span><span class="pln"> </span><span class="str">"--"</span><span class="pln"> </span><span class="com">// (7)</span><span class="pln">
</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// إرسال البريد الإلكتروني</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> mail</span><span class="pun">(</span><span class="pln">$to</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $message</span><span class="pun">,</span><span class="pln"> $headers</span><span class="pun">);</span><span class="pln"> 

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$result</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (8)</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: http://example.com/path/to/thank-you.php'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="lit">303</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (9)</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) يجب تقسيم محتوى المرفق المُرسل باستخدام تشفير <code>Base64</code> إلى أجزاء بطول 76 محرفًا كما هو محدد في القسم 6.8 من RFC 2045، تستخدم الدالة <code>chunk_split()‎</code> بشكلٍ افتراضي طول الجزء 76 مع <code>CRLF</code> زائدة <code>‎(\r\n)‎</code>، لا يتضمن متطلب 76 محرفًا المحارف <code>carriage return</code> و<code>line feed</code>.
</p>

<p>
	في الموضع (2) تحدد الحدود الكيانات متعددة الأجزاء، يجب ألا يكون الحد في أي جزء مغلف كما هو مذكور في القسم 5.1 من RFC 2046 لذا يجب أن يكون فريدًا، وكما هو مذكور في القسم 5.1.1 التالي فإنّ الحدّ يُعرَّف على أنّه خط يتألف من موصلين ("--") وقيمة معامل ومسافة خطية اختيارية و<code>CRLF</code> نهائية.
</p>

<p>
	في الموضع (3) بادئة اختيارية.
</p>

<p>
	في الموضع (4) إنشاء قيمة معامل حد فريدة مع البادئة باستخدام الدالة <code>uniqid()‎</code>، المعامل الثاني يجعل قيمة المعامل فريدة أكثر.
</p>

<p>
	في الموضع (5) محدد حد الترويسة
</p>

<p>
	في الموضع (6) محدد حد المحتوى
</p>

<p>
	في الموضع (7) محدد حد الإغلاق
</p>

<p>
	في الموضع (8) تكون الدالة أرجعت القيمة <code>TRUE</code> وسيُعاد التوجيه إلى صفحة <code>thank-you</code>، نستخدم النمط <code>POST/REDIRECT/GET</code> لمنع إعادة إرسال النموذج عندما يحدّث المستخدم الصفحة.
</p>

<p>
	في الموضع (9) لم يُرسل البريد الإلكتروني، تحقق من السجلات لمعرفة السبب.
</p>

<h3>
	ترميز نقل المحتوى
</h3>

<p>
	الترميزات المتاحة هي 7 بت، 8 بت، الثنائي، مقتبس قابل للطباعة (quoted-printable)، الأساس 64 (base64)، ‏ietf-token وx-token، من هذه الترميزات عندما يكون <code>Content-Type</code> متعدد الأجزاء فإنّ ترميز نقل المحتوى يجب ألّا يكون أي قيمة أخرى غير 7 بت أو 8 بت أو ثنائي.
</p>

<p>
	نختار في مثالنا ترميز 7 بت الذي يمثّل محارف US-ASCII للترويسة متعددة الأجزاء لأنّ بعض البروتوكولات تدعم هذا الترميز فقط، ويمكن بعدها تشفير البيانات ضمن الحدود على أساس كل جزء على حدة، وهذا ما يفعله هذا المثال بالضبط. الجزء الأول الذي يتضمن رسالة من النوع <code>text/plain</code> يُعرَّف على أنّه 8 بت بما أنّه قد يكون من الضروري أن يدعم محارف إضافية، في هذه الحالة تُستخدم مجموعة المحارف <code>Latin1 (iso-8859-1)‎</code>، الجزء الثاني هو المرفق لذا يُعرَّف على أنّه بترميز الأساس 64 <code>application/octet-stream</code>. بما أنّ الأساس 64 يحوّل البيانات إلى المجال 7 بت، يمكن أن تُرسَل عبر عمليات نقل مقيدة.
</p>

<h2>
	إرسال بريد إلكتروني يحتوي على نص بسيط باستخدام PHPMailer
</h2>

<p>
	<strong>بريد إلكتروني يحتوي على نص بسيط</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_25" style="">
<span class="pun">&lt;?</span><span class="pln">php
$mail </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PHPMailer</span><span class="pun">();</span><span class="pln">

$mail</span><span class="pun">-&gt;</span><span class="typ">From</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"from@example.com"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">FromName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Full Name"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addReplyTo</span><span class="pun">(</span><span class="str">"reply@example.com"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Reply Address"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Subject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Subject Text"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Body</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"This is a sample basic text email using PHPMailer."</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$mail</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: http://example.com/path/to/thank-you.php'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="lit">303</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Mailer Error: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $mail</span><span class="pun">-&gt;</span><span class="typ">ErrorInfo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) تكون الدالة أرجعت القيمة <code>TRUE</code> وسيُعاد التوجيه إلى صفحة <code>thank-you</code>، نستخدم النمط <code>POST/REDIRECT/GET</code> لمنع إعادة إرسال النموذج عندما يحدّث المستخدم الصفحة.
</p>

<p>
	<strong>إضافة مستقبلين إضافيين، مستقبلين نسخة إضافية (CC)، مستقبلين نسخة إضافية محجوبين (BCC)</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_27" style="">
<span class="pun">&lt;?</span><span class="pln">php
$mail </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PHPMailer</span><span class="pun">();</span><span class="pln">

$mail</span><span class="pun">-&gt;</span><span class="typ">From</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"from@example.com"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">FromName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Full Name"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addReplyTo</span><span class="pun">(</span><span class="str">"reply@example.com"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Reply Address"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addAddress</span><span class="pun">(</span><span class="str">"recepient1@example.com"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Recepient Name"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addAddress</span><span class="pun">(</span><span class="str">"recepient2@example.com"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addCC</span><span class="pun">(</span><span class="str">"cc@example.com"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addBCC</span><span class="pun">(</span><span class="str">"bcc@example.com"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Subject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Subject Text"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Body</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"This is a sample basic text email using PHPMailer."</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$mail</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: http://example.com/path/to/thank-you.php'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="lit">303</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Error: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $mail</span><span class="pun">-&gt;</span><span class="typ">ErrorInfo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) تكون الدالة أرجعت القيمة <code>TRUE</code> وسيُعاد التوجيه إلى صفحة <code>thank-you</code>، نستخدم النمط <code>POST/REDIRECT/GET</code> لمنع إعادة إرسال النموذج عندما يحدّث المستخدم الصفحة.
</p>

<h2>
	إرسال بريد إلكتروني باستخدام PHPMailer
</h2>

<p>
	إليك مثال عن إرسال بريد إلكتروني يحتوي على صيغة HTML باستخدام PHPMailer:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_29" style="">
<span class="pun">&lt;?</span><span class="pln">php
$mail </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PHPMailer</span><span class="pun">();</span><span class="pln">

$mail</span><span class="pun">-&gt;</span><span class="typ">From</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"from@example.com"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">FromName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Full Name"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addReplyTo</span><span class="pun">(</span><span class="str">"reply@example.com"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Reply Address"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addAddress</span><span class="pun">(</span><span class="str">"recepient1@example.com"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Recepient Name"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addAddress</span><span class="pun">(</span><span class="str">"recepient2@example.com"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addCC</span><span class="pun">(</span><span class="str">"cc@example.com"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addBCC</span><span class="pun">(</span><span class="str">"bcc@example.com"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Subject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Subject Text"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">isHTML</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Body</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"&lt;html&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;This paragraph is bold.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;This text is
italic.&lt;/i&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">AltBody</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"This paragraph is not bold.\n\nThis text is not italic."</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$mail</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: http://example.com/path/to/thank-you.php'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="lit">303</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Error: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $mail</span><span class="pun">-&gt;</span><span class="typ">ErrorInfo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) تكون الدالة أرجعت القيمة <code>TRUE</code> وسيُعاد التوجيه إلى صفحة <code>thank-you</code>، نستخدم النمط <code>POST/REDIRECT/GET</code> لمنع إعادة إرسال النموذج عندما يحدّث المستخدم الصفحة.
</p>

<h2>
	إرسال بريد إلكتروني مع مرفق باستخدام PHPMailer
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_31" style="">
<span class="pun">&lt;?</span><span class="pln">php
$mail </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PHPMailer</span><span class="pun">();</span><span class="pln">

$mail</span><span class="pun">-&gt;</span><span class="typ">From</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"from@example.com"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">FromName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Full Name"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="pln">addReplyTo</span><span class="pun">(</span><span class="str">"reply@example.com"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Reply Address"</span><span class="pun">);</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Subject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Subject Text"</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">Body</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"This is a sample basic text email with an attachment using PHPMailer."</span><span class="pun">;</span><span class="pln">

</span><span class="com">// إضافة مرفق ثابت</span><span class="pln">
$attachment </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/path/to/your/file.pdf'</span><span class="pun">;</span><span class="pln">
$mail</span><span class="pun">-&gt;</span><span class="typ">AddAttachment</span><span class="pun">(</span><span class="pln">$attachment </span><span class="pun">,</span><span class="pln"> </span><span class="str">'RenamedFile.pdf'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫إضافة مرفق ثانٍ يُنشأ وقت التنفيذ مثل CSV ليُفتح باستخدام إكسل</span><span class="pln">
$csvHeader </span><span class="pun">=</span><span class="pln"> </span><span class="str">"header1,header2,header3"</span><span class="pun">;</span><span class="pln">
$csvData </span><span class="pun">=</span><span class="pln"> </span><span class="str">"row1col1,row1col2,row1col3\nrow2col1,row2col2,row2col3"</span><span class="pun">;</span><span class="pln">

$mail</span><span class="pun">-&gt;</span><span class="typ">AddStringAttachment</span><span class="pun">(</span><span class="pln">$csvHeader </span><span class="pun">.</span><span class="str">"\n"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $csvData</span><span class="pun">,</span><span class="pln"> </span><span class="str">'your-csv-file.csv'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'base64'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'application/vnd.ms-excel'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$mail</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: http://example.com/path/to/thank-you.php'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="lit">303</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Error: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $mail</span><span class="pun">-&gt;</span><span class="typ">ErrorInfo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) تكون الدالة أرجعت القيمة <code>TRUE</code> وسيُعاد التوجيه إلى صفحة <code>thank-you</code>، نستخدم النمط <code>POST/REDIRECT/GET</code> لمنع إعادة إرسال النموذج عندما يحدّث المستخدم الصفحة.
</p>

<h2>
	إرسال بريد إلكتروني يحتوي على نص بسيط باستخدام Sendgrid
</h2>

<p>
	<strong>بريد إلكتروني يحتوي على نص بسيط</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_33" style="">
<span class="pun">&lt;?</span><span class="pln">php
$sendgrid </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SendGrid</span><span class="pun">(</span><span class="str">"YOUR_SENDGRID_API_KEY"</span><span class="pun">);</span><span class="pln">
$email </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SendGrid</span><span class="pln">\Email</span><span class="pun">();</span><span class="pln">

$email</span><span class="pun">-&gt;</span><span class="pln">addTo</span><span class="pun">(</span><span class="str">"recipient@example.com"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setFrom</span><span class="pun">(</span><span class="str">"sender@example.com"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setSubject</span><span class="pun">(</span><span class="str">"Subject Text"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setText</span><span class="pun">(</span><span class="str">"This is a sample basic text email using "</span><span class="pun">);</span><span class="pln">

$sendgrid</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">(</span><span class="pln">$email</span><span class="pun">);</span></pre>

<p>
	<strong>إضافة مستقبلين إضافيين، مستقبلين نسخة إضافية (CC)، مستقبلين نسخة إضافية محجوبين (BCC)</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_35" style="">
<span class="pun">&lt;?</span><span class="pln">php
$sendgrid </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SendGrid</span><span class="pun">(</span><span class="str">"YOUR_SENDGRID_API_KEY"</span><span class="pun">);</span><span class="pln">
$email </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SendGrid</span><span class="pln">\Email</span><span class="pun">();</span><span class="pln">
$email</span><span class="pun">-&gt;</span><span class="pln">addTo</span><span class="pun">(</span><span class="str">"recipient@example.com"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setFrom</span><span class="pun">(</span><span class="str">"sender@example.com"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setSubject</span><span class="pun">(</span><span class="str">"Subject Text"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setHtml</span><span class="pun">(</span><span class="str">"&lt;html&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;This paragraph is bold.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;This text is italic.&lt;/i&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"</span><span class="pun">);</span><span class="pln">

$personalization </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Personalization</span><span class="pun">();</span><span class="pln">
$email </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Email</span><span class="pun">(</span><span class="str">"Recepient Name"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"recepient1@example.com"</span><span class="pun">);</span><span class="pln">
$personalization</span><span class="pun">-&gt;</span><span class="pln">addTo</span><span class="pun">(</span><span class="pln">$email</span><span class="pun">);</span><span class="pln">
$email </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Email</span><span class="pun">(</span><span class="str">"RecepientCC Name"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"recepient2@example.com"</span><span class="pun">);</span><span class="pln">
$personalization</span><span class="pun">-&gt;</span><span class="pln">addCc</span><span class="pun">(</span><span class="pln">$email</span><span class="pun">);</span><span class="pln">
$email </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Email</span><span class="pun">(</span><span class="str">"RecepientBCC Name"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"recepient3@example.com"</span><span class="pun">);</span><span class="pln">
$personalization</span><span class="pun">-&gt;</span><span class="pln">addBcc</span><span class="pun">(</span><span class="pln">$email</span><span class="pun">);</span><span class="pln">
$email</span><span class="pun">-&gt;</span><span class="pln">addPersonalization</span><span class="pun">(</span><span class="pln">$personalization</span><span class="pun">);</span><span class="pln">

$sendgrid</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">(</span><span class="pln">$email</span><span class="pun">);</span></pre>

<h2>
	إرسال بريد إلكتروني مع مرفق باستخدام Sendgrid
</h2>

<p>
	إليك الشيفرة الكاملة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6343_37" style="">
<span class="pun">&lt;?</span><span class="pln">php
$sendgrid </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SendGrid</span><span class="pun">(</span><span class="str">"YOUR_SENDGRID_API_KEY"</span><span class="pun">);</span><span class="pln">
$email </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SendGrid</span><span class="pln">\Email</span><span class="pun">();</span><span class="pln">

$email</span><span class="pun">-&gt;</span><span class="pln">addTo</span><span class="pun">(</span><span class="str">"recipient@example.com"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setFrom</span><span class="pun">(</span><span class="str">"sender@example.com"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setSubject</span><span class="pun">(</span><span class="str">"Subject Text"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setText</span><span class="pun">(</span><span class="str">"This is a sample basic text email using "</span><span class="pun">);</span><span class="pln">

$attachment </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/path/to/your/file.pdf'</span><span class="pun">;</span><span class="pln">
$content </span><span class="pun">=</span><span class="pln"> file_get_contents</span><span class="pun">(</span><span class="pln">$attachment</span><span class="pun">);</span><span class="pln">
$content </span><span class="pun">=</span><span class="pln"> chunk_split</span><span class="pun">(</span><span class="pln">base64_encode</span><span class="pun">(</span><span class="pln">$content</span><span class="pun">));</span><span class="pln">

$attachment </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Attachment</span><span class="pun">();</span><span class="pln">
$attachment</span><span class="pun">-&gt;</span><span class="pln">setContent</span><span class="pun">(</span><span class="pln">$content</span><span class="pun">);</span><span class="pln">
$attachment</span><span class="pun">-&gt;</span><span class="pln">setType</span><span class="pun">(</span><span class="str">"application/pdf"</span><span class="pun">);</span><span class="pln">
$attachment</span><span class="pun">-&gt;</span><span class="pln">setFilename</span><span class="pun">(</span><span class="str">"RenamedFile.pdf"</span><span class="pun">);</span><span class="pln">
$attachment</span><span class="pun">-&gt;</span><span class="pln">setDisposition</span><span class="pun">(</span><span class="str">"attachment"</span><span class="pun">);</span><span class="pln">
$email</span><span class="pun">-&gt;</span><span class="pln">addAttachment</span><span class="pun">(</span><span class="pln">$attachment</span><span class="pun">);</span><span class="pln">

$sendgrid</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">(</span><span class="pln">$email</span><span class="pun">);</span></pre>

<p>
	ترجمة -وبتصرف- للفصل [Sending Email] من كتاب <a data-ss1616971550="1" data-ss1616971841="1" data-ss1616972263="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%85%D9%84%D8%A7%D8%AD%D8%B8%D8%A7%D8%AA-%D8%AD%D9%88%D9%84-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%A8%D8%B1%D9%88%D8%AA%D9%88%D9%83%D9%88%D9%84-imap-%D9%81%D9%8A-php-r1175/" rel="">ملاحظات حول استعمال بروتوكول IMAP في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mongodb-%D9%88-redis-%D9%81%D9%8A-php-r1173/" rel="">استخدام MongoDB و Redis في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1174</guid><pubDate>Tue, 16 Mar 2021 13:00:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; MongoDB &#x648; Redis &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mongodb-%D9%88-redis-%D9%81%D9%8A-php-r1173/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/1.png.6189fd4f67aa96deb7fb5d996c2b4fa1.png" /></p>

<h2>
	كل شيء بين MongoDB و PHP
</h2>

<h3>
	المتطلبات
</h3>

<ul>
<li>
		خادم MongoDB يعمل على منفذ والذي هو 27017 عادةً. (اكتب <code>mongod</code> في موجه الأوامر لتشغيل خادم mongod)
	</li>
	<li>
		لغة <a href="https://wiki.hsoub.com/PHP" rel="external">php </a>مثبّتة إما باستخدام <code>cgi</code> أو <code>fpm</code> مع إضافة <code>MongoDB</code> (إضافة MongoDB لا توجد مع php بشكلٍ افتراضي).
	</li>
	<li>
		مكتبة المُنشئ (Composer) (‏mongodb/mongodb). نفّذ التعليمة <code>php composer.phar require "mongodb/mongodb=^1.0.0"‎</code> في المجلد الجذر للمشروع لتثبيت مكتبة MongoDB).
	</li>
</ul>
<p>
	إذا تأكدت من المتطلبات يمكنك بعدها الانتقال للخطوة التالية:
</p>

<ul>
<li>
		التحقق من تثبيت php: نفّذ التعليمة <code>php -v</code> في موجه الأوامر إذا لم تكن متأكدًا من أنّها مثبّتة لديك وستُرجع مايشبه التالي:
	</li>
</ul>
<pre class="ipsCode">
PHP 7.0.6 (cli) (built: Apr 28 2016 14:12:14) ( ZTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
</pre>

<ul>
<li>
		التحقق من تثبيت MongoDB: وذلك بتنفيذ التعليمة <code>mongo --version</code> والتي ستُرجع <code>MongoDB shell version: 3.2.6</code>.
	</li>
	<li>
		التحقق من تثبيت المُنشئ: وذلك بتنفيذ التعليمة <code>php composer.phar --version</code> التي ستُرجع <code>Composer version 1.2-dev (3d09c17b489cd29a0c0b3b11e731987e7097797d) 2016-08-30 16:12:39</code>.
	</li>
</ul>
<h3>
	الاتصال من php إلى MongoDB
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_7" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// ‫يجب أن يشير هذا المسار إلى المحمِّل التلقائي للمُنشئ من المكان حيث يجب أن تُحمَّل مكتبة MongoDB </span><span class="pln">
 </span><span class="kwd">require</span><span class="pln"> </span><span class="str">'vendor/autoload.php'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// استخدام اسم مستخدم وكلمة مرور مخصَّصَين</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    $mongo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MongoDB</span><span class="pln">\Client</span><span class="pun">(</span><span class="str">'mongodb://username:password@localhost:27017'</span><span class="pun">);</span><span class="pln">
    print_r</span><span class="pun">(</span><span class="pln">$mongo</span><span class="pun">-&gt;</span><span class="pln">listDatabases</span><span class="pun">());</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln"> 
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    echo $e</span><span class="pun">-&gt;</span><span class="pln">getMessage</span><span class="pun">();</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// استخدام إعدادات افتراضية</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    $mongo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MongoDB</span><span class="pln">\Client</span><span class="pun">(</span><span class="str">'mongodb://localhost:27017'</span><span class="pun">);</span><span class="pln">
    print_r</span><span class="pun">(</span><span class="pln">$mongo</span><span class="pun">-&gt;</span><span class="pln">listDatabases</span><span class="pun">());</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    echo $e</span><span class="pun">-&gt;</span><span class="pln">getMessage</span><span class="pun">();</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln"> </span></pre>

<p>
	ستتصل الشيفرة السابقة باستخدام مكتبة المُنشئ MongoDB <code>(‏mongodb/mongodb)</code> المضمّنة بالشكل <code>vendor/autoload.php</code> للاتصال بخادم MongoDB? الذي يعمل على المنفذ 27017. ستتصل إذا كان كل شيء صحيحًا وتعرض قائمة مصفوفة أما إذا حدث استثناء بالاتصال إلى خادم MongoDB? ستُطبع رسالة.
</p>

<h3>
	الإنشاء (الإضافة) في MongoDB
</h3>

<p>
	يستخدم MongoDB المجموعة (collection) بدلًا من الجداول كما هو الحال في SQL.
</p>

<p>
	نستخدم في الشيفرة التالية الكائن <code>‎$mongo</code> لاختيار قاعدة البيانات والمجموعة، إذا لم توجد قاعدة البيانات (demo في مثالنا) والمجموعة (beers في مثالنا) سينشئهما MongoDB تلقائيًا.
</p>

<p>
	ونستخدم <code>‎$collection</code> لإضافة ملف في MongoDB، يشبه الملف السطر في SQL، وكل ملف مُنشئ له معرِّف فريد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_9" style="">
<span class="pun">&lt;?</span><span class="pln">php
$collection </span><span class="pun">=</span><span class="pln"> $mongo</span><span class="pun">-&gt;</span><span class="pln">demo</span><span class="pun">-&gt;</span><span class="pln">beers</span><span class="pun">;</span><span class="pln">

$result </span><span class="pun">=</span><span class="pln"> $collection</span><span class="pun">-&gt;</span><span class="pln">insertOne</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Hinterland'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'brewery'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'BrewDog'</span><span class="pln"> </span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

echo </span><span class="str">"Inserted with Object ID '{$result-&gt;getInsertedId()}'"</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	استخدمنا في المثال الكائن <code>‎$mongo</code> المستخدم سابقًا في شيفرة الاتصال من php إلى MongoDB، يستخدم MongoDB نوع تنسيق البيانات <code>JSON</code> لذا سنستخدم في php المصفوفة لإضافة بيانات إلى MongoDB، ستحوّل مكتبة mongo من المصفوفة إلى <code>JSON</code> وبالعكس، لكل ملف في MongoDB معرّف خاص به يمكننا الحصول عليه عند الإضافة باستخدام الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_11" style="">
<span class="pln"> $result</span><span class="pun">-&gt;</span><span class="pln">getInsertedId</span><span class="pun">();</span></pre>

<h3>
	القراءة (البحث) في MongoDB
</h3>

<p>
	نستخدم التابع <code>find()‎</code> للاستعلام عن السجلات، ويكون المعامل مصفوفة تتضمن زوج قيمة مفتاح نريد إيجاده، تُرجَع النتيجة على شكل مصفوفة ونستخدم <code>foreach</code> لفلترة المفاتيح المطلوبة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_13" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> $collection</span><span class="pun">-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Hinterland'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'brewery'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'BrewDog'</span><span class="pln"> </span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$result </span><span class="kwd">as</span><span class="pln"> $entry</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    echo $entry</span><span class="pun">[</span><span class="str">'_id'</span><span class="pun">],</span><span class="pln"> </span><span class="str">': '</span><span class="pun">,</span><span class="pln"> $entry</span><span class="pun">[</span><span class="str">'name'</span><span class="pun">],</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln"> 
</span><span class="pun">?&gt;</span></pre>

<p>
	مثال آخر للبحث عن عدة مستخدمين اسمهم "Mike":
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_15" style="">
<span class="pln">$filter </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Mike'</span><span class="pun">];</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\Driver\Query</span><span class="pun">(</span><span class="pln">$filter</span><span class="pun">);</span><span class="pln">

$cursor </span><span class="pun">=</span><span class="pln"> $manager</span><span class="pun">-&gt;</span><span class="pln">executeQuery</span><span class="pun">(</span><span class="str">'database_name.collection_name'</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">);</span><span class="pln"> 
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$cursor </span><span class="kwd">as</span><span class="pln"> $doc</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    var_dump</span><span class="pun">(</span><span class="pln">$doc</span><span class="pun">);</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	ونستخدم التابع <code>findOne()‎</code> للحصول على ملف واحد، مثال للبحث عن مستخدم واحد فقط له معرِّف محدد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_17" style="">
<span class="pln">$options </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'limit'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">];</span><span class="pln"> 
$filter </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\BSON\ObjectID</span><span class="pun">(</span><span class="str">'578ff7c3648c940e008b457a'</span><span class="pun">)];</span><span class="pln"> 
$query </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\Driver\Query</span><span class="pun">(</span><span class="pln">$filter</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">);</span><span class="pln"> 

$cursor </span><span class="pun">=</span><span class="pln"> $manager</span><span class="pun">-&gt;</span><span class="pln">executeQuery</span><span class="pun">(</span><span class="str">'database_name.collection_name'</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">);</span><span class="pln"> 
$cursorArray </span><span class="pun">=</span><span class="pln"> $cursor</span><span class="pun">-&gt;</span><span class="pln">toArray</span><span class="pun">();</span><span class="pln"> 
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$cursorArray</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    var_dump</span><span class="pun">(</span><span class="pln">$cursorArray</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<h3>
	الحذف في MongoDB
</h3>

<p>
	تعيد الشيفرة التالية 1 في حال تم الحذف بنجاح وتعيد 0 في حال الفشل.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_19" style="">
<span class="pun">&lt;?</span><span class="pln">php
$result </span><span class="pun">=</span><span class="pln"> $collection</span><span class="pun">-&gt;</span><span class="pln">drop</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Hinterland'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> 
print_r</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">-&gt;</span><span class="pln">ok</span><span class="pun">);</span><span class="pln"> 
</span><span class="pun">?&gt;</span></pre>

<p>
	يمكنك الاطلاع في <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="https://docs.mongodb.com/php-library/current/" rel="external nofollow">التوثيق الرسمي</a> من MongoDB على العديد من التوابع التي يمكن تطبيقها على <code>‎$collection</code>.
</p>

<h2>
	الاتصال مع MongoDB وإجراء العمليات
</h2>

<p>
	إنشاء اتصال MongoDB يمكنك استخدامه للاستعلام منه لاحقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_21" style="">
<span class="pln">$manager </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\Driver\Manager</span><span class="pun">(</span><span class="str">'mongodb://localhost:27017'</span><span class="pun">);</span></pre>

<p>
	ستتعلم في المثال التالي كيفية الاستعلام باستخدام كائن الاتصال، تُغلق هذه الإضافة الاتصال بشكلٍ تلقائي لذا ليس من الضروري إغلاقه يدويًا.
</p>

<h3>
	إضافة ملف
</h3>

<p>
	مثال لإضافة ملف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_23" style="">
<span class="pln">$document </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> 
    </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'John'</span><span class="pun">,</span><span class="pln"> 
    </span><span class="str">'active'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> 
    </span><span class="str">'info'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'genre'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'male'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'age'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">30</span><span class="pun">]</span><span class="pln"> 
</span><span class="pun">];</span><span class="pln"> 
$bulk </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\Driver\BulkWrite</span><span class="pun">;</span><span class="pln"> 
$_id1 </span><span class="pun">=</span><span class="pln"> $bulk</span><span class="pun">-&gt;</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">$document</span><span class="pun">);</span><span class="pln"> 
$result </span><span class="pun">=</span><span class="pln"> $manager</span><span class="pun">-&gt;</span><span class="pln">executeBulkWrite</span><span class="pun">(</span><span class="str">'database_name.collection_name'</span><span class="pun">,</span><span class="pln"> $bulk</span><span class="pun">);</span></pre>

<h3>
	تحديث ملف
</h3>

<p>
	مثال لتحديث كل الملفات التي اسمها "John":
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_25" style="">
<span class="pln">$filter </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'John'</span><span class="pun">];</span><span class="pln"> 
$document </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Mike'</span><span class="pun">];</span><span class="pln"> 

$bulk </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\Driver\BulkWrite</span><span class="pun">;</span><span class="pln"> 
$bulk</span><span class="pun">-&gt;</span><span class="pln">update</span><span class="pun">(</span><span class="pln"> 
    $filter</span><span class="pun">,</span><span class="pln"> 
    $document</span><span class="pun">,</span><span class="pln"> 
    </span><span class="pun">[</span><span class="str">'multi'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">]</span><span class="pln"> 
</span><span class="pun">);</span><span class="pln"> 
$result </span><span class="pun">=</span><span class="pln"> $manager</span><span class="pun">-&gt;</span><span class="pln">executeBulkWrite</span><span class="pun">(</span><span class="str">'database_name.collection_name'</span><span class="pun">,</span><span class="pln"> $bulk</span><span class="pun">);</span></pre>

<h3>
	حذف ملف
</h3>

<p>
	مثال لحذف كل الملفات التي اسمها "Peter":
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_27" style="">
<span class="pln">$bulk </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MongoDB\Driver\BulkWrite</span><span class="pun">;</span><span class="pln"> 

$filter </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Peter'</span><span class="pun">];</span><span class="pln"> 
$bulk</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">(</span><span class="pln">$filter</span><span class="pun">);</span><span class="pln"> 

$result </span><span class="pun">=</span><span class="pln"> $manager</span><span class="pun">-&gt;</span><span class="pln">executeBulkWrite</span><span class="pun">(</span><span class="str">'database_name.collection_name'</span><span class="pun">,</span><span class="pln"> $bulk</span><span class="pun">);</span></pre>

<h2>
	استخدام Redis مع PHP
</h2>

<h3>
	الاتصال إلى كائن Redis
</h3>

<p>
	بفرض أنّ الخادم الافتراضي يعمل على المضيف المحلي مع المنفذ الافتراضي?، عندها يكون أمر الاتصال إلى خادم Redis هذا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_29" style="">
<span class="pln">$redis </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Redis</span><span class="pun">();</span><span class="pln"> 
$redis</span><span class="pun">-&gt;</span><span class="pln">connect</span><span class="pun">(</span><span class="str">'127.0.0.1'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6379</span><span class="pun">);</span></pre>

<h3>
	تثبيت <code>PHP Redis</code> على نظام التشغيل أبونتو
</h3>

<p>
	نثبّت أولًا خادم Redis:
</p>

<pre class="ipsCode" id="ips_uid_7615_33">
sudo apt install redis-server </pre>

<p>
	ثم نثبّت وحدة PHP:
</p>

<pre class="ipsCode">
sudo apt install php-redis
</pre>

<p>
	ثم نعيد تشغيل خادم Apache:
</p>

<pre class="ipsCode">
sudo service apache2 restart
</pre>

<h3>
	تنفيذ أوامر Redis في PHP
</h3>

<p>
	توفر وحدة <code>Redis PHP</code> الوصول إلى نفس الأوامر كعميل <code>Redis CLI</code> لذا يمكن استخدامها بشكلٍ مباشر.܏ الصياغة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_35" style="">
<span class="com">// إنشاء مفتاحين جديدين</span><span class="pln">
$redis</span><span class="pun">-&gt;</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'mykey-1'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">123</span><span class="pun">);</span><span class="pln"> 
$redis</span><span class="pun">-&gt;</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'mykey-2'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'abcd'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الحصول على مفتاح واحد</span><span class="pln">
</span><span class="com">// 123</span><span class="pln">

</span><span class="pun">‬</span><span class="com">// ‫الحصول على كل المفاتيح التي بدايتها 'my-key-‎‎'</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$redis</span><span class="pun">-&gt;</span><span class="pln">keys</span><span class="pun">(</span><span class="str">'mykey-*'</span><span class="pun">));</span><span class="pln">
</span><span class="com">// '123', 'abcd'</span></pre>

<h2>
	الإضافة PDO في PHP
</h2>

<p>
	تسمح الإضافة <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="%E2%80%8Fhttps://www.php.net/manual/en/book.pdo.php" rel="">PDO</a> للمطورين بالاتصال بأنواع مختلفة كثيرة من قواعد البيانات وتنفيذ استعلامات مختلفة عليها بطريقة موحدة كائنية التوجه.
</p>

<h3>
	منع حقن SQL باستخدام استعلامات ذات وسائط
</h3>

<p>
	حقن SQL هو هجوم يسمح لمستخدم ضار بتعديل استعلام SQL بإضافة أوامر غير مرغوب بها إلى الاستعلام، مثلًا الاستعلام التالي معرَّض للخطر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_37" style="">
<span class="pln">$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">'SELECT name, email, user_level FROM users WHERE userID = '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'user'</span><span class="pun">];</span><span class="pln">
$conn</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$sql</span><span class="pun">);</span></pre>

<p>
	تسمح هذه الشيفرة لأي مستخدم بالتعديل في قاعدة البيانات بشكلٍ أساسي كما يرغب، مثلًا بفرض لدينا سلسلة الاستعلام التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_39" style="">
<span class="pln">page</span><span class="pun">.</span><span class="pln">php</span><span class="pun">?</span><span class="pln">user</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;%</span><span class="lit">20TRUNCATE</span><span class="pun">%</span><span class="lit">20TABLE</span><span class="pun">%</span><span class="lit">20users</span><span class="pun">;</span></pre>

<p>
	تجعل هذه السلسلة الاستعلام يكون بالشكل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_41" style="">
<span class="pln">SELECT name</span><span class="pun">,</span><span class="pln"> email</span><span class="pun">,</span><span class="pln"> user_level FROM users WHERE userID </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> TRUNCATE TABLE users</span><span class="pun">;</span></pre>

<p>
	يعدّ هذا المثال مبالغًا فيه (معظم هجمات حقن SQL لا تهدف إلى حذف البيانات ولا تدعم معظم دوال تنفيذ استعلام PHP الاستعلام المتعدد)، هذا مثال على إمكانية جعل هجوم حقن SQL ممكنًا من خلال التجميع غير المتقن للاستعلام، لسوء الحظ فإنَّ مثل هذه الهجمات شائع جدًا وفعال بشكلٍ كبير بسبب المبرمجين الذين يفشلون في اتخاذ الاحتياطات المناسبة لحماية بياناتهم.
</p>

<p>
	الحل المناسب لمنع حدوث حقن SQL هو تعليمات التحضير (prepared statements)، فنستخدم عنصرًا بديلًا (placeholder) بدلًا من دمج بيانات المستخدم بشكلٍ مباشر مع الاستعلام، ثم تُرسَل البيانات بشكلٍ منفصل وبالتالي لا توجد فرصة لمحرك SQL أن يحتار بخصوص بيانات المستخدم. ولاحظ أنّ إضافة <code>PHP MySQLi</code> تدعم أيضًا تعليمات التحضير.
</p>

<p>
	تدعم PDO نوعين من العناصر البديلة (لا يمكن استخدام العناصر البديلة لتسمية الأعمدة أو الجداول وإنما فقط للقيم):
</p>

<p>
	1- العناصر البديلة المسماة، نقطتان (:) يتبعهما اسم واضح مثل (‎:user).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_43" style="">
<span class="com">// استخدام العناصر البديلة المسماة</span><span class="pln">
$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">'SELECT name, email, user_level FROM users WHERE userID = :user'</span><span class="pun">;</span><span class="pln">
$prep </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">$sql</span><span class="pun">);</span><span class="pln">

</span><span class="com">// مصفوفة ترابطية</span><span class="pln">
$prep</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="str">'user'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'user'</span><span class="pun">]]);</span><span class="pln"> 
$result </span><span class="pun">=</span><span class="pln"> $prep</span><span class="pun">-&gt;</span><span class="pln">fetchAll</span><span class="pun">();</span></pre>

<p>
	2- العناصر البديلة الموضعية التقليدية في SQL تُمثَّل بالعلامة <code>?</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_45" style="">
<span class="com">// استخدام العناصر البديلة الممثَّلة بعلامة الاستفهام</span><span class="pln">
$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">'SELECT name, user_level FROM users WHERE userID = ? AND user_level = ?'</span><span class="pun">;</span><span class="pln">
$prep </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">$sql</span><span class="pun">);</span><span class="pln">

</span><span class="com">// مصفوفة مفهرسة</span><span class="pln">
$prep</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'user'</span><span class="pun">],</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'user_level'</span><span class="pun">]]);</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> $prep</span><span class="pun">-&gt;</span><span class="pln">fetchAll</span><span class="pun">();</span></pre>

<p>
	يجب أن تعلم أنّه إذا احتجت إلى تغيير اسم عمود أو جدول بشكلٍ ديناميكي فإنّ هذه ممارسة سيئة وعلى مسؤوليتك الأمنية الخاصة، مع أنّه يمكنك القيام بذلك عن طريق دمج السلاسل النصية. إحدى الطرق لتحسين أمان مثل هذه الاستعلامات هي تعيين جدول فيه القيم المسموح بها ومقارنة القيمة التي تريدها للدمج مع هذا الجدول.
</p>

<p>
	يجب أن تعلم أنّه من المهم ضبط ترميز محارف الاتصال ليكون DSN (‏Data Source Name) فقط، وإلا قد يكون تطبيقك معرّضًا لثغرة ضعيفة. إنّ ضبط ترميز المحارف ليكون DSN غير متاح في الإصدارات PDO السابقة للإصدار 5.3.6 لذا فالخيار الوحيد هو ضبط سمة الاتصال <code>PDO::ATTR_EMULATE_PREPARES</code> لتكون <code>false</code> مباشرةً بعد إنشائه.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_47" style="">
<span class="pln">$conn</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">PDO</span><span class="pun">::</span><span class="pln">ATTR_EMULATE_PREPARES</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span></pre>

<p>
	ستؤدي هذه الشيفرة إلى استخدام PDO لتعليمات التحضير الأساسية الموجودة في <code>DBMS</code> (‏Database Management Systems) بدلًا من محاكاتها فقط، وانتبه إلى أنّ PDO <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="https://github.com/php/php-src/blob/master/ext/pdo_mysql/mysql_driver.c#L210" rel="external nofollow">ستتراجع ببطء</a> لمحاكاة التعليمات التي لا تستطيع <code>MySQL</code> تحضيرها محليًّا، هذه العبارات موجودة في <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-prepared-statements.html" rel="external nofollow">التوثيق</a>.
</p>

<h3>
	اتصال PDO الأساسي والاسترجاع
</h3>

<p>
	بدءًا من الإصدار PHP 5.0 أصبحت PDO متاحة كطبقة وصول إلى قاعدة البيانات، وهي لا تعرف قاعدة البيانات، ستعمل الشيفرة في مثال الاتصال التالي لأي من <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="https://www.php.net/manual/en/pdo.drivers.php" rel="external nofollow">قواعد البيانات المدعومة</a> ببساطة عن طريق تغيير الترميز DSN.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_49" style="">
<span class="com">// (1)</span><span class="pln">
$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mysql:host=localhost;dbname=testdb;charset=utf8"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// (2)</span><span class="pln">
$username </span><span class="pun">=</span><span class="pln"> </span><span class="str">"user"</span><span class="pun">;</span><span class="pln">
$password </span><span class="pun">=</span><span class="pln"> </span><span class="str">"pass"</span><span class="pun">;</span><span class="pln">
$db </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="pln">$dsn</span><span class="pun">,</span><span class="pln"> $username</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫ضبط PDO لرمي استثناء إذا أُدخِل استعلام غير صحيح</span><span class="pln">
$db</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">PDO</span><span class="pun">::</span><span class="pln">ATTR_ERRMODE</span><span class="pun">,</span><span class="pln"> PDO</span><span class="pun">::</span><span class="pln">ERRMODE_EXCEPTION</span><span class="pun">);</span><span class="pln">

</span><span class="com">// تحضير تعليمة التنفيذ مع عنصر بديل مفرد</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SELECT * FROM users WHERE class = ?"</span><span class="pun">;</span><span class="pln">
$statement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">

</span><span class="com">// إنشاء بعض المعاملات لملء العناصر البديلة وتنفيذ التعليمة</span><span class="pln">
$parameters </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="str">"221B"</span><span class="pln"> </span><span class="pun">];</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">$parameters</span><span class="pun">);</span><span class="pln">

</span><span class="com">// التكرار على كل سجل كمصفوفة ترابطية</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> $statement</span><span class="pun">-&gt;</span><span class="pln">fetch</span><span class="pun">(</span><span class="pln">PDO</span><span class="pun">::</span><span class="pln">FETCH_ASSOC</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    do_stuff</span><span class="pun">(</span><span class="pln">$row</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ننشئ في الموضع (1) مقبضًا لقاعدة البيانات ونستخدم <code>MySQL</code> (اتصال باستخدام مقبس محلي) يوضّح الموضع (2) أنّه يمكنك استخدام <code>MySQL</code> (اتصال عبر الشبكة، يمكنك تحديد المنفذ أيضًا إذا أردت) باستخدام الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_51" style="">
<span class="pln">$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mysql:host=127.0.0.1;port=3306;dbname=testdb;charset=utf8"</span><span class="pun">;</span></pre>

<p>
	أو استخدام <code>Postgres</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_53" style="">
<span class="pln">$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">"pgsql:host=localhost;port=5432;dbname=testdb;"</span><span class="pun">;</span></pre>

<p>
	أو حتى <code>SQLite</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_55" style="">
<span class="pln">$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">"sqlite:/path/to/database"</span></pre>

<p>
	تنشئ الدالة <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="%E2%80%8Fhttps://www.php.net/manual/en/pdo.prepare.php" rel="">prepare</a> كائنًا من الصنف <code>PDOStatement</code> من سلسلة الاستعلام، تجري عمليات تنفيذ الاستعلام واسترجاع النتائج على هذا الكائن المُرجَع. في حال الفشل إما تعيد الدالة <code>false</code> أو ترمي استثناءً (بالاعتماد على كيفية ضبط إعدادات اتصال PDO).
</p>

<h3>
	عمليات قاعدة البيانات مع PDO
</h3>

<p>
	تضمن عمليات (transactions) قاعدة البيانات أنَّ مجموعة التغييرات على قاعدة البيانات ستصبح دائمة فقط إذا نجحت كل التعليمات، يمكن التقاط أي فشل في الاستعلام أو الشيفرة خلال عملية ما ثم يكون لديك خيار التراجع (roll back) عن التغييرات التي حاولت القيام بها. توفر PDO توابع بسيطة لعمليات البدء وحفظ التغييرات (committing) والتراجع.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_57" style="">
<span class="pln">$pdo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="pln">
    $dsn</span><span class="pun">,</span><span class="pln">
    $username</span><span class="pun">,</span><span class="pln">
    $password</span><span class="pun">,</span><span class="pln">
    array</span><span class="pun">(</span><span class="pln">PDO</span><span class="pun">::</span><span class="pln">ATTR_ERRMODE </span><span class="pun">=&gt;</span><span class="pln"> PDO</span><span class="pun">::</span><span class="pln">ERRMODE_EXCEPTION</span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $statement </span><span class="pun">=</span><span class="pln"> $pdo</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="str">"UPDATE user SET name = :name"</span><span class="pun">);</span><span class="pln">
    $pdo</span><span class="pun">-&gt;</span><span class="pln">beginTransaction</span><span class="pun">();</span><span class="pln">
    $statement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="str">"name"</span><span class="pun">=&gt;</span><span class="str">'Bob'</span><span class="pun">]);</span><span class="pln">
    $statement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="str">"name"</span><span class="pun">=&gt;</span><span class="str">'Joe'</span><span class="pun">]);</span><span class="pln">
    $pdo</span><span class="pun">-&gt;</span><span class="pln">commit</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">\Exception $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$pdo</span><span class="pun">-&gt;</span><span class="pln">inTransaction</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $pdo</span><span class="pun">-&gt;</span><span class="pln">rollback</span><span class="pun">();</span><span class="pln">
        </span><span class="com">// إذا وصلنا إلى هنا فإنَّ التحديثين ليسا في قاعدة البيانات</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> $e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تكون أي تغييرات تُجرى على البيانات خلال العملية مرئية للاتصال النشط، ستُرجع تعليمات <code>SELECT</code> التغييرات المُعدَّلة حتى لو لم تُحفظ في قاعدة البيانات بعد.
</p>

<h3>
	مثال عملي لاستخدام العمليات مع PDO
</h3>

<p>
	نعرض لك في الفقرة التالية مثال عملي من العالم الحقيقي حيث يضمن استخدام العمليات اتساق قاعدة البيانات.
</p>

<p>
	تخيل بأنّك تبني عربة تسوق لموقع تجارة الكترونية وقررت أن تحتفظ بطلبات العملاء في جدولين من قاعدة البيانات، اسم الجدول الأول <code>orders</code> يعبر عن الطلبات وحقوله هي <code>order_id</code>، <code>‏name</code>، <code>‏address</code>، <code>‏telephone</code> و<code>‏created_at</code>، واسم الجدول الثاني <code>orders_products</code> يحوي منتجات الطلبات وحقوله هي <code>order_id</code>،<code>‏product_id</code> و<code>quantity</code>، أي يحتوي الجدول الأول على بيانات وصفية للطلب والجدول الثاني على المنتجات الفعلية التي طلبها العملاء.
</p>

<h4>
	إضافة طلب جديد إلى قاعدة البيانات
</h4>

<p>
	تحتاج لإضافة طلب جديد إلى قاعدة البيانات إلى أمرين، الأول هو إنشاء سجل جديد (INSERT) في الجدول <code>orders</code> يحتوي على البيانات الوصفية للطلب (الاسم والعنوان وغير ذلك)، والثاني هو إنشاء سجل جديد في الجدول <code>orders_products</code> لكل منتج من المنتجات الموجودة في قائمة الطلب. يمكنك القيام بذلك باستخدام الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_59" style="">
<span class="com">// إضافة البيانات الوصفية للطلب في قاعدة البيانات</span><span class="pln">
$preparedStatement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">
    </span><span class="str">'INSERT INTO `orders` (`name`, `address`, `telephone`, `created_at`)
    VALUES (:name, :address, :telephone, :created_at)'</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

$preparedStatement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="pln">
    </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $name</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'address'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'telephone'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $telephone</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> time</span><span class="pun">(),</span><span class="pln">
</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// ‫الحصول على `order_id` المولَّد</span><span class="pln">
$orderId </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">lastInsertId</span><span class="pun">();</span><span class="pln">

</span><span class="com">// بناء استعلام لإضافة منتجات الطلب</span><span class="pln">
$insertProductsQuery </span><span class="pun">=</span><span class="pln"> </span><span class="str">'INSERT INTO `orders_products` (`order_id`, `product_id`, `quantity`) VALUES'</span><span class="pun">;</span><span class="pln">

$count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> $products </span><span class="kwd">as</span><span class="pln"> $productId </span><span class="pun">=&gt;</span><span class="pln"> $quantity </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $insertProductsQuery </span><span class="pun">.=</span><span class="pln"> </span><span class="str">' (:order_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count </span><span class="pun">.</span><span class="pln"> </span><span class="str">', :product_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count </span><span class="pun">.</span><span class="pln"> </span><span class="str">', :quantity'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count </span><span class="pun">.</span><span class="pln"> </span><span class="str">')'</span><span class="pun">;</span><span class="pln">
    $insertProductsParams</span><span class="pun">[</span><span class="str">'order_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $orderId</span><span class="pun">;</span><span class="pln">
    $insertProductsParams</span><span class="pun">[</span><span class="str">'product_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $productId</span><span class="pun">;</span><span class="pln">
    $insertProductsParams</span><span class="pun">[</span><span class="str">'quantity'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $quantity</span><span class="pun">;</span><span class="pln">

    </span><span class="pun">++</span><span class="pln">$count</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// إضافة المنتجات المُضمَّنة في الطلب إلى قاعدة البيانات</span><span class="pln">
$preparedStatement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">$insertProductsQuery</span><span class="pun">);</span><span class="pln">
$preparedStatement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">$insertProductsParams</span><span class="pun">);</span></pre>

<p>
	ستعمل هذه الشيفرة بشكلٍ رائع على إضافة طلب جديد إلى قاعدة البيانات حتى يحدث شيء ما غير متوقع ولسببٍ ما يفشل استعلام <code>INSERT</code> الثاني وعندها سيكون لديك طلب جديد في الجدول <code>orders</code> بدون وجود منتجات مرتبطة فيه من الجدول <code>orders_products</code>. لحسن الحظ يمكن إصلاح هذا ببساطة بجعل الاستعلامين في عملية قاعدة بيانات واحدة.
</p>

<h4>
	إضافة طلب جديد إلى قاعدة البيانات مع عملية
</h4>

<p>
	كل ماعليك فعله لبدء عملية باستخدام PDO هو استدعاء التابع <code>beginTransaction</code> قبل تنفيذ أي استعلامات على قاعدة البيانات، ثم تجري التغييرات التي تريدها بتنفيذ استعلامات <code>INSERT</code> و/أو <code>UPDATE</code> وفي النهاية تستدعي التابع <code>commit</code> للكائن لجعل التغييرات دائمة، قبل استدعاء التابع <code>commit</code> فإنّ كل التغييرات التي تجريها على بياناتك غير دائمة ويمكن التراجع عنها بسهولة باستدعاء التابع <code>rollback</code> للكائن PDO.
</p>

<p>
	نوضح في المثال التالي استخدام العمليات لإضافة طلب جديد في قاعدة البيانات مع ضمان اتساق البيانات في نفس الوقت، ستُرجع جميع التغييرات إذا فشل أحد الاستعلامين، نستخدم في هذا المثال <code>MySQL</code> لكن يمكن تطبيقه على أي قاعدة بيانات تدعم العمليات.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_61" style="">
<span class="pln">$db </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="str">'mysql:host='</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $host </span><span class="pun">.</span><span class="pln"> </span><span class="str">';dbname='</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $dbname </span><span class="pun">.</span><span class="pln"> </span><span class="str">';charset=utf8'</span><span class="pun">,</span><span class="pln"> $username</span><span class="pun">,</span><span class="pln">$password</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫تأكد من أنّ PDO سترمي استثناءً في حالة الخطأ لجعل عملية معالجة الخطأ أسهل</span><span class="pln">
$db</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">PDO</span><span class="pun">::</span><span class="pln">ATTR_ERRMODE</span><span class="pun">,</span><span class="pln"> PDO</span><span class="pun">::</span><span class="pln">ERRMODE_EXCEPTION</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// بدءًا من هذه النقطة وحتى تُحفظ العملية يمكن التراجع عن كل تغيير في قاعدة البيانات</span><span class="pln">
    $db</span><span class="pun">-&gt;</span><span class="pln">beginTransaction</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// إضافة البيانات الوصفية للطلب في قاعدة البيانات</span><span class="pln">
    $preparedStatement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">
        </span><span class="str">'INSERT INTO `orders` (`order_id`, `name`, `address`, `created_at`)
        VALUES (:name, :address, :telephone, :created_at)'</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">

    $preparedStatement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="pln">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $name</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'address'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'telephone'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $telephone</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> time</span><span class="pun">(),</span><span class="pln">
    </span><span class="pun">]);</span><span class="pln">

    </span><span class="com">// ‫الحصول على `order_id` المولَّد</span><span class="pln">
    $orderId </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">lastInsertId</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// بناء الاستعلام لإضافة منتجات الطلب</span><span class="pln">
    $insertProductsQuery </span><span class="pun">=</span><span class="pln"> </span><span class="str">'INSERT INTO `orders_products` (`order_id`,     `product_id`, `quantity`) VALUES'</span><span class="pun">;</span><span class="pln">

    $count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> $products </span><span class="kwd">as</span><span class="pln"> $productId </span><span class="pun">=&gt;</span><span class="pln"> $quantity </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $insertProductsQuery </span><span class="pun">.=</span><span class="pln"> </span><span class="str">' (:order_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count </span><span class="pun">.</span><span class="pln"> </span><span class="str">', :product_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count </span><span class="pun">.</span><span class="pln"> </span><span class="str">',     :quantity'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count </span><span class="pun">.</span><span class="pln"> </span><span class="str">')'</span><span class="pun">;</span><span class="pln">

        $insertProductsParams</span><span class="pun">[</span><span class="str">'order_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $orderId</span><span class="pun">;</span><span class="pln">
        $insertProductsParams</span><span class="pun">[</span><span class="str">'product_id'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $productId</span><span class="pun">;</span><span class="pln">
        $insertProductsParams</span><span class="pun">[</span><span class="str">'quantity'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $count</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $quantity</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">++</span><span class="pln">$count</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// إضافة منتجات الطلب إلى قاعدة البيانات</span><span class="pln">
    $preparedStatement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">$insertProductsQuery</span><span class="pun">);</span><span class="pln">
    $preparedStatement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">$insertProductsParams</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// جعل تغييرات قاعدة البيانات دائمة</span><span class="pln">
    $db</span><span class="pun">-&gt;</span><span class="pln">commit</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="typ">PDOException</span><span class="pln"> $e </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// فشل إضافة الطلب في قاعدة البيانات لذا نتراجع عن التغييرات</span><span class="pln">
    $db</span><span class="pun">-&gt;</span><span class="pln">rollback</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> $e</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الاتصال بخادم MySQL/MariaDB باستخدام PDO
</h3>

<p>
	يوجد طريقتين للاتصال بخادم MySQL/MariaDB وفقًا للبنية التحتية.
</p>

<h4>
	الاتصال (TCP/IP) المعياري
</h4>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_63" style="">
<span class="pln">$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">'mysql:dbname=demo;host=server;port=3306;charset=utf8'</span><span class="pun">;</span><span class="pln">
$connection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \PDO</span><span class="pun">(</span><span class="pln">$dsn</span><span class="pun">,</span><span class="pln"> $username</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫رمي استثناءات عند حدوث خطأ SQL</span><span class="pln">
$connection</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">\PDO</span><span class="pun">::</span><span class="pln">ATTR_ERRMODE</span><span class="pun">,</span><span class="pln"> \PDO</span><span class="pun">::</span><span class="pln">ERRMODE_EXCEPTION</span><span class="pun">);</span><span class="pln">

</span><span class="com">// منع محاكاة تعليمات التحضير</span><span class="pln">
$connection</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">\PDO</span><span class="pun">::</span><span class="pln">ATTR_EMULATE_PREPARES</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span></pre>

<p>
	يجب أن تعطّل المحاكاة بشكلٍ واضح لأنّ PDO صممت لتكون متكاملة مع إصدارات خادم <code>MySQL</code> الأقدم (التي لا تدعم تعليمات التحضير)، وإلا ستخسر فوائد منع الحقن (injection prevention) المضافة التي يوفرها عادةً استخدام تعليمات التحضير.
</p>

<p>
	سلوك معالجة الخطأ الافتراضي هو حل وسط آخر، إذا لم يُعَدّ فلن تظهر PDO أي مؤشرات إلى أخطاء <code>SQL</code>، يُنصح بضبطه إلى الإعداد "exception mode" (نمط الاستثناء) لأنّه يمنحك وظائف إضافية عند كتابة تعابير ثبات مجردة (مثلًا عندما يكون لديك استثناء عند انتهاك القيد <code>UNIQUE</code>).
</p>

<h4>
	اتصال المقبس
</h4>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_65" style="">
<span class="pln">$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">'mysql:unix_socket=/tmp/mysql.sock;dbname=demo;charset=utf8'</span><span class="pun">;</span><span class="pln">
$connection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \PDO</span><span class="pun">(</span><span class="pln">$dsn</span><span class="pun">,</span><span class="pln"> $username</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫رمي استثناءات عند حدوث خطأ SQL</span><span class="pln">
$connection</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">\PDO</span><span class="pun">::</span><span class="pln">ATTR_ERRMODE</span><span class="pun">,</span><span class="pln"> \PDO</span><span class="pun">::</span><span class="pln">ERRMODE_EXCEPTION</span><span class="pun">);</span><span class="pln">

</span><span class="com">// منع محاكاة تعليمات التحضير</span><span class="pln">
$connection</span><span class="pun">-&gt;</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="pln">\PDO</span><span class="pun">::</span><span class="pln">ATTR_EMULATE_PREPARES</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span></pre>

<p>
	في الأنظمة مثل <code>unix</code> إذا كان اسم المضيف 'localhost' يتم الاتصال بالخادم عبر مقبس المجال (domain socket).
</p>

<h3>
	الحصول على عدد الأسطر المتأثرة بالاستعلام باستخدام PDO
</h3>

<p>
	نبدأ بالمتغير <code>‎$db</code> والذي هو نسخة من الصنف PDO. نريد غالبًا بعد تنفيذ الاستعلام أن نحدد عدد الأسطر المتأثرة بهذا الاستعلام عندها نستخدم التابع <code>rowCount()‎</code> من الصنف <code>PDOStatement</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_67" style="">
<span class="pln">$query </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">"DELETE FROM table WHERE name = 'John'"</span><span class="pun">);</span><span class="pln"> $count </span><span class="pun">=</span><span class="pln"> $query</span><span class="pun">-&gt;</span><span class="pln">rowCount</span><span class="pun">();</span><span class="pln"> echo </span><span class="str">"Deleted $count rows named John"</span><span class="pun">;</span></pre>

<p>
	ملاحظة: يُستخدم هذا التابع لتحديد عدد الأسطر المتأثرة بتعليمات <code>INSERT</code> و<code>DELETE</code> و<code>UPDATE</code> فقط، بالرغم من أنّ هذا التابع قد يعمل بشكلٍ صحيح مع تعليمات <code>SELECT</code> أيضًا إلا أنّه غير متسق مع جميع قواعد البيانات.
</p>

<h3>
	PDO::lastInsertId()‎
</h3>

<p>
	يمكنك الحصول على قيمة المعرِّف (ID) المتزايدة تلقائيًا للسطر الذي أضفته إلى جدول قاعدة البيانات باستخدام التابع <code>lastInsertId()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_69" style="">
<span class="com">// ‫فتح اتصال أساسي (MySQL)</span><span class="pln">
$host </span><span class="pun">=</span><span class="pln"> </span><span class="str">'localhost'</span><span class="pun">;</span><span class="pln">
$database </span><span class="pun">=</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">;</span><span class="pln">
$user </span><span class="pun">=</span><span class="pln"> </span><span class="str">'root'</span><span class="pln">
$password </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mysql:host=$host;dbname=$database;charset=utf8"</span><span class="pun">;</span><span class="pln">
$pdo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="pln">$dsn</span><span class="pun">,</span><span class="pln"> $user</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫إضافة سطر جديد في الجدول الافتراضي 'foo_user'</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"INSERT INTO foo_user(pseudo, email) VALUES ('anonymous', 'anonymous@example.com')"</span><span class="pun">;</span><span class="pln">
$query_success </span><span class="pun">=</span><span class="pln"> $pdo</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">

</span><span class="com">// استعادة المعرِّف للسطر الأخير المدخل</span><span class="pln">
$id </span><span class="pun">=</span><span class="pln"> $pdo</span><span class="pun">-&gt;</span><span class="pln">lastInsertId</span><span class="pun">();</span><span class="pln">
</span><span class="com">// القيمة المعادة هي عدد صحيح</span></pre>

<p>
	لدينا الكلمة المفتاحية <code>RETURNING</code> في قواعد البيانات <code>postgresql</code> و<code>oracle</code> والتي تُرجع الأعمدة المحددة للأسطر المُدخلة/المعدّلة حاليًا. إليك مثال لإضافة سطر جديد واحد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_71" style="">
<span class="com">// ‫‫فتح اتصال أساسي (PGSQL)</span><span class="pln">
$host </span><span class="pun">=</span><span class="pln"> </span><span class="str">'localhost'</span><span class="pun">;</span><span class="pln">
$database </span><span class="pun">=</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">;</span><span class="pln">
$user </span><span class="pun">=</span><span class="pln"> </span><span class="str">'root'</span><span class="pln">
$password </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
$dsn </span><span class="pun">=</span><span class="pln"> </span><span class="str">"pgsql:host=$host;dbname=$database;charset=utf8"</span><span class="pun">;</span><span class="pln">
$pdo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="pln">$dsn</span><span class="pun">,</span><span class="pln"> $user</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫إضافة سطر جديد في الجدول الافتراضي 'foo_user'</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"INSERT INTO foo_user(pseudo, email) VALUES ('anonymous', 'anonymous@example.com') RETURNING id"</span><span class="pun">;</span><span class="pln">
$statement </span><span class="pun">=</span><span class="pln"> $pdo</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">

</span><span class="com">// استعادة المعرِّف للسطر الأخير المدخل</span><span class="pln">
$id </span><span class="pun">=</span><span class="pln"> $statement</span><span class="pun">-&gt;</span><span class="pln">fetchColumn</span><span class="pun">();</span></pre>

<h2>
	استخدام الإضافة SQLSRV في PHP
</h2>

<h3>
	استعادة رسائل الخطأ
</h3>

<p>
	من المهم جلب رسالة (أو رسائل) الخطأ المُرجعة من قِبل المُشغّل عند حدوث خطأ ما وذلك لمعرفة سبب المشكلة، الصيغة هي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_75" style="">
<span class="pln">sqlsrv_errors</span><span class="pun">([</span><span class="kwd">int</span><span class="pln"> $errorsOrWarnings</span><span class="pun">]);</span></pre>

<p>
	تُرجع هذه الشيفرة مصفوفة مع مفتاح ووصف.
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
<tbody></tbody>
<thead><tr>
<th>
				المفتاح
			</th>
			<th>
				الوصف
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				SQLSTATE
			</td>
			<td>
				‫ حالة خادم SQL/ مشغّل OBDC
			</td>
		</tr>
<tr>
<td>
				الشيفرة
			</td>
			<td>
				SQL Server شيفرة خطأ
			</td>
		</tr>
<tr>
<td>
				الرسالة
			</td>
			<td>
				وصف الخطأ
			</td>
		</tr>
</tbody>
</table>
<p>
	من الشائع استخدام الدالة السابقة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_77" style="">
<span class="pln">$brokenQuery </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SELECT BadColumnName FROM Table_1"</span><span class="pun">;</span><span class="pln">
$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $brokenQuery</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$stmt </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">$errors </span><span class="pun">=</span><span class="pln"> sqlsrv_errors</span><span class="pun">())</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$errors </span><span class="kwd">as</span><span class="pln"> $error</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            echo </span><span class="str">"SQLSTATE: "</span><span class="pun">.</span><span class="pln">$error</span><span class="pun">[</span><span class="str">'SQLSTATE'</span><span class="pun">].</span><span class="str">"&lt;br /&gt;"</span><span class="pun">;</span><span class="pln">
            echo </span><span class="str">"code: "</span><span class="pun">.</span><span class="pln">$error</span><span class="pun">[</span><span class="str">'code'</span><span class="pun">].</span><span class="str">"&lt;br /&gt;"</span><span class="pun">;</span><span class="pln">
            echo </span><span class="str">"message: "</span><span class="pun">.</span><span class="pln">$error</span><span class="pun">[</span><span class="str">'message'</span><span class="pun">].</span><span class="str">"&lt;br /&gt;"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	جلب نتائج الاستعلام
</h3>

<p>
	يوجد 3 طرق أساسية لجلب النتائج من استعلام:
</p>

<ul>
<li>
		<strong>sqlsrv_fetch_array()‎</strong>
	</li>
</ul>
<p>
	تعيد هذه الدالة السطر التالي كمصفوفة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_79" style="">
<span class="pln">$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">while</span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> sqlsrv_fetch_array</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $row</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
    $var </span><span class="pun">=</span><span class="pln"> $row</span><span class="pun">[</span><span class="str">"name"</span><span class="pun">];</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لهذه الدالة معامل ثاني اختياري لجلب أنواع مختلفة من المصفوفات، يمكن أن يكون <code>SQLSRV_FETCH_ASSOC</code> أو <code>SQLSRV_FETCH_NUMERIC</code> أو <code>SQLSRV_FETCH_BOTH</code> (القيمة الافتراضية) ويعيد مصفوفة ترابطية، عددية، أو مصفوفة ترابطية وعددية على الترتيب.
</p>

<ul>
<li>
		<strong>sqlsrv_fetch_object()‎</strong>
	</li>
</ul>
<p>
	تعيد هذه الدالة السطر التالي ككائن.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_81" style="">
<span class="pln">$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">while</span><span class="pun">(</span><span class="pln">$obj </span><span class="pun">=</span><span class="pln"> sqlsrv_fetch_object</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// أسماء خاصيات الكائن هي أسماء حقول الاستعلام</span><span class="pln">
    echo $obj</span><span class="pun">-&gt;</span><span class="pln">field</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//...</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		<strong>sqlsrv_fetch()‎</strong>
	</li>
</ul>
<p>
	تجعل هذه الدالة السطر التالي متاحًا للقراءة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_83" style="">
<span class="pln">$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">while</span><span class="pun">(</span><span class="pln">sqlsrv_fetch</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// الحصول على الحقل الأول</span><span class="pln">
    $foo </span><span class="pun">=</span><span class="pln"> sqlsrv_get_field</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<h3>
	إنشاء اتصال
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_85" style="">
<span class="com">// ‫اسم الخادم/النسخة، متضمنًا رقم منفذ اختياري (الافتراضي 1433)</span><span class="pln">
$dbServer </span><span class="pun">=</span><span class="pln"> </span><span class="str">"localhost,1234"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// اسم قاعدة البيانات</span><span class="pln">
$dbName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"db001"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// اسم المستخدم</span><span class="pln">
$dbUser </span><span class="pun">=</span><span class="pln"> </span><span class="str">"user"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// كلمة مرور قاعدة البيانات لهذا المستخدم</span><span class="pln">
$dbPassword </span><span class="pun">=</span><span class="pln"> </span><span class="str">"password"</span><span class="pun">;</span><span class="pln">

$connectionInfo </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"Database"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $dbName</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"UID"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $dbUser</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"PWD"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $dbPassword
</span><span class="pun">);</span><span class="pln">
$conn </span><span class="pun">=</span><span class="pln"> sqlsrv_connect</span><span class="pun">(</span><span class="pln">$dbServer</span><span class="pun">,</span><span class="pln"> $connectionInfo</span><span class="pun">);</span></pre>

<p>
	للإضافة SQLSRV أيضًا مشغّل PDO. للاتصال باستخدام PDO:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_87" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="str">"sqlsrv:Server=localhost,1234;Database=db001"</span><span class="pun">,</span><span class="pln"> $dbUser</span><span class="pun">,</span><span class="pln"> $dbPassword</span><span class="pun">);</span></pre>

<h3>
	كتابة استعلام بسيط
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_89" style="">
<span class="com">// إنشاء اتصال</span><span class="pln">
$conn </span><span class="pun">=</span><span class="pln"> sqlsrv_connect</span><span class="pun">(</span><span class="pln">$dbServer</span><span class="pun">,</span><span class="pln"> $connectionInfo</span><span class="pun">);</span><span class="pln">

$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SELECT * FROM [table]"</span><span class="pun">;</span><span class="pln">
$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">);</span></pre>

<p>
	<strong>ملاحظة:</strong> نستخدم الأقواس المربعة <code>[]</code> للهرب من <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="%E2%80%8Fhttps://docs.microsoft.com/en-us/sql/t-sql/language-elements/reserved-keywords-transact-sql?redirectedfrom=MSDN&amp;view=sql-server-ver15" rel="">الكلمة المحجوزة</a> <code>‏table</code>، وتعمل نفس عمل علامة الاقتباس المائلة ` في MySQL.
</p>

<h3>
	استدعاء إجراء مخزن (Stored Procedure)
</h3>

<p>
	لاستدعاء إجراء مخزن على الخادم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_91" style="">
<span class="com">// المعاملات '?' تتضمن معاملات خرج</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{call [dbo].[myStoredProcedure](?,?,?)}"</span><span class="pun">;</span><span class="pln">

$params </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
    array</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">,</span><span class="pln"> SQLSRV_PARAM_IN</span><span class="pun">),</span><span class="pln">
    array</span><span class="pun">(</span><span class="pln">$age</span><span class="pun">,</span><span class="pln"> SQLSRV_PARAM_IN</span><span class="pun">),</span><span class="pln">
    </span><span class="com">// ‏يجب أن يكون المتغير ‎$count معرّف مسبقًا</span><span class="pln">
    array</span><span class="pun">(</span><span class="pln">$count</span><span class="pun">,</span><span class="pln"> SQLSRV_PARAM_OUT</span><span class="pun">,</span><span class="pln"> SQLSRV_PHPTYPE_INT</span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

$result </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">,</span><span class="pln"> $params</span><span class="pun">);</span></pre>

<h3>
	كتابة استعلام ذو معاملات
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_93" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> sqlsrv_connect</span><span class="pun">(</span><span class="pln">$dbServer</span><span class="pun">,</span><span class="pln"> $connectionInfo</span><span class="pun">);</span><span class="pln">

$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SELECT * FROM [users] WHERE [name] = ? AND [password] = ?"</span><span class="pun">;</span><span class="pln">
$params </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="str">"joebloggs"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"pa55w0rd"</span><span class="pun">);</span><span class="pln">

$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">,</span><span class="pln"> $params</span><span class="pun">);</span></pre>

<p>
	إذا كنت تخطط لاستخدام نفس تعليمة الاستعلام أكثر من مرة مع معاملات مختلفة فيمكنك تحقيق ذلك باستخدام الدوال <code>sqlsrv_prepare()‎</code> و<code>sqlsrv_execute()‎</code> كما في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7615_95" style="">
<span class="pln">$cart </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"apple"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"banana"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"chocolate"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"INSERT INTO [order_items]([item], [quantity]) VALUES(?,?)"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// المتغيرات هي معاملات يجب تمريرها بالمرجع</span><span class="pln">
$params </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(&amp;</span><span class="pln">$item</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">$qty</span><span class="pun">);</span><span class="pln">

$stmt </span><span class="pun">=</span><span class="pln"> sqlsrv_prepare</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $query</span><span class="pun">,</span><span class="pln"> $params</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pun">(</span><span class="pln">$cart </span><span class="kwd">as</span><span class="pln"> $item </span><span class="pun">=&gt;</span><span class="pln"> $qty</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">sqlsrv_execute</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> FALSE</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">die</span><span class="pun">(</span><span class="pln">print_r</span><span class="pun">(</span><span class="pln">sqlsrv_errors</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [PDO - Using MongoDB - mongo-php - Using Redis with PHP - Using SQLSRV] من كتاب <a data-ss1616970683="1" data-ss1616971121="1" data-ss1616971172="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%B1%D8%B3%D8%A7%D9%84-%D8%A8%D8%B1%D9%8A%D8%AF-%D8%A5%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A-%D9%81%D9%8A-php-r1174/" rel="">كيفية إرسال بريد إلكتروني في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-php-mysqli-%D9%88%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sqlite3-r1131/" rel="">إضافة PHP MySQLi ونظام إدارة قواعد البيانات SQLite3</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1173</guid><pubDate>Fri, 12 Mar 2021 13:00:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; PHP MySQLi &#x648;&#x646;&#x638;&#x627;&#x645; &#x625;&#x62F;&#x627;&#x631;&#x629; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; SQLite3</title><link>https://academy.hsoub.com/programming/php/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-php-mysqli-%D9%88%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sqlite3-r1131/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/10.png.7a1f6ce84c8a16230d743ad4d22c0215.png" /></p>

<p>
	<a href="%E2%80%8Fhttps://www.php.net/manual/en/book.mysqli.php%E2%80%8F" rel="">واجهة mysqli</a> هي تحسين (وتعني إضافة MySQL محسَّنة "MySQL Improvement extension") لواجهة MySQL التي أُهملت في الإصدار 5.5 وحُذِفت في الإصدار 7.0. طُوِّرت إضافة <code>mysqli</code> المعروفة أيضًا باسم إضافة MySQL المحسَّنة للاستفادة من إيجابيات الميزات الجديدة الموجودة في إصدارات أنظمة MySQL بدءًا من الإصدار 4.1.3 وما بعد. ضُمِّنت إضافة <code>mysqli</code> في الإصدار PHP 5 وما بعده.
</p>

<h2>
	إغلاق الاتصال
</h2>

<p>
	يُنصَح بإغلاق الاتصال بعد الانتهاء من الاستعلام من قاعدة البيانات لتحرير الموارد.
</p>

<p>
	<strong>النمط الكائني التوجه</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_7" style="">
<span class="pln">$conn</span><span class="pun">-&gt;</span><span class="pln">close</span><span class="pun">();</span></pre>

<p>
	<strong>النمط الإجرائي</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_9" style="">
<span class="pln">mysqli_close</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">);</span></pre>

<p>
	<strong>ملاحظة</strong>: سيُغلق الاتصال مع الخادم حالما ينتهي تنفيذ السكربت ما لم يُغلق مبكرًا باستدعاء دالة إغلاق الاتصال بشكلٍ صريح.
</p>

<p>
	حالة استخدام: يجب بكل تأكيد إغلاق الاتصال إذا احتوى السكربت على كمية معقولة من المعالجة بعد جلب النتيجة واستعاد مجموعة النتائج كاملةً، إذا لم نقم بذلك فهناك احتمال أن يصل خادم MySQL إلى حد الاتصال عندما يكون خادم الويب قيد الاستخدام المكثف.
</p>

<h2>
	اتصال MySQLi
</h2>

<p>
	<strong>النمط الكائني التوجه</strong>
</p>

<p>
	الاتصال بالخادم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_17" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> mysqli</span><span class="pun">(</span><span class="str">"localhost"</span><span class="pun">,</span><span class="str">"my_user"</span><span class="pun">,</span><span class="str">"my_password"</span><span class="pun">);</span></pre>

<p>
	ضبط قاعدة البيانات الافتراضية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_15" style="">
<span class="pln">$conn</span><span class="pun">-&gt;</span><span class="pln">select_db</span><span class="pun">(</span><span class="str">"my_db"</span><span class="pun">);</span></pre>

<p>
	الاتصال بقاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_13" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> mysqli</span><span class="pun">(</span><span class="str">"localhost"</span><span class="pun">,</span><span class="str">"my_user"</span><span class="pun">,</span><span class="str">"my_password"</span><span class="pun">,</span><span class="str">"my_db"</span><span class="pun">);</span></pre>

<p>
	<strong>النمط الإجرائي</strong>
</p>

<p>
	الاتصال بالخادم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_19" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> mysqli_connect</span><span class="pun">(</span><span class="str">"localhost"</span><span class="pun">,</span><span class="str">"my_user"</span><span class="pun">,</span><span class="str">"my_password"</span><span class="pun">);</span></pre>

<p>
	ضبط قاعدة البيانات الافتراضية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_21" style="">
<span class="pln">mysqli_select_db</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> </span><span class="str">"my_db"</span><span class="pun">);</span></pre>

<p>
	الاتصال بقاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_23" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> mysqli_connect</span><span class="pun">(</span><span class="str">"localhost"</span><span class="pun">,</span><span class="str">"my_user"</span><span class="pun">,</span><span class="str">"my_password"</span><span class="pun">,</span><span class="str">"my_db"</span><span class="pun">);</span></pre>

<p>
	<strong>التحقق من الاتصال بقاعدة البيانات</strong>
</p>

<p>
	النمط الكائني التوجه
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_25" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">-&gt;</span><span class="pln">connect_errno </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    trigger_error</span><span class="pun">(</span><span class="pln">$db</span><span class="pun">-&gt;</span><span class="pln">connect_error</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// else: successfully connected</span></pre>

<p>
	النمط الإجرائي
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_27" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">$conn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    trigger_error</span><span class="pun">(</span><span class="pln">mysqli_connect_error</span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// else: successfully connected</span></pre>

<h2>
	تمرير حلقة على نتائج MySQLi
</h2>

<p>
	تجعل PHP من السهل الحصول على البيانات من النتائج وتكرارها باستخدام تعليمة <code>while</code>، وترجع <code>false</code> عندما تفشل في الحصول على السطر التالي وتنتهي الحلقة. تعمل هذه الأمثلة مع:
</p>

<ul>
<li>
		<a href="%E2%80%8Fhttps://www.php.net/manual/en/mysqli-result.fetch-assoc.php" rel="">mysqli_fetch_assoc</a> - مصفوفة ترابطية مع أسماء الأعمدة كمفاتيح.
	</li>
	<li>
		<a href="%E2%80%8Fhttps://www.php.net/manual/en/mysqli-result.fetch-object.php" rel="">mysqli_fetch_object</a> - كائن <code>stdClass</code> مع أسماء الأعمدة كمتغيرات.
	</li>
	<li>
		<a href="%E2%80%8Fhttps://www.php.net/manual/en/mysqli-result.fetch-array.php" rel="">mysqli_fetch_array</a> - مصفوفة ترابطية وعددية (يمكنك استخدام وسيط لتحصل على إحداها)
	</li>
	<li>
		<a href="%E2%80%8Fhttps://www.php.net/manual/en/mysqli-result.fetch-row.php%E2%80%8F" rel="">mysqli_fetch_row</a> - مصفوفة عددية.
	</li>
</ul>
<p>
	<strong>النمط الكائني التوجه</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_29" style="">
<span class="kwd">while</span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> $result</span><span class="pun">-&gt;</span><span class="pln">fetch_assoc</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    var_dump</span><span class="pun">(</span><span class="pln">$row</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>النمط الإجرائي</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_31" style="">
<span class="kwd">while</span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> mysqli_fetch_assoc</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    var_dump</span><span class="pun">(</span><span class="pln">$row</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا استخدام الشيفرة التالية للحصول على معلومات دقيقة من النتائج:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_33" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> $result</span><span class="pun">-&gt;</span><span class="pln">fetch_assoc</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'Name and surname: '</span><span class="pun">.</span><span class="pln">$row</span><span class="pun">[</span><span class="str">'name'</span><span class="pun">].</span><span class="str">' '</span><span class="pun">.</span><span class="pln">$row</span><span class="pun">[</span><span class="str">'surname'</span><span class="pun">].</span><span class="str">'&lt;br&gt;'</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫طباعة معلومات من العمود 'age'    </span><span class="pln">
    echo </span><span class="str">'Age: '</span><span class="pun">.</span><span class="pln">$row</span><span class="pun">[</span><span class="str">'age'</span><span class="pun">].</span><span class="str">'&lt;br&gt;'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	تعليمات التحضير في MySQLi
</h2>

<p>
	يمكنك قراءة المزيد حول منع حقن SQL مع الاستعلامات التي تحوي معاملات لمعرفة سبب مساعدة تعليمات التحضير لك في تأمين تعليمات SQL ضد هجمات حقن SQL.
</p>

<p>
	المتغير <code>‎$conn</code> هو كائن MySQLi في الشيفرات التالية وفي المثالين نفرض أنّ <code>‎$sql</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_35" style="">
<span class="pln">$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SELECT column_1
    FROM table
    WHERE column_2 = ?
    AND column_3 &gt; ?"</span><span class="pun">;</span></pre>

<p>
	تمثّل <code>?</code> القيم التي سنوفرها لاحقًا، لاحظ أننا لا نحتاج علامات الاقتباس للنصوص البديلة بغض النظر عن النوع، يمكننا أيضًا أن نوفر النصوص البديلة فقط في جزء البيانات من الاستعلام أي <code>SET</code> و<code>VALUES</code> و<code>WHERE</code>، ولا يمكن استخدام النصوص البديلة في الأجزاء <code>SELECT</code> أو <code>FROM</code>.
</p>

<p>
	<strong>النمط الكائني التوجه</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_37" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$stmt </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="pln">$sql</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $stmt</span><span class="pun">-&gt;</span><span class="pln">bind_param</span><span class="pun">(</span><span class="str">"si"</span><span class="pun">,</span><span class="pln"> $column_2_value</span><span class="pun">,</span><span class="pln"> $column_3_value</span><span class="pun">);</span><span class="pln">
    $stmt</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">();</span><span class="pln">
    $stmt</span><span class="pun">-&gt;</span><span class="pln">bind_result</span><span class="pun">(</span><span class="pln">$column_1</span><span class="pun">);</span><span class="pln">
    $stmt</span><span class="pun">-&gt;</span><span class="pln">fetch</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// ‫يمكننا الآن استخدام المتغير ‎$column_1 مثل أي متغير PHP آخر</span><span class="pln">
    $stmt</span><span class="pun">-&gt;</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>النمط الإجرائي</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_39" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$stmt </span><span class="pun">=</span><span class="pln"> mysqli_prepare</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $sql</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    mysqli_stmt_bind_param</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">,</span><span class="pln"> </span><span class="str">"si"</span><span class="pun">,</span><span class="pln"> $column_2_value</span><span class="pun">,</span><span class="pln"> $column_3_value</span><span class="pun">);</span><span class="pln">
    mysqli_stmt_execute</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// جلب البيانات هنا</span><span class="pln">
    mysqli_stmt_close</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُحدَّد المعامل الأول للتابع <code>‎$stmt-&gt;bind_param</code> أو المعامل الثاني للتابع <code>mysqli_stmt_bind_param</code> وفقًا لنمط البيانات للمعامل المقابل في استعلام SQL:
</p>
<style type="text/css">
table {
    width: 100%; 
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table><tbody>
<tr>
<td>
				<strong>المعامل</strong>
			</td>
			<td>
				<strong>نوع البيانات للمعامل المقيّد</strong>
			</td>
		</tr>
<tr>
<td>
				i
			</td>
			<td>
				integer عدد صحيح
			</td>
		</tr>
<tr>
<td>
				d
			</td>
			<td>
				double عدد عشري
			</td>
		</tr>
<tr>
<td>
				s
			</td>
			<td>
				string سلسلة نصية
			</td>
		</tr>
<tr>
<td>
				b
			</td>
			<td>
				blob كائن بيانات ثنائية
			</td>
		</tr>
</tbody></table>
<p>
	يجب أن تكون قائمة المعاملات بنفس الترتيب الموجود في الاستعلام، تعني <code>si</code> في هذا المثال أنّ المعامل الأول <code>‎(column_2 = ?)‎</code> هو سلسلة نصية والمعامل الثاني <code>‎(column_3 &gt; ?)‎</code> عدد صحيح.
</p>

<h2>
	سلاسل الهروب النصية
</h2>

<p>
	سلاسل الهروب النصية (Escaping Strings) طريقة قديمة (وأقل أمنًا) لتأمين البيانات لإدراجها في استعلام، تعمل باستخدام <a href="%E2%80%8Fhttps://dev.mysql.com/doc/refman/5.7/en/mysql-real-escape-string.html" rel="">دالة MySQL ‏mysql_real_escape_string()<code>‎</code></a> لمعالجة وتعقيم البيانات (أي أنّ PHP لا تقوم بعملية الهروب). توفر واجهة برمجة التطبيقات MySQLi الوصول المباشر لهذه الدالة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_41" style="">
<span class="pln">$escaped </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">real_escape_string</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'var'</span><span class="pun">]);</span><span class="pln">

</span><span class="com">//أو</span><span class="pln">
$escaped </span><span class="pun">=</span><span class="pln"> mysqli_real_escape_string</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'var'</span><span class="pun">]);</span></pre>

<p>
	عند هذه النقطة يصبح لديك سلسلة نصية تعدها MySQL آمنة للاستخدام في استعلام مباشر.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_43" style="">
<span class="pln">$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">'SELECT * FROM users WHERE username = "'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $escaped </span><span class="pun">.</span><span class="pln"> </span><span class="str">'"'</span><span class="pun">;</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$sql</span><span class="pun">);</span></pre>

<p>
	إذًا لم لا تُعدّ هذه الطريقة آمنة مثل تعليمات التحضير؟ لأنه يوجد عدة طرق لخداع MySQL لإنتاج سلسلة نصية تُعد آمنة. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_45" style="">
<span class="pln">$id </span><span class="pun">=</span><span class="pln"> mysqli_real_escape_string</span><span class="pun">(</span><span class="str">"1 OR 1=1"</span><span class="pun">);</span><span class="pln">
$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">'SELECT * FROM table WHERE id = '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $id</span><span class="pun">;</span></pre>

<p>
	لا يمثّل التعبير <code>‎1 OR 1=1‎</code> بيانات ستهرّبها MySQL، لكنه لا يزال يمثّل حقن SQL، يوجد <a href="https://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string" rel="external nofollow">أمثلة أخرى</a> تمثّل حالات تُعاد فيها بيانات غير آمنة، المشكلة هي أنّ دالة الهروب في MySQL صُممت لجعل البيانات تتوافق مع صيغة SQL وليس للتأكد من أنّ MySQL لا تتمكن من خلط بيانات المستخدم من أجل تعليمات SQL.
</p>

<h2>
	تنقيح أخطاء SQL في MySQLi
</h2>

<p>
	الاستعلام في الشيفرة التالية سيفشل (استخدمنا المتغير ‎$conn للاتصال بالخادم كما وضحنا سابقًا):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_47" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'SELECT * FROM non_existent_table'</span><span class="pun">);</span></pre>

<p>
	نتيجة <code>‎$result</code> هي <code>false</code> وهذا لا يساعدنا على معرفة الخطأ، لحسن الحظ يمكن لمتغير الاتصال <code>‎$conn</code> أن يخبرنا عن الفشل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_49" style="">
<span class="pln">trigger_error</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">-&gt;</span><span class="pln">error</span><span class="pun">);</span></pre>

<p>
	أو بالنمط الإجرائي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_51" style="">
<span class="pln">trigger_error</span><span class="pun">(</span><span class="pln">mysqli_error</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">));</span></pre>

<p>
	عندها ستحصل على خطأ مشابه لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_53" style="">
<span class="typ">Table</span><span class="pln"> </span><span class="str">'my_db.non_existent_table'</span><span class="pln"> doesn</span><span class="str">'t exist</span></pre>

<h2>
	استعلام MySQLi
</h2>

<p>
	تأخذ الدالة <code>query</code> سلسلة SQL صحيحة وتنفّذها مباشرةً على الاتصال بقاعدة البيانات <code>‎$conn</code>.
</p>

<p>
	<strong>النمط الكائني التوجه</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_55" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">"SELECT * FROM `people`"</span><span class="pun">);</span></pre>

<p>
	<strong>النمط الإجرائي</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_57" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> mysqli_query</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> </span><span class="str">"SELECT * FROM `people`"</span><span class="pun">);</span></pre>

<p>
	سيظهر تحذير، المشكلة الشائعة هنا هي أنّك تنفّذ الشيفرة ببساطة وتتوقعها أن تعمل (تعيد مثلًا كائنًا من الصنف <a href="%E2%80%8Fhttps://www.php.net/manual/en/class.mysqli-stmt.php" rel="">mysqli_stmt</a>)، بما أنّ هذه الدالة تأخذ سلسلة نصية فقط فأنت تبني الاستعلام أولًا وإذا وُجدَت أي أخطاء في SQL سيفشل مصرِّف MySQL وعندها تعيد الدالة القيمة <code>false</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_59" style="">
<span class="com">// سيفشل الاستعلام التالي</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'SELECT * FROM non_existent_table'</span><span class="pun">);</span><span class="pln"> 
$row </span><span class="pun">=</span><span class="pln"> $result</span><span class="pun">-&gt;</span><span class="pln">fetch_assoc</span><span class="pun">();</span></pre>

<p>
	ستنتج الشيفرة السابقة خطأ <code>E_FATAL</code> لأنّ نتيجة <code>‎$result</code> هي <code>false</code> وليس كائنًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_61" style="">
<span class="pln">PHP </span><span class="typ">Fatal</span><span class="pln"> error</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Call</span><span class="pln"> to a member </span><span class="kwd">function</span><span class="pln"> fetch_assoc</span><span class="pun">()</span><span class="pln"> on a non</span><span class="pun">-</span><span class="kwd">object</span></pre>

<p>
	الخطأ الإجرائي مشابه لكنه ليس خطأً فادحًا لأننا نخترق توقعات الدالة فقط.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_63" style="">
<span class="com">// نفس الاستعلام السابق</span><span class="pln">
$row </span><span class="pun">=</span><span class="pln"> mysqli_fetch_assoc</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">);</span></pre>

<p>
	ستحصل على الرسالة التالية من PHP:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_67" style="">
<span class="pln">mysqli_fetch_array</span><span class="pun">()</span><span class="pln"> expects parameter </span><span class="lit">1</span><span class="pln"> to be mysqli_result</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> given</span></pre>

<p>
	يمكنك تجنب هذا باستخدام شيفرة الاختبار التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_71" style="">
<span class="kwd">if</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">)</span><span class="pln"> $row </span><span class="pun">=</span><span class="pln"> mysqli_fetch_assoc</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">);</span></pre>

<h2>
	كيفية الحصول على البيانات من تعليمات التحضير
</h2>

<p>
	<strong>تعليمات التحضير</strong>
</p>

<p>
	اطّلع على تعليمات التحضير في mysqli لمعرفة كيفية تحضير وتنفيذ استعلام.
</p>

<p>
	<strong>ربط النتائج</strong>
</p>

<ul>
<li>
		<strong>النمط الكائني التوجه</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_73" style="">
<span class="pln">$stmt</span><span class="pun">-&gt;</span><span class="pln">bind_result</span><span class="pun">(</span><span class="pln">$forename</span><span class="pun">);</span></pre>

<ul>
<li>
		<strong>النمط الإجرائي</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_76" style="">
<span class="pln">mysqli_stmt_bind_result</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">,</span><span class="pln"> $forename</span><span class="pun">);</span></pre>

<p>
	مشكلة استخدام الدالة <code>bind_result</code> أنّها تتطلب تعليمة لتحديد الأعمدة التي ستُستخدم، أي أنّه كي تعمل الشيفرة السابقة يجب أن يبدو الاستعلام بالشكل <code>SELECT forename FROM users</code>، لتضمين المزيد من الأعمدة يمكنك إضافتها كمعاملات للدالة <code>bind_result</code> (وتأكد من إضافتهم إلى استعلام SQL).
</p>

<p>
	نُسند في كلتا الحالتين العمود <code>forename</code> للمتغير <code>‎$forename</code>، تأخذ هذه الدالة عدد وسائط بعدد الأعمدة التي تريد إسنادها، يتم هذا الإسناد مرة واحدة بما أنّ الدالة تُربَط بالمرجع، لذا يمكننا تمرير حلقة بالشكل التالي:
</p>

<ul>
<li>
		<strong>النمط الكائني التوجه</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_78" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">-&gt;</span><span class="pln">fetch</span><span class="pun">())</span><span class="pln">
    echo </span><span class="str">"$forename&lt;br /&gt;"</span><span class="pun">;</span></pre>

<ul>
<li>
		<strong>النمط الإجرائي</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_80" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">mysqli_stmt_fetch</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">))</span><span class="pln">
    echo </span><span class="str">"$forename&lt;br /&gt;"</span><span class="pun">;</span></pre>

<p>
	العيب في هذا أنّك تحتاج لإسناد الكثير من المتغيرات في وقت واحد وهذا يجعل تتبع الاستعلامات الكبيرة أمرًا صعبًا، إذا كان لديك <a href="%E2%80%8Fhttps://www.php.net/manual/en/book.mysqlnd.php%E2%80%8F" rel="">محرك MySQL أساسي (mysqlnd)</a> مثبّت فإنّ كل ما تحتاجه هو استخدام <a href="%E2%80%8Fhttps://www.php.net/manual/en/mysqli-stmt.get-result.php" rel="">get_result</a>.
</p>

<ul>
<li>
		<strong>النمط الكائني التوجه</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_82" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> $stmt</span><span class="pun">-&gt;</span><span class="pln">get_result</span><span class="pun">();</span></pre>

<ul>
<li>
		<strong>النمط الإجرائي</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_84" style="">
<span class="pln">$result </span><span class="pun">=</span><span class="pln"> mysqli_stmt_get_result</span><span class="pun">(</span><span class="pln">$stmt</span><span class="pun">);</span></pre>

<p>
	يعدّ هذا سهلًا لأننا نحصل على كائن من الصنف <a href="%E2%80%8Fhttps://www.php.net/manual/en/class.mysqli-result.php%E2%80%8F" rel="">mysqli_result</a>? وهو نفس الكائن الذي تعيده <code>mysqli_query</code> أي أنّه يمكنك استخدام حلقة لعرض النتيجة.
</p>

<p>
	<strong>ماذا لو لم نستطع تثبيت <code>mysqlnd</code>؟</strong>
</p>

<p>
	يمكنك الاطلاع على جواب مناسب من <a href="https://stackoverflow.com/questions/10752815/mysqli-get-result-alternative/30551477#30551477" rel="external nofollow">هنا</a>.
</p>

<p>
	يمكن أن تؤدي هذه الدالة مهمة <code>get_result</code> بدون أن تكون مثبّتة على الخادم، فهي ببساطة تكرر النتائج وتبني مصفوفة ترابطية.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_86" style="">
<span class="kwd">function</span><span class="pln"> get_result</span><span class="pun">(</span><span class="pln">\mysqli_stmt $statement</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">();</span><span class="pln">
    $statement</span><span class="pun">-&gt;</span><span class="pln">store_result</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun">&lt;</span><span class="pln"> $statement</span><span class="pun">-&gt;</span><span class="pln">num_rows</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $metadata </span><span class="pun">=</span><span class="pln"> $statement</span><span class="pun">-&gt;</span><span class="pln">result_metadata</span><span class="pun">();</span><span class="pln">
        $params </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$field </span><span class="pun">=</span><span class="pln"> $metadata</span><span class="pun">-&gt;</span><span class="pln">fetch_field</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            $params</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">$result</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">][</span><span class="pln">$field</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        call_user_func_array</span><span class="pun">(</span><span class="pln">array</span><span class="pun">(</span><span class="pln">$statement</span><span class="pun">,</span><span class="pln"> </span><span class="str">'bind_result'</span><span class="pun">),</span><span class="pln"> $params</span><span class="pun">);</span><span class="pln">
        $statement</span><span class="pun">-&gt;</span><span class="pln">fetch</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا بعدها استخدام الدالة للحصول على النتائج كما لو أننا نستخدم <code>mysqli_fetch_assoc()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_88" style="">
<span class="pun">&lt;?</span><span class="pln">php
$query </span><span class="pun">=</span><span class="pln"> $mysqli</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="str">"SELECT * FROM users WHERE forename LIKE ?"</span><span class="pun">);</span><span class="pln">
$condition </span><span class="pun">=</span><span class="pln"> </span><span class="str">"J%"</span><span class="pun">;</span><span class="pln">
$query</span><span class="pun">-&gt;</span><span class="pln">bind_param</span><span class="pun">(</span><span class="str">"s"</span><span class="pun">,</span><span class="pln"> $condition</span><span class="pun">);</span><span class="pln">
$query</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">();</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> get_result</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> array_shift</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $row</span><span class="pun">[</span><span class="str">"id"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">' - '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $row</span><span class="pun">[</span><span class="str">"forename"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $row</span><span class="pun">[</span><span class="str">"surname"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">'&lt;br&gt;'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيظهر لنا نفس الخرج في حالة استخدام محرك mysqlnd باستثناء أنّه لا يحتاج للتثبيت، وهذا الحل مناسب جداً إذا كنت لا تستطيع تثبيت المحرك.
</p>

<h2>
	إضافة معرف في MySQLi
</h2>

<p>
	استعادة آخر معرّف مولَّد من استعلام <code>INSERT</code> على جدول فيه عمود <code>AUTO_INCREMENT</code>.
</p>

<ul>
<li>
		<strong>النمط الكائني التوجه</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_90" style="">
<span class="pln">$id </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">insert_id</span><span class="pun">;</span></pre>

<ul>
<li>
		<strong>النمط الإجرائي</strong>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_92" style="">
<span class="pln">$id </span><span class="pun">=</span><span class="pln"> mysqli_insert_id</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">);</span></pre>

<p>
	ترجع الشيفرة السابقة القيمة صفر إذا لم يكن هناك استعلام سابق على الاتصال أو إذا لم يحدّث الاستعلام قيمة <code>AUTO_INCREMENT</code>.
</p>

<p>
	<strong>إضافة معرّف عند تحديث الأسطر</strong>
</p>

<p>
	لا تُرجع تعليمة <code>UPDATE</code> معرّف السطر المُضاف في الحالة العادية، إذ يُرجَع المعرّف <code>AUTO_INCREMENT</code> عند حفظ سطر جديد فقط (أو إضافته)، يمكن استخدام الصياغة <code>INSERT ... ON DUPLICATE KEY UPDATE</code> للتحديث مما يجعل التحديثات تطرأ على المعرِّف الجديد.
</p>

<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_94" style="">
<span class="pln">CREATE TABLE iodku </span><span class="pun">(</span><span class="pln">
    id INT AUTO_INCREMENT NOT NULL</span><span class="pun">,</span><span class="pln">
    name VARCHAR</span><span class="pun">(</span><span class="lit">99</span><span class="pun">)</span><span class="pln"> NOT NULL</span><span class="pun">,</span><span class="pln">
    misc INT NOT NULL</span><span class="pun">,</span><span class="pln">
    PRIMARY KEY</span><span class="pun">(</span><span class="pln">id</span><span class="pun">),</span><span class="pln">
    UNIQUE</span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
</span><span class="pun">)</span><span class="pln"> ENGINE</span><span class="pun">=</span><span class="typ">InnoDB</span><span class="pun">;</span><span class="pln">

INSERT INTO iodku </span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> misc</span><span class="pun">)</span><span class="pln">
    VALUES
    </span><span class="pun">(</span><span class="str">'Leslie'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">123</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">(</span><span class="str">'Sally'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">456</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Query</span><span class="pln"> OK</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> rows affected </span><span class="pun">(</span><span class="lit">0.00</span><span class="pln"> sec</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Records</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="typ">Duplicates</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="typ">Warnings</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span></pre>

<table><tbody>
<tr>
<td>
				id
			</td>
			<td>
				name
			</td>
			<td>
				misc
			</td>
		</tr>
<tr>
<td>
				1
			</td>
			<td>
				Leslie
			</td>
			<td>
				123
			</td>
		</tr>
<tr>
<td>
				2
			</td>
			<td>
				Sally
			</td>
			<td>
				456
			</td>
		</tr>
</tbody></table>
<p>
	في حال حدّثَ الجدول <code>IODKU</code> واستعاد <code>LAST_INSERT_ID()‎</code> المعرِّف المرتبط:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_96" style="">
<span class="pln">$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">"INSERT INTO iodku (name, misc)
    VALUES
    ('Sally', 3333) 
    ON DUPLICATE KEY UPDATE
    id = LAST_INSERT_ID(id),
    misc = VALUES(misc)"</span><span class="pun">;</span><span class="pln">
$conn</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$sql</span><span class="pun">);</span><span class="pln">
$id </span><span class="pun">=</span><span class="pln"> $conn</span><span class="pun">-&gt;</span><span class="pln">insert_id</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	يجب أن تحدّث الشيفرة السابقة السطر الثاني من الجدول وتعيد القيمة الحالية للمعرِّف (2).
</p>

<p>
	الحالة التي يحدث فيها إضافة سطر وتعيد <code>LAST_INSERT_ID()‎</code> المعرِّف الجديد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_98" style="">
<span class="pln">$sql </span><span class="pun">=</span><span class="pln"> </span><span class="str">"INSERT INTO iodku (name, misc)
    VALUES
    ('Dana', 789) 
    ON DUPLICATE KEY UPDATE
    id = LAST_INSERT_ID(id),
    misc = VALUES(misc);
    $conn-&gt;query($sql);
    $id = $conn-&gt;insert_id; </span></pre>

<p>
	يجب أن تضيف الشيفرة السابقة سطرًا جديدًا إلى الجدول وتعيد القيمة الأخيرة للمعرِّف (3). ينتج عن الاستعلام:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_100" style="">
<span class="pln">SELECT </span><span class="pun">*</span><span class="pln"> FROM iodku</span><span class="pun">;</span></pre>

<p>
	الجدول التالي:
</p>

<table><tbody>
<tr>
<td>
				id
			</td>
			<td>
				name
			</td>
			<td>
				misc
			</td>
		</tr>
<tr>
<td>
				1
			</td>
			<td>
				Leslie
			</td>
			<td>
				123
			</td>
		</tr>
<tr>
<td>
				2
			</td>
			<td>
				Sally
			</td>
			<td>
				3333
			</td>
		</tr>
<tr>
<td>
				3
			</td>
			<td>
				Dana
			</td>
			<td>
				789
			</td>
		</tr>
</tbody></table>
<h2>
	درس سريع لمكتبة SQLite3
</h2>

<p>
	إليك مثال كامل عن جميع واجهات برمجة التطبيقات الشائعة الاستخدام المرتبطة بمكتبة <code>SQLite3</code>، بهدف جعلك تعمل بسرعة كبيرة ويمكنك أيضاً الحصول على <a href="https://gist.github.com/bladeSk/6294d3266370868601a7d2e50285dbf5" rel="external nofollow">ملف PHP قابل للتنفيذ</a> لهذا الدرس.
</p>

<p>
	<strong>إنشاء/فتح قاعدة بيانات</strong>
</p>

<p>
	ننشئ قاعدة بيانات أولاً، ننشئها فقط إذا لم يكن الملف موجوداً ونفتحها للقراءة/الكتابة، امتداد الملف يعود لك لكن الشائع هو استخدام الامتداد <code>‎.sqlite</code> الأكثر إيضاحًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_102" style="">
<span class="pln">$db </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SQLite3</span><span class="pun">(</span><span class="str">'analytics.sqlite'</span><span class="pun">,</span><span class="pln"> SQLITE3_OPEN_CREATE </span><span class="pun">|</span><span class="pln"> SQLITE3_OPEN_READWRITE</span><span class="pun">);</span></pre>

<p>
	<strong>إنشاء جدول</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_104" style="">
<span class="pln">$db</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'CREATE TABLE IF NOT EXISTS "visits" (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    "user_id" INTEGER,
    "url" VARCHAR,
    "time" DATETIME
)'</span><span class="pun">);</span></pre>

<p>
	<strong>إضافة عينة بيانات</strong>
</p>

<p>
	يُنصح بإحاطة الاستعلامات المرتبطة ضمن عملية (transaction) (مع الكلمات المفتاحية <code>BEGIN</code> و<code>COMMIT</code>) حتى لو لم تكن مهتمًا بالترابط، إذا لم تفعل ذلك فإنّ <code>SQLite</code> ستحيط كل استعلام مفرد بعملية بشكلٍ تلقائي مما يؤدي إلى البطء الشديد. قد تُفاجئ بسبب <a href="%E2%80%8Fhttps://stackoverflow.com/questions/3852068/sqlite-insert-very-slow/3852082#3852082" rel="">بطء تعليمات <code>INSERT</code></a> إذا كنت جديدًا على استخدام <code>SQLite</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_106" style="">
<span class="pln">$db</span><span class="pun">-&gt;</span><span class="kwd">exec</span><span class="pun">(</span><span class="str">'BEGIN'</span><span class="pun">);</span><span class="pln">
$db</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'INSERT INTO "visits" ("user_id", "url", "time")
    VALUES (42, "/test", "2017-01-14 10:11:23")'</span><span class="pun">);</span><span class="pln">
$db</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'INSERT INTO "visits" ("user_id", "url", "time")
    VALUES (42, "/test2", "2017-01-14 10:11:44")'</span><span class="pun">);</span><span class="pln">
$db</span><span class="pun">-&gt;</span><span class="kwd">exec</span><span class="pun">(</span><span class="str">'COMMIT'</span><span class="pun">);</span></pre>

<p>
	يمكنك القيام بإضافة بيانات قد لا تكون آمنة مع تعليمة تحضير، باستخدام المعاملات ذات الأسماء (named parameters):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_108" style="">
<span class="pln">$statement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="str">'INSERT INTO "visits" ("user_id", "url", "time")
    VALUES (:uid, :url, :time)'</span><span class="pun">);</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">bindValue</span><span class="pun">(</span><span class="str">':uid'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1337</span><span class="pun">);</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">bindValue</span><span class="pun">(</span><span class="str">':url'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/test'</span><span class="pun">);</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">bindValue</span><span class="pun">(</span><span class="str">':time'</span><span class="pun">,</span><span class="pln"> date</span><span class="pun">(</span><span class="str">'Y-m-d H:i:s'</span><span class="pun">));</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">();</span><span class="pln"> you can reuse the statement </span><span class="kwd">with</span><span class="pln"> different values</span></pre>

<p>
	<strong>جلب البيانات</strong>
</p>

<p>
	لنجلب زيارات اليوم للمستخدم رقم 42، سنستخدم تعليمة التحضير من جديد لكن هذه المرة مع معاملات ذات أسماء وهذا أكثر إيجازًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_110" style="">
<span class="pln">$statement </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="str">'SELECT * FROM "visits" WHERE "user_id" = ? AND "time" &gt;= ?'</span><span class="pun">);</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">bindValue</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">);</span><span class="pln">
$statement</span><span class="pun">-&gt;</span><span class="pln">bindValue</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2017-01-14'</span><span class="pun">);</span><span class="pln">
$result </span><span class="pun">=</span><span class="pln"> $statement</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">();</span><span class="pln">

echo </span><span class="str">"Get the 1st row as an associative array:\n"</span><span class="pun">;</span><span class="pln">
print_r</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">-&gt;</span><span class="pln">fetchArray</span><span class="pun">(</span><span class="pln">SQLITE3_ASSOC</span><span class="pun">));</span><span class="pln">
echo </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
echo </span><span class="str">"Get the next row as a numeric array:\n"</span><span class="pun">;</span><span class="pln">
print_r</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">-&gt;</span><span class="pln">fetchArray</span><span class="pun">(</span><span class="pln">SQLITE3_NUM</span><span class="pun">));</span><span class="pln">
echo </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	ملاحظة: تُرجع الدالة <code>fetchArray()‎</code> القيمة <code>false</code> إذا لم يكن هناك المزيد من الأسطر، يمكنك الاستفادة من هذا في حلقة <code>while</code>.
</p>

<p>
	حرّر الذاكرة - لا يحدث هذا تلقائيًا أثناء تشغيل السكربت.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_112" style="">
<span class="pln">$result</span><span class="pun">-&gt;</span><span class="pln">finalize</span><span class="pun">();</span></pre>

<p>
	<strong>الاختزالات</strong>
</p>

<p>
	إليك اختزال مفيد لجلب سطر واحد كمصفوفة ترابطية، يعني المعامل الثاني أننا نريد كل الأعمدة المُختارة. انتبه إلى أنّ هذا الاختزال لا يدعم ربط المعاملات لكن يمكنك بدلًا من ذلك الهروب من السلاسل النصية، ضع القيم دائمًا بين علامات اقتباس مفردة إذ تستخدم علامات الاقتباس المزدوجة لأسماء الجداول والأعمدة (بشكل مشابه لعلامات الاقتباس المائلة في MySQL).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_114" style="">
<span class="pln">$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">'SELECT * FROM "visits" WHERE "url" = \''</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
    </span><span class="typ">SQLite3</span><span class="pun">::</span><span class="pln">escapeString</span><span class="pun">(</span><span class="str">'/test'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
    </span><span class="str">'\' ORDER BY "id" DESC LIMIT 1'</span><span class="pun">;</span><span class="pln">

$lastVisit </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">querySingle</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

echo </span><span class="str">"Last visit of '/test':\n"</span><span class="pun">;</span><span class="pln">
print_r</span><span class="pun">(</span><span class="pln">$lastVisit</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	اختزال آخر مفيد لاستعادة قيمة واحدة فقط.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_116" style="">
<span class="pln">$userCount </span><span class="pun">=</span><span class="pln"> $db</span><span class="pun">-&gt;</span><span class="pln">querySingle</span><span class="pun">(</span><span class="str">'SELECT COUNT(DISTINCT "user_id") FROM "visits"'</span><span class="pun">);</span><span class="pln">

echo </span><span class="str">"User count: $userCount\n"</span><span class="pun">;</span><span class="pln">
echo </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	<strong>التنظيف</strong>
</p>

<p>
	في النهاية، أغلق قاعدة البيانات على الرغم من أنّ هذا يتم تلقائيًا عندما ينتهي السكربت.
</p>

<pre class="ipsCode">
$db-&gt;close();
</pre>

<h2>
	الاستعلام من قاعدة بيانات
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_118" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// ‫إنشاء كائن SQLite3 جديد من ملف قاعدة البيانات على الخادم</span><span class="pln">
$database </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SQLite3</span><span class="pun">(</span><span class="str">'mysqlitedb.db'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫الاستعلام من قاعدة البيانات باستخدام SQL</span><span class="pln">
$results </span><span class="pun">=</span><span class="pln"> $database</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'SELECT bar FROM foo'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// التكرار على كل النتائج وإظهارهم على الصفحة</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> $results</span><span class="pun">-&gt;</span><span class="pln">fetchArray</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    var_dump</span><span class="pun">(</span><span class="pln">$row</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h2>
	استعادة نتيجة واحدة فقط
</h2>

<p>
	بالإضافة إلى استخدام تعليمات <code>‏LIMIT</code> في SQL، يمكنك استخدام الدالة <code>querySingle</code> في <code>SQLite3</code> لاستعادة سطر واحد أو العمود الأول.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_269_120" style="">
<span class="pun">&lt;?</span><span class="pln">php
$database </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SQLite3</span><span class="pun">(</span><span class="str">'mysqlitedb.db'</span><span class="pun">);</span><span class="pln">

</span><span class="com">//(1)</span><span class="pln">
$database</span><span class="pun">-&gt;</span><span class="pln">querySingle</span><span class="pun">(</span><span class="str">'SELECT column1Name FROM table WHERE column2Name=1'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// (2)</span><span class="pln">
$database</span><span class="pun">-&gt;</span><span class="pln">querySingle</span><span class="pun">(</span><span class="str">'SELECT column1Name, column2Name FROM user WHERE column3Name=1'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span></pre>

<p>
	في الموضع (1) بدون ضبط المعامل الثاني الاختياري للقيمة <code>true</code> سيُرجع الاستعلام العمود الأول من السطر الأول للنتائج فقط ويكون من نفس نوع <code>columnName</code>.
</p>

<p>
	في الموضع (2) مع المعامل الاختياري <code>entire_row</code> سيرجع هذا الاستعلام مصفوفة من كامل السطر الأول من نتائج الاستعلام.
</p>

<p>
	ترجمة -وبتصرف- للفصول من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-mongodb-%D9%88-redis-%D9%81%D9%8A-php-r1173/" rel="">استخدام MongoDB و Redis في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-php-r1130/" rel="">المقابس (sockets) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1131</guid><pubDate>Wed, 03 Mar 2021 13:02:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x642;&#x627;&#x628;&#x633; (sockets) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-php-r1130/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/9.png.191d022cc0e3e717a13ef926a52f25e1.png" /></p>

<h2>
	مقبس عميل TCP
</h2>

<h3>
	إنشاء مقبس يستخدم TCP (‏Transmission Control Protocol)
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_9" style="">
<span class="pln">$socket </span><span class="pun">=</span><span class="pln"> socket_create</span><span class="pun">(</span><span class="pln">AF_INET</span><span class="pun">,</span><span class="pln"> SOCK_STREAM</span><span class="pun">,</span><span class="pln"> SOL_TCP</span><span class="pun">);</span></pre>

<p>
	تأكّد من أنّ المقبس (socket) أُنشئ بنجاح، تُستخدم الدالة <code>onSocketFailure</code> لمعالجة أخطاء المقبس، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_11" style="">
<span class="kwd">if</span><span class="pun">(!</span><span class="pln">is_resource</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> onSocketFailure</span><span class="pun">(</span><span class="str">"Failed to create socket"</span><span class="pun">);</span></pre>

<h3>
	اتصال المقبس بعنوان محدد
</h3>

<p>
	يفشل السطر الثاني بأمان إذا فشل الاتصال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_13" style="">
<span class="pln">socket_connect</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="str">"chat.stackoverflow.com"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6667</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">or</span><span class="pln"> onSocketFailure</span><span class="pun">(</span><span class="str">"Failed to connect to chat.stackoverflow.com:6667"</span><span class="pun">,</span><span class="pln"> $socket</span><span class="pun">);</span></pre>

<h3>
	إرسال بيانات إلى الخادم
</h3>

<p>
	ترسل الدالة <code>socket_write</code> البايتات عبر مقبس، تُمثَّل مصفوفة البايت في PHP بسلسلة نصية والتي هي غير حساسة للترميز بشكلٍ طبيعي.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_15" style="">
<span class="pln">socket_write</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="str">"NICK Alice\r\nUSER alice 0 * :Alice\r\n"</span><span class="pun">);</span></pre>

<h3>
	إرسال بيانات من الخادم
</h3>

<p>
	تستقبل الشيفرة التالية بعض البيانات من الخادم باستخدام الدالة <code>socket_read</code>، إنّ تمرير قيمة المعامل الثالث على أنّها <code>PHP_NORMAL_READ</code> يقرأ حتى البايت <code>‎\r/\n</code> ويُضمَّن في القيمة المُعادة، أما تمريرها على أنّها <code>PHP_BINARY_READ</code> يقرأ الكمية المطلوبة من بيانات المجرى.
</p>

<p>
	تُعيد الدالة <code>socket_read</code> القيمة <code>false</code> مباشرةً إذا اُستدعيت الدالة <code>socket_set_nonblock</code> قبلها واُستخدمَت القيمة <code>PHP_BINARY_READ</code>، وإلا يُعطَّل التابع حتى تُستقبَل بيانات كافية (الوصول إلى الطول المحدد في المعامل الثاني أو الوصول إلى نهاية السطر) أو يُغلَق المقبس.
</p>

<p>
	يقرأ المثال التالي بيانات من خادم IRC (‏Internet Relay Chat) بشكلٍ افتراضي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_17" style="">
<span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// قراءة سطر من المقبس</span><span class="pln">
    $line </span><span class="pun">=</span><span class="pln"> socket_read</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1024</span><span class="pun">,</span><span class="pln"> PHP_NORMAL_READ</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">substr</span><span class="pun">(</span><span class="pln">$line</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="str">"\r"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (1)</span><span class="pln">
        socket_read</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> PHP_BINARY_READ</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    $message </span><span class="pun">=</span><span class="pln"> parseLine</span><span class="pun">(</span><span class="pln">$line</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">-&gt;</span><span class="pln">type </span><span class="pun">===</span><span class="pln"> </span><span class="str">"QUIT"</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُقرأ في الموضع (1) بايت واحد من المقبس أو يتم تجاوزه، نفرض أنّ البايت التالي في المجرى يجب أن يكون <code>‎\n‎</code> ويعدّ هذا ممارسة سيئة ويجعل السكربت ضعيفًا ومعرّضًا لقيم غير متوقعة.
</p>

<h3>
	إغلاق المقبس
</h3>

<p>
	يؤدي إغلاق المقبس إلى تحريره وتحرير الموارد المرتبطة به.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_19" style="">
<span class="pln">socket_close</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">);</span></pre>

<h2>
	مقبس خادم TCP
</h2>

<h3>
	إنشاء المقبس
</h3>

<p>
	إنشاء مقبس يستخدم TCP نفس طريقة إنشاء مقبس عميل.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_25" style="">
<span class="pln">$socket </span><span class="pun">=</span><span class="pln"> socket_create</span><span class="pun">(</span><span class="pln">AF_INET</span><span class="pun">,</span><span class="pln"> SOCK_STREAM</span><span class="pun">,</span><span class="pln"> SOL_TCP</span><span class="pun">);</span></pre>

<h3>
	ربط المقبس
</h3>

<p>
	يكون اتصال الربط من شبكة ما (المعامل 2) إلى منفذ معين للمقبس (المعامل 3)، المعامل الثاني عادةً هو "0.0.0.0" والذي يقبل الاتصال من كل الشبكات. أحد أشهر الأسباب التي تؤدي إلى حدوث خطأ نتيجة التابع <code>socket_bind</code> هو أن يكون <a data-ss1619595305="1" href="https://www.google.com.hk/search?q=site%3Astackexchange.com%20OR%20site%3Astackoverflow.com%20kill%20processes%20bound%20to%20address" rel="external nofollow">العنوان المحدد مقيد مسبقًا بعملية أخرى</a>. تُنهى عادةً العمليات الأخرى يدويًا (لمنع إنهاء العمليات الحرجة دون قصد) لذا تُحرَّر المقابس.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_27" style="">
<span class="pln">socket_bind</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="str">"0.0.0.0"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6667</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> onSocketFailure</span><span class="pun">(</span><span class="str">"Failed to bind to 0.0.0.0:6667"</span><span class="pun">);</span></pre>

<h3>
	ضبط المقبس للاستماع
</h3>

<p>
	نستخدم التابع <code>socket_listen</code> لجعل المقبس يستمع إلى الاتصالات الواردة، يعبر المعامل الثاني عن عدد الاتصالات الأعظمي المسموح لها أن تكون في قائمة الانتظار قبل قبولها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_29" style="">
<span class="pln">socket_listen</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span></pre>

<h3>
	معالجة الاتصال
</h3>

<p>
	خادم TCP هو خادم يعالج الاتصالات الأبناء، يُنشئ التابع <code>socket_accept</code> اتصال ابن جديد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_31" style="">
<span class="pln">$conn </span><span class="pun">=</span><span class="pln"> socket_accept</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">);</span></pre>

<p>
	نقل بيانات الاتصال من التابع <code>socket_accept</code> هو نفسه في مقبس عميل TCP.
</p>

<p>
	يمكنك استدعاء التابع <code>socket_close($conn);‎</code> مباشرةً عندما تريد إغلاق الاتصال، ولا يؤثر هذا على مقبس خادم TCP الأصلي.
</p>

<h3>
	إغلاق الخادم
</h3>

<p>
	يجب استدعاء التابع <code>socket_close($socket);‎</code> عند الانتهاء من استخدام الخادم، مما سيؤدي إلى تحرير عنوان TCP وبالتالي يُسمح لعمليات أخرى بالربط معه.
</p>

<h2>
	مقبس خادم UDP
</h2>

<p>
	خادم UDP (‏user datagram protocol) لا يعتمد على المجرى بل على الرزمة (packet-based) على عكس TCP، مثلًا عميل يرسل بيانات في وحدات تدعى رزم (packets) إلى الخادم ويعرف العميل العملاء من خلال عناوينهم، لا يوجد دالة مضمَّنة تربط الرزم المختلفة المُرسلة من نفس العميل (على عكس TCP حيث تُعالج البيانات المُرسلة من نفس العميل بمورد محدد ينشأه التابع <code>socket_accept</code>)، يمكننا التفكير أنّه عند كل وصول لرزمة UDP فإنّ اتصال TCP جديد يُقبَل ويُغلق.
</p>

<h3>
	إنشاء مقبس خادم UDP
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_33" style="">
<span class="pln">$socket </span><span class="pun">=</span><span class="pln"> socket_create</span><span class="pun">(</span><span class="pln">AF_INET</span><span class="pun">,</span><span class="pln"> SOCK_DGRAM</span><span class="pun">,</span><span class="pln"> SOL_UDP</span><span class="pun">);</span></pre>

<h3>
	ربط المقبس إلى عنوان
</h3>

<p>
	نفس المعاملات الموجودة لخادم TCP.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_35" style="">
<span class="pln">socket_bind</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="str">"0.0.0.0"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9000</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> onSocketFailure</span><span class="pun">(</span><span class="str">"Failed to bind to 0.0.0.0:9000"</span><span class="pun">,</span><span class="pln">$socket</span><span class="pun">);</span></pre>

<h3>
	إرسال رزمة
</h3>

<p>
	ترسل الشيفرة التالية المتغير <code>‎$data</code> في رزمة UDP إلى <code>‎$address:$port</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_37" style="">
<span class="pln">socket_sendto</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> $data</span><span class="pun">,</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">);</span></pre>

<h3>
	استقبال رزمة
</h3>

<p>
	تحاول الشيفرة التالية إدارة رزم UDP بطريقة تعتمد على فهرسة العميل.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_39" style="">
<span class="pln">$clients </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">){</span><span class="pln">
    socket_recvfrom</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> $buffer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">32768</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> $ip</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
        </span><span class="kwd">or</span><span class="pln"> onSocketFailure</span><span class="pun">(</span><span class="str">"Failed to receive packet"</span><span class="pun">,</span><span class="pln"> $socket</span><span class="pun">);</span><span class="pln">
    $address </span><span class="pun">=</span><span class="pln"> </span><span class="str">"$ip:$port"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$clients</span><span class="pun">[</span><span class="pln">$address</span><span class="pun">]))</span><span class="pln"> $clients</span><span class="pun">[</span><span class="pln">$address</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Client</span><span class="pun">();</span><span class="pln">
    $clients</span><span class="pun">[</span><span class="pln">$address</span><span class="pun">]-&gt;</span><span class="pln">handlePacket</span><span class="pun">(</span><span class="pln">$buffer</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إغلاق الخادم
</h3>

<p>
	يمكن استخدام التابع <code>socket_close</code> على مورد مقبس خادم UDP. سيحرر هذا عنوان UDP مما يسمح بربط العمليات الأخرى إلى هذا العنوان.
</p>

<h2>
	معالجة أخطاء المقبس
</h2>

<p>
	نستخدم التابع <code>socket_last_error</code> للحصول على رقم معرِّف الخطأ الأخير من إضافة المقابس، ونستخدم التابع <code>socket_strerror</code> لتحويل هذا الرقم إلى سلسلة نصيّة قابلة للقراءة من قِبل الإنسان.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1591_41" style="">
<span class="kwd">function</span><span class="pln"> onSocketFailure</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $message</span><span class="pun">,</span><span class="pln"> $socket </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">is_resource</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $message </span><span class="pun">.=</span><span class="pln"> </span><span class="str">": "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">die</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	مقابس الويب (Webscockets)
</h2>

<p>
	ينفّذ استخدام إضافة المقبس (socket) واجهة منخفضة المستوى لدوال اتصال المقبس بالاعتماد على مقابس BSD (‏Berkeley Software Distribution) الشائعة، مما يوفر إمكانية العمل كخادم مقبس وعميل.
</p>

<h3>
	خادم TCP/IP بسيط
</h3>

<p>
	يمكنك أن تجد <a data-ss1619595286="1" data-ss1619595305="1" href="https://www.php.net/manual/en/sockets.examples.php" rel="external nofollow">هنا</a> مثالًا بسيطًا يعتمد على توثيق PHP الرسمي.
</p>

<p>
	أنشئ سكربت مقبس ويب يستمع إلى المنفذ 5000 باستخدام putty والطرفية لتنفيذ الأمر <code>telnet 127.0.0.1 5000</code> (المضيف المحلي)، يرد هذا السكربت بالرسالة التي أرسلتها (كتعقب عكسي):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3066_10" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// تعطيل المهلة</span><span class="pln">
set_time_limit</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// تعطيل التخزين المؤقت للخرج</span><span class="pln">
ob_implicit_flush</span><span class="pun">();</span><span class="pln"> 

</span><span class="com">// الإعدادات</span><span class="pln">
$address </span><span class="pun">=</span><span class="pln"> </span><span class="str">'127.0.0.1'</span><span class="pun">;</span><span class="pln">
$port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">;</span><span class="pln">

</span><span class="com">// (1)</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">$socket </span><span class="pun">=</span><span class="pln"> socket_create</span><span class="pun">(</span><span class="pln">AF_INET</span><span class="pun">,</span><span class="pln"> SOCK_STREAM</span><span class="pun">,</span><span class="pln"> SOL_TCP</span><span class="pun">))</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Couldn't create socket"</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">()).</span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// (2)</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">socket_bind</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Bind Error "</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$sock</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">socket_listen</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Listen Failed "</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">$msgsock </span><span class="pun">=</span><span class="pln"> socket_accept</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"Error: socket_accept: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/* إرسال رسالة ترحيب */</span><span class="pln">
    $msg </span><span class="pun">=</span><span class="pln"> </span><span class="str">"\nPHP Websocket \n"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// الاستماع إلى دخل المستخدم</span><span class="pln">
    </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">false</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$buf </span><span class="pun">=</span><span class="pln"> socket_read</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2048</span><span class="pun">,</span><span class="pln">         PHP_NORMAL_READ</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            echo </span><span class="str">"socket read error: "</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">break</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">$buf </span><span class="pun">=</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">$buf</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="com">// الرد على المستخدم برسالته</span><span class="pln">
        $talkback </span><span class="pun">=</span><span class="pln"> </span><span class="str">"PHP: You said '$buf'.\n"</span><span class="pun">;</span><span class="pln">
        socket_write</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">,</span><span class="pln"> $talkback</span><span class="pun">,</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$talkback</span><span class="pun">));</span><span class="pln">
        </span><span class="com">// طباعة الرسالة على الطرفية</span><span class="pln">
        echo </span><span class="str">"$buf\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
    socket_close</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
socket_close</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	في الموضع (1) لدينا الدالة <code>socket_create</code> لها الشكل العام <code>( int $domain , int $type , int $protocol )</code>:
</p>

<ul>
<li>
		يمكن أن يكون المتغير <code>‎$domain</code> هو <code>AF_INET</code> أو <code>AF_INET6</code> من أجل <code>IPV6</code> أو <code>AF_UNIX</code> من أجل بروتوكول الاتصال المحلي.
	</li>
	<li>
		يمكن أن يكون المتغير <code>‎$protocol</code> إما <code>SOL_TCP</code> أو <code>SOL_UDP</code> ‏(TCP/UDP) تعيد هذه الدالة القيمة <code>true</code> في حالة النجاح.
	</li>
</ul>
<p>
	في الموضع (2) نستخدم الدالة <code>socket_bind</code> التي لها الشكل العام <code>‎socket_bind ( resource $socket , string $address [, int $port = 0 ] )‎</code>، تربط هذه الدالة المقبس ليستمع إلى عنوان ومنفذ محددين.
</p>

<h2>
	استيثاق HTTP
</h2>

<p>
	سنكتب سكربت استيثاق ترويسة HTTP بسيط، ولاحظ أنّه يجب وضع هذه الشيفرة في ترويسة الصفحة وإلا لن يعمل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3066_8" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_SERVER</span><span class="pun">[</span><span class="str">'PHP_AUTH_USER'</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'WWW-Authenticate: Basic realm="My Realm"'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'HTTP/1.0 401 Unauthorized'</span><span class="pun">);</span><span class="pln">
    echo </span><span class="str">'Text to send if user hits Cancel button'</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

echo </span><span class="str">"&lt;p&gt;Hello {$_SERVER['PHP_AUTH_USER']}.&lt;/p&gt;"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// حفظ المعلومات</span><span class="pln">
$user </span><span class="pun">=</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'PHP_AUTH_USER'</span><span class="pun">];</span><span class="pln"> 
echo </span><span class="str">"&lt;p&gt;You entered {$_SERVER['PHP_AUTH_PW']} as your password.&lt;/p&gt;"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫حفظ كلمة المرور (يمكن إضافة التشفير اختياريًا)</span><span class="pln">
$pass </span><span class="pun">=</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'PHP_AUTH_PW'</span><span class="pun">];</span><span class="pln"> </span><span class="com">//Save the password(optionally add encryption)!</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">
// ‫صفحة html</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [ WebSockets - HTTP Authentication - Sockets] من كتاب <a data-ss1619595305="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a data-ss1619595305="1" href="https://academy.hsoub.com/programming/php/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-php-mysqli-%D9%88%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sqlite3-r1131/" rel="">إضافة PHP MySQLi ونظام إدارة قواعد البيانات SQLite3</a>
	</li>
	<li>
		المقال السابق: <a data-ss1619595305="1" href="https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%B7%D9%84%D8%A8%D9%8A%D8%A7%D8%AA-http-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-php-r1129/" rel="">معالجة بيانات طلبيات HTTP والتعامل مع أخطاء رفع الملفات في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1130</guid><pubDate>Mon, 01 Mar 2021 13:03:00 +0000</pubDate></item><item><title>&#x645;&#x639;&#x627;&#x644;&#x62C;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x637;&#x644;&#x628;&#x64A;&#x627;&#x62A; HTTP &#x648;&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x623;&#x62E;&#x637;&#x627;&#x621; &#x631;&#x641;&#x639; &#x627;&#x644;&#x645;&#x644;&#x641;&#x627;&#x62A; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%B7%D9%84%D8%A8%D9%8A%D8%A7%D8%AA-http-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-php-r1129/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/8.png.c9b1d8b35844f607bba7ea49a30a25fc.png" /></p>

<h2>
	قراءة بيانات خام مُرسَلة عبر طلب POST
</h2>

<p>
	تُنظَّم عادةً البيانات المُرسلة عبر طلب <code>POST</code> في أزواج مفتاح/قيمة مع نوع <code>MIME</code> <code>‏application/x-www-formurlencoded</code>، ومع ذلك تتطلب العديد من التطبيقات مثل خدمات الويب (web services) بيانات خام بتنسيق <code>XML</code> أو <code>JSON</code> غالبًا لتُرسَل، يمكن قراءة هذه البيانات بإحدى طريقتين.
</p>

<ul>
<li>
		الأولى هي عبر مجرى يوفر الوصول إلى هيكل الطلب الخام <code>php://input</code>. لدينا الشيفرة التالية في الإصدار PHP &lt; 5.6:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_7" style="">
<span class="pln">$rawdata </span><span class="pun">=</span><span class="pln"> file_get_contents</span><span class="pun">(</span><span class="str">"php://input"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫بفرض أننا نحصل على JSON</span><span class="pln">
$decoded </span><span class="pun">=</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">$rawdata</span><span class="pun">);</span></pre>

<ul>
<li>
		الثانية عبر المتغير <code>‎$HTTP_RAW_POST_DATA</code> الذي هو متغير عام يتضمن بيانات خام مُرسَلة عبر طلب <code>POST</code> وهو مُتاح فقط إذا كان الموجِّه <code>always_populate_raw_post_data</code> في ملف <code>php.ini</code> مفعّلًا.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_9" style="">
<span class="pln">$rawdata </span><span class="pun">=</span><span class="pln"> $HTTP_RAW_POST_DATA</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫إذا كنا نريد الحصول على XML</span><span class="pln">
$decoded </span><span class="pun">=</span><span class="pln"> simplexml_load_string</span><span class="pun">(</span><span class="pln">$rawdata</span><span class="pun">);</span></pre>

<p>
	أُهمل هذا المتغير منذ الإصدار PHP 5.6 وأُزيل في الإصدار PHP 7.0.
</p>

<p>
	لاحظ أنّ هذه التوابع غير متاحة عندما يُضبَط نوع المحتوى إلى القيمة <code>multipart/form-data</code> التي تُستَخدم لرفع الملفات.
</p>

<h2>
	قراءة بيانات مُرسَلة عبر طلب POST
</h2>

<p>
	تُخزَّن البيانات المُرسَلة عبر طلب <code>POST</code> في المتغير ذو النطاق العام العالي <code>‎$_POST</code> على شكل مصفوفة ترابطية.
</p>

<p>
	لاحظ أنّ الوصول إلى عنصر مصفوفة غير موجود يولّد ملاحظة لذا يجب التأكد دومًا من وجود العنصر باستخدام الدوال <code>isset()‎</code> أو <code>empty()‎</code> أو عامل تجميع <code>null</code>، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_11" style="">
<span class="pln">$from </span><span class="pun">=</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">[</span><span class="str">"name"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">"name"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"NO NAME"</span><span class="pun">;</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">[</span><span class="str">"message"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">"message"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"NO MESSAGE"</span><span class="pun">;</span><span class="pln">
echo </span><span class="str">"Message from $from: $message"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫الإصدار PHP ≥ 7.0</span><span class="pln">
$from </span><span class="pun">=</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">"name"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="str">"NO NAME"</span><span class="pun">;</span><span class="pln">
$message </span><span class="pun">=</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">"message"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="str">"NO MESSAGE"</span><span class="pun">;</span><span class="pln">

echo </span><span class="str">"Message from $from: $message"</span><span class="pun">;</span></pre>

<h2>
	قراءة بيانات مُرسَلة عبر طلب GET
</h2>

<p>
	تُخزَّن البيانات المُرسَلة عبر طلب <code>GET</code> في المتغير ذو النطاق العام العالي <code>‎$_GET</code> على شكل مصفوفة ترابطية.
</p>

<p>
	لاحظ أنّ الوصول إلى عنصر مصفوفة غير موجود يولّد ملاحظة لذا يجب التأكد دومًا من وجود العنصر باستخدام الدوال <code>isset()‎</code> أو <code>empty()‎</code> أو عامل تجميع <code>null</code>، مثال:
</p>

<p>
	مثال (بفرض لدينا الرابط <code>‎/topics.php?author=alice&amp;topic=php‎</code>):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_13" style="">
<span class="pln">$author </span><span class="pun">=</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">"author"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">"author"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"NO AUTHOR"</span><span class="pun">;</span><span class="pln">
$topic </span><span class="pun">=</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">"topic"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">"topic"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"NO TOPIC"</span><span class="pun">;</span><span class="pln">
echo </span><span class="str">"Showing posts from $author about $topic"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫الإصدار PHP ≥ 7.0</span><span class="pln">
$author </span><span class="pun">=</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">"author"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="str">"NO AUTHOR"</span><span class="pun">;</span><span class="pln">
$topic </span><span class="pun">=</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">"topic"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="str">"NO TOPIC"</span><span class="pun">;</span><span class="pln">

echo </span><span class="str">"Showing posts from $author about $topic"</span><span class="pun">;</span></pre>

<h2>
	معالجة أخطاء رفع ملف
</h2>

<p>
	قد يتضمن العنصر <code>‎$_FILES["FILE_NAME"]['error']‎</code> (حيث "FILE_NAME" قيمة الخاصيّة <code>name</code> للعنصر <code>input</code> الموجود في النموذج الخاص بك) إحدى القيم التالية:
</p>

<p>
	1- <code>UPLOAD_ERR_OK</code>: لا يوجد خطأ، رُفِع الملف بنجاح.
</p>

<p>
	2- <code>UPLOAD_ERR_INI_SIZE</code>: تجاوز الملف المرفوع قيمة <code>upload_max_filesize</code> في الملف <code>php.ini</code>.
</p>

<p>
	3- <code>UPLOAD_ERR_PARTIAL</code>: تجاوز الملف المرفوع القيمة <code>MAX_FILE_SIZE</code> المحددة في نموذج HTML.
</p>

<p>
	4- <code>UPLOAD_ERR_NO_FILE</code>: لم يُحمَّل أي ملف.
</p>

<p>
	5- <code>UPLOAD_ERR_NO_TMP_DIR</code>: فقدان مجلد مؤقت (من الإصدار PHP 5.0.3).
</p>

<p>
	6- <code>UPLOAD_ERR_CANT_WRITE</code>: فشل كتابة الملف على القرص (من الإصدار PHP 5.1.0).
</p>

<p>
	7- <code>UPLOAD_ERR_EXTENSION</code>: إضافة PHP أوقفت رفع الملف (من الإصدار PHP 5.2.0).
</p>

<p>
	الطريقة الأساسية لفحص الأخطاء:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_15" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="com">// ‫"FILE_NAME" قيمة الخاصيّة `name` للعنصر `input` الموجود في النموذج الخاص بك‫</span><span class="pln">
$fileError </span><span class="pun">=</span><span class="pln"> $_FILES</span><span class="pun">[</span><span class="str">"FILE_NAME"</span><span class="pun">][</span><span class="str">"error"</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">switch</span><span class="pun">(</span><span class="pln">$fileError</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">case</span><span class="pln"> UPLOAD_ERR_INI_SIZE</span><span class="pun">:</span><span class="pln">
    </span><span class="com">// ‫تجاوز الحجم الأعظمي المحدد في php.ini</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">case</span><span class="pln"> UPLOAD_ERR_PARTIAL</span><span class="pun">:</span><span class="pln">
    </span><span class="com">// ‫تجاوز الحجم الأعظمي المحدد في نموذج html</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">case</span><span class="pln"> UPLOAD_ERR_NO_FILE</span><span class="pun">:</span><span class="pln">
    </span><span class="com">// لم يُحمَّل أي ملف</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">case</span><span class="pln"> UPLOAD_ERR_NO_TMP_DIR</span><span class="pun">:</span><span class="pln">
    </span><span class="com">// لا يوجد مجلد مؤقت للكتابة فيه</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">case</span><span class="pln"> UPLOAD_ERR_CANT_WRITE</span><span class="pun">:</span><span class="pln">
    </span><span class="com">// خطأ في الكتابة إلى القرص</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    </span><span class="com">// لا يوجد أخطاء!</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	تمرير مصفوفات عبر طلب POST
</h2>

<p>
	يُرسَل عادةً عنصر نموذج HTML إلى PHP كقيمة مفردة، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_17" style="">
<span class="tag">&lt;pre&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php print_r</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">);?&gt;</span><span class="pln">
</span><span class="tag">&lt;/pre&gt;</span><span class="pln">
</span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"post"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"hidden"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"foo"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"bar"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
Array
(
    [foo] =&gt; bar
)
</pre>

<p>
	لكن قد تحتاج أحيانًا إلى تمرير مصفوفة قيم، يمكنك القيام بذلك بإضافة مايشبه اللاحقة في PHP إلى الخاصيّة <code>name</code> لعناصر HTML:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_19" style="">
<span class="tag">&lt;pre&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php print_r</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">);?&gt;</span><span class="pln">
</span><span class="tag">&lt;/pre&gt;</span><span class="pln">
</span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"post"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"hidden"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"foo[]"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"bar"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"hidden"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"foo[]"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"baz"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
Array
(
    [foo] =&gt; Array
    (
        [0] =&gt; bar
        [1] =&gt; baz
    )
)
</pre>

<p>
	يمكنك أيضًا تحديد فهارس المصفوفة إما أرقام أو سلاسل نصية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_21" style="">
<span class="tag">&lt;pre&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php print_r</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">);?&gt;</span><span class="pln">
</span><span class="tag">&lt;/pre&gt;</span><span class="pln">
</span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"post"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"hidden"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"foo[42]"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"bar"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"hidden"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"foo[foo]"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"baz"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
Array
(
    [foo] =&gt; Array
    (
        [42] =&gt; bar
        [foo] =&gt; baz
    )
)
</pre>

<p>
	يمكن استخدام هذه التقنية لتجنب حلقات ما بعد المعالجة عبر مصفوفة <code>‎$_POST</code> مما يجعل شيفرتك أنظف وأدق.
</p>

<h2>
	رفع ملفات باستخدام HTTP PUT
</h2>

<p>
	توفر PHP الدعم للطريقة <code>HTTP PUT</code> المستخدمة من قِبَل بعض العملاء لتخزين الملفات على الخادم، تعدّ طلبات <code>PUT</code> أبسط من رفع ملف باستخدام طلبات <code>POST</code> وتبدو بالشكل:
</p>

<pre class="ipsCode" id="ips_uid_9701_23">
PUT /path/filename.html HTTP/1.1
</pre>

<p>
	يمكنك كتابة شيفرة PHP التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9701_25" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="com">// ‫تأتي بيانات PUT من مجرى الدخل القياسي</span><span class="pln">
$putdata </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"php://input"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"r"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// فتح ملف للكتابة</span><span class="pln">
$fp </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"putfile.ext"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"w"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قراءة 1 كيلوبايت في كل مرة وكتابتها في الملف</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$data </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">(</span><span class="pln">$putdata</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1024</span><span class="pun">))</span><span class="pln">
fwrite</span><span class="pun">(</span><span class="pln">$fp</span><span class="pun">,</span><span class="pln"> $data</span><span class="pun">);</span><span class="pln">

</span><span class="com">/* إغلاق المجاري */</span><span class="pln">
fclose</span><span class="pun">(</span><span class="pln">$fp</span><span class="pun">);</span><span class="pln">
fclose</span><span class="pun">(</span><span class="pln">$putdata</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	ترجمة -وبتصرف- للفصل [Reading Request Data] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%A8%D8%B3-sockets-%D9%81%D9%8A-php-r1130/" rel="">المقابس (sockets) في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-url-%D9%81%D9%8A-php-r1128/" rel="">التعامل مع الروابط URL في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1129</guid><pubDate>Sat, 27 Feb 2021 13:05:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x627;&#x644;&#x631;&#x648;&#x627;&#x628;&#x637; URL &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-url-%D9%81%D9%8A-php-r1128/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/7.png.faa780a8558eaa799a22ce3def409dca.png" /></p>

<h2>
	تحليل رابط
</h2>

<p>
	نستخدم الدالة <a href="%E2%80%8Fhttps://www.php.net/parse_url" rel=""><code>parse_url()‎</code></a> لتقسيم رابط (url) إلى مكوناته الفردية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_7" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'http://www.example.com/page?foo=1&amp;bar=baz#anchor'</span><span class="pun">;</span><span class="pln">
$parts </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span></pre>

<p>
	تصبح محتويات المتغير <code>‎$parts</code> بعد تنفيذ الشيفرة السابقة:
</p>

<pre class="ipsCode">
Array
(
    [scheme] =&gt; http
    [host] =&gt; www.example.com
    [path] =&gt; /page
    [query] =&gt; foo=1&amp;bar=baz
    [fragment] =&gt; anchor
)
</pre>

<p>
	يمكنك أن ترجع أيضًا مكون واحد من الرابط بشكلٍ انتقائي، فمثلًا لترجع سلسلة الاستعلام (query string) فقط:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_10" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'http://www.example.com/page?foo=1&amp;bar=baz#anchor'</span><span class="pun">;</span><span class="pln">
$queryString </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">,</span><span class="pln"> PHP_URL_QUERY</span><span class="pun">);</span></pre>

<p>
	يعدّ أيّ من الثوابت التالية مقبولًا:
</p>

<ul>
<li>
		PHP_URL_SCHEME
	</li>
	<li>
		‏PHP_URL_HOST
	</li>
	<li>
		PHP_URL_PORT
	</li>
	<li>
		‏PHP_URL_USER
	</li>
	<li>
		‏PHP_URL_PASS
	</li>
	<li>
		‏PHP_URL_PATH
	</li>
	<li>
		‏PHP_URL_QUERY
	</li>
	<li>
		PHP_URL_FRAGMENT
	</li>
</ul>
<p>
	يمكنك استخدام الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/parse_str" rel=""><code>parse_str()‎</code></a> لتحليل سلسلة الاستعلام إلى أزواج مفتاح/قيمة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_12" style="">
<span class="pln">$params </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
parse_str</span><span class="pun">(</span><span class="pln">$queryString</span><span class="pun">,</span><span class="pln"> $params</span><span class="pun">);</span></pre>

<p>
	تصبح محتويات المتغير <code>‎$params</code> بعد تنفيذ الشيفرة السابقة:
</p>

<pre class="ipsCode">
Array
(
    [foo] =&gt; 1
    [bar] =&gt; baz
)
</pre>

<h2>
	بناء سلسلة استعلام للرابط من مصفوفة
</h2>

<p>
	تنشأ الدالة <a href="%E2%80%8Fhttps://www.php.net/manual/en/function.http-build-query.php" rel=""><code>http_build_query()‎</code></a> سلسلة استعلام من مصفوفة أو كائن، يمكن أن تُضاف هذه السلسلة إلى رابط ما لإنشاء طلب من النوع <code>GET</code> أو تُستخدم في طلب <code>POST</code> مع مكتبة <code>cURL</code> مثلًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_15" style="">
<span class="pln">$parameters </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
    </span><span class="str">'parameter1'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'parameter2'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'bar'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

$queryString </span><span class="pun">=</span><span class="pln"> http_build_query</span><span class="pun">(</span><span class="pln">$parameters</span><span class="pun">);</span></pre>

<p>
	تصبح محتويات المتغير <code>‎$queryString</code> بعد تنفيذ الشيفرة السابقة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_17" style="">
<span class="pln">parameter1</span><span class="pun">=</span><span class="pln">foo</span><span class="pun">&amp;</span><span class="pln">parameter2</span><span class="pun">=</span><span class="pln">bar</span></pre>

<p>
	تعمل الدالة <code>http_build_query()‎</code> مع المصفوفات متعددة الأبعاد أيضًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_19" style="">
<span class="pln">$parameters </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"parameter3"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
        </span><span class="str">"sub1"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"foo"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"sub2"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"bar"</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">),</span><span class="pln">
    </span><span class="str">"parameter4"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"baz"</span><span class="pun">,</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

$queryString </span><span class="pun">=</span><span class="pln"> http_build_query</span><span class="pun">(</span><span class="pln">$parameters</span><span class="pun">);</span></pre>

<p>
	تصبح محتويات المتغير <code>‎$queryString</code> بعد تنفيذ الشيفرة السابقة:
</p>

<pre class="ipsCode">
parameter3%5Bsub1%5D=foo&amp;parameter3%5Bsub2%5D=bar&amp;parameter4=baz
</pre>

<p>
	والذي هو النسخة المرمزة للرابط:
</p>

<pre class="ipsCode">
parameter3[sub1]=foo&amp;parameter3[sub2]=bar&amp;parameter4=baz
</pre>

<h2>
	إعادة التوجيه إلى رابط آخر
</h2>

<p>
	يمكنك استخدام الدالة <code>header()‎</code> لتوجيه المتصفح ليعيد التوجيه إلى رابط مختلف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_21" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'https://example.org/foo/bar'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// فحص الترويسات - لايمكنك إرسال ترويسات إذا أُرسلت بالفعل</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">headers_sent</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $url</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// الحماية من تنفيذ الشيفرة بعد إعادة توجيه الطلب</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">'Cannot redirect, headers already sent'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك أيضًا إعادة التوجيه إلى رابط نسبي (هذا ليس جزء من توصيف HTTP الرسمي، لكنه يعمل مع جميع المتصفحات):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_23" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'foo/bar'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">headers_sent</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $url</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">'Cannot redirect, headers already sent'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا كانت الترويسات قد أُرسلت، يمكنك إرسال وسم HTML <code>‏meta refresh</code>.
</p>

<p>
	يعتمد وسم <code>‏meta refresh</code> على معالجة HTML بشكلٍ صحيح عند العميل لكن قد لايتم ذلك وفقًا للمطلوب، بشكلٍ عام يعمل بشكل صحيح فقط مع متصفحات الويب، ويجب أن تنتبه أيضًا أنه إذا كانت الترويسات قد أُرسلت بالفعل فقد تحصل على خطأ وهذا يشغّل استثناءً.
</p>

<p>
	يمكنك أيضًا أن تطبع رابطًا يضغط عليه المستخدم للعملاء الذين يتجاهلون وسم <code>‏meta refresh</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_25" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'https://example.org/foo/bar'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">headers_sent</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $url</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫الحماية من رؤية المتصفح للرابط على أنّه HTML</span><span class="pln">
    $saveUrl </span><span class="pun">=</span><span class="pln"> htmlspecialchars</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span><span class="pln"> 

    </span><span class="com">// ‫إخبار المتصفح أن يعيد توجيه الصفحة إلى ‎$saveUrl بعد 0 ثانية</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="str">'&lt;meta http-equiv="refresh" content="0; url='</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $saveUrl </span><span class="pun">.</span><span class="pln"> </span><span class="str">'"&gt;'</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// إظهار الرابط للمستخدم</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="str">'&lt;p&gt;Please continue to &lt;a href="'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $saveUrl </span><span class="pun">.</span><span class="pln"> </span><span class="str">'"&gt;'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $saveUrl </span><span class="pun">.</span><span class="pln"> </span><span class="str">'&lt;/a&gt;&lt;/p&gt;'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">exit</span><span class="pun">;</span></pre>

<h2>
	كيفية تحليل رابط
</h2>

<p>
	عند كتابتك شيفرة بلغة PHP قد تحتاج إلى تقسيم رابط إلى عدة أجزاء، ويوجد عدة طرق لذلك وفقًا لاحتياجاتك، سنشرح هذه الطرق في الفقرة التالية لتختار منها ما يناسبك.
</p>

<h3>
	استخدام parse_url()‎
</h3>

<p>
	تحلل الدالة <code>parse_url()‎</code> رابطًا وتعيد مصفوفة ترابطية (associative array) تتضمن مكونات الرابط المختلفة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_27" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="str">'http://example.com/project/controller/action/param1/param2'</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
Array
(
    [scheme] =&gt; http
    [host] =&gt; example.com
    [path] =&gt; /project/controller/action/param1/param2
)
*/</span></pre>

<p>
	يمكنك استخدام الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/explode" rel="">explode</a> إذا كنت تحتاج أن يكون <code>path</code> مقسّمًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_29" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="str">'http://example.com/project/controller/action/param1/param2'</span><span class="pun">);</span><span class="pln">
$url</span><span class="pun">[</span><span class="str">'sections'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> explode</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> $url</span><span class="pun">[</span><span class="str">'path'</span><span class="pun">]);</span><span class="pln">

</span><span class="com">/*
Array
(
    [scheme] =&gt; http
    [host] =&gt; example.com
    [path] =&gt; /project/controller/action/param1/param2
    [sections] =&gt; Array
    (
        [0] =&gt;
        [1] =&gt; project
        [2] =&gt; controller
        [3] =&gt; action
        [4] =&gt; param1
        [5] =&gt; param2
    )
)
*/</span></pre>

<p>
	يمكنك استخدام الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/end" rel="">end()‎</a> إذا كنت تحتاج الجزء الأخير من <code>sections</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_31" style="">
<span class="pln">$last </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">end</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">[</span><span class="str">'sections'</span><span class="pun">]);</span></pre>

<p>
	إذا كان الرابط يحتوي على متغيرات <code>GET</code> يمكنك استعادتها أيضًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_33" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="str">'http://example.com?var1=value1&amp;var2=value2'</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
Array
(
    [scheme] =&gt; http
    [host] =&gt; example.com
    [query] =&gt; var1=value1&amp;var2=value2
)
*/</span></pre>

<p>
	إذا أردت تقسيم متغيرات الاستعلام يمكنك استخدام <code>parse_str()‎</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_35" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="str">'http://example.com?var1=value1&amp;var2=value2'</span><span class="pun">);</span><span class="pln">
parse_str</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">[</span><span class="str">'query'</span><span class="pun">],</span><span class="pln"> $parts</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
Array
(
    [var1] =&gt; value1
    [var2] =&gt; value2
)
*/</span></pre>

<h3>
	استخدام explode()‎
</h3>

<p>
	تعيد الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/explode" rel=""><code>explode</code></a> مصفوفة من السلاسل النصية، كل منها سلسلة جزئية من سلسلة نصية مُشكَّلة من تقسيمها على الحدود التي يشكّلها حد السلسلة النصية.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_37" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://example.com/project/controller/action/param1/param2"</span><span class="pun">;</span><span class="pln">
$parts </span><span class="pun">=</span><span class="pln"> explode</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> $url</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
Array
(
    [0] =&gt; http:
    [1] =&gt;
    [2] =&gt; example.com
    [3] =&gt; project
    [4] =&gt; controller
    [5] =&gt; action
    [6] =&gt; param1
    [7] =&gt; param2
)
*/</span></pre>

<p>
	يمكنك استعادة الجزء الأخير من الرابط كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_39" style="">
<span class="pln">$last </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">end</span><span class="pun">(</span><span class="pln">$parts</span><span class="pun">);</span><span class="pln">
</span><span class="com">// param2</span></pre>

<p>
	يمكنك أيضًا التنقل في المصفوفة باستخدام <code>sizeof()‎</code> مع عامل رياضي كما في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_41" style="">
<span class="pln">echo $parts</span><span class="pun">[</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">$parts</span><span class="pun">)-</span><span class="lit">2</span><span class="pun">];</span><span class="pln">
</span><span class="com">// param1</span></pre>

<h3>
	استخدام basename()‎
</h3>

<p>
	تُعطى الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/basename" rel=""><code>basename()‎</code></a> سلسلة نصية تتضمن مسارًا إلى ملف أو مجلد وترجع مكوّن الاسم الزائد أي ترجع الجزء الأخير من الرابط فقط.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_43" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://example.com/project/controller/action/param1/param2"</span><span class="pun">;</span><span class="pln">
$parts </span><span class="pun">=</span><span class="pln"> basename</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span><span class="pln">
</span><span class="com">// param2</span></pre>

<p>
	إذا كان الرابط يحتوي على المزيد من الأشياء وكل ما تحتاجه هو اسم المجلد الذي يتضمن الملف الذي تستخدمه عندها يمكنك استخدام <code>dirname()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5631_45" style="">
<span class="pln">$url </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://example.com/project/controller/action/param1/param2/index.php"</span><span class="pun">;</span><span class="pln">
$parts </span><span class="pun">=</span><span class="pln"> basename</span><span class="pun">(</span><span class="pln">dirname</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">));</span><span class="pln">
</span><span class="com">// param2</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [URLs - How to break down an URL] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%B7%D9%84%D8%A8%D9%8A%D8%A7%D8%AA-http-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-php-r1129/" rel="">معالجة بيانات طلبيات HTTP والتعامل مع أخطاء رفع الملفات في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D9%85%D9%88%D9%84%D8%AF%D8%A7%D8%AA-%D9%88%D8%AA%D9%88%D8%B6%D9%8A%D8%AD-%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D9%85%D8%BA%D9%84%D9%81-closure-%D9%81%D9%8A-php-r1127/" rel="">شرح المولدات وتوضيح مفهوم المغلف (closure) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1128</guid><pubDate>Wed, 24 Feb 2021 13:08:00 +0000</pubDate></item><item><title>&#x634;&#x631;&#x62D; &#x627;&#x644;&#x645;&#x648;&#x644;&#x62F;&#x627;&#x62A; &#x648;&#x62A;&#x648;&#x636;&#x64A;&#x62D; &#x645;&#x641;&#x647;&#x648;&#x645; &#x627;&#x644;&#x645;&#x63A;&#x644;&#x641; (closure) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D9%85%D9%88%D9%84%D8%AF%D8%A7%D8%AA-%D9%88%D8%AA%D9%88%D8%B6%D9%8A%D8%AD-%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D9%85%D8%BA%D9%84%D9%81-closure-%D9%81%D9%8A-php-r1127/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/6.png.bf36f0a99e33ab367de4d78e359a86e2.png" /></p>

<h2>
	الكلمة المفتاحية Yield
</h2>

<p>
	تشبه التعليمة <code>yield</code> تعليمة <code>return</code> باستثناء أنّه بدلًا من إيقاف تنفيذ الدالة وإرجاع شيء ما، فإنّها تُرجع كائن <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/generators" rel=""><code>Generator</code></a> وتوقف تنفيذ دالة المولِّد، إليك مثال عن دالة مجال مكتوبة كمولِّد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_7" style="">
<span class="kwd">function</span><span class="pln"> gen_one_to_three</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫لاحظ أنّ المتغير ‎$i مسبوق بالكلمة المفتاحية yield.</span><span class="pln">
        </span><span class="kwd">yield</span><span class="pln"> $i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك ملاحظة أنّ هذه الدالة ترجع كائنًا من النوع مولِّد <code>Generator</code> من خلال فحص الخرج باستخدام الدالة <code>var_dump</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_9" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">gen_one_to_three</span><span class="pun">())</span><span class="pln">

</span><span class="com">/*
class Generator (0) {
}
*/</span></pre>

<h3>
	القيم المعادة (Yielding)
</h3>

<p>
	يمكن تكرار الكائن <code>Generator</code> مثل المصفوفة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_11" style="">
<span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">gen_one_to_three</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"$value\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	خرج المثال السابق:
</p>

<pre class="ipsCode">
1
2
3
</pre>

<h3>
	القيم المعادة مع مفاتيح
</h3>

<p>
	بالإضافة إلى إعادة قيم يمكنك إعادة أزواج قيمة/مفتاح:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_13" style="">
<span class="kwd">function</span><span class="pln"> gen_one_to_three</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $keys </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"first"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"second"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"third"</span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫لاحظ أنّ المتغير ‎$i‎ هو قيمة معادة</span><span class="pln">
        </span><span class="kwd">yield</span><span class="pln"> $keys</span><span class="pun">[</span><span class="pln">$i </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">gen_one_to_three</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $key </span><span class="pun">=&gt;</span><span class="pln"> $value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"$key: $value\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	خرج المثال السابق:
</p>

<pre class="ipsCode">
first: 1
second: 2
third: 3
</pre>

<h2>
	قراءة ملف كبير باستخدام مولد
</h2>

<p>
	إحدى حالات الاستخدام الشائعة للمولِّدات هي قراءة ملف من القرص والمرور على كامل محتوياته، إليك في الشيفرة التالية صنفًا يسمح لك بالتكرار عبر ملف <code>CSV</code>، يمكن التنبؤ باستخدام الذاكرة لهذا السكربت ولن يتفاوت هذا الاستخدام بتغير حجم ملف <code>CSV</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_15" style="">
<span class="pun">&lt;?</span><span class="pln">php
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CsvReader</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">protected</span><span class="pln"> $file</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$filePath</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">file </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="pln">$filePath</span><span class="pun">,</span><span class="pln"> </span><span class="str">'r'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> rows</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">feof</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $row </span><span class="pun">=</span><span class="pln"> fgetcsv</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4096</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">yield</span><span class="pln"> $row</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$csv </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CsvReader</span><span class="pun">(</span><span class="str">'/path/to/huge/csv/file.csv'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$csv</span><span class="pun">-&gt;</span><span class="pln">rows</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $row</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫القيام بشيء ما مع صف CSV</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	لماذا نستخدم المولِّد؟
</h2>

<p>
	تعدّ المولِّدات مفيدةً عندما نحتاج إلى توليد مجموعة كبيرة للمرور عليها لاحقًا، وهي أبسط بديل لإنشاء صنف ينفّذ مكرِّرًا والذي غالبًا ما يكون مبالغ به.
</p>

<p>
	بفرض لدينا الدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_17" style="">
<span class="kwd">function</span><span class="pln"> randomNumbers</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> $length</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $array </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun">&lt;</span><span class="pln"> $length</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $array</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> mt_rand</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> $array</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تولِّد الدالة السابقة مصفوفة تُملأ بأرقام عشوائية، قد نستخدمها بالشكل <code>randomNumbers(10)‎</code> مثلًا مما يعطينا مصفوفة من 10 أرقام عشوائية، لكن ماذا لو أردنا توليد مليون رقمًا عشوائيًا؟ يمكننا القيام بذلك بكتابة <code>randomNumbers(1000000)‎</code> لكن هذا يكلّف ذاكرة، إذ أنّ مليون عدد صحيح مخزّن في مصفوفة يحتاج إلى حوالي 33 ميجابايت من الذاكرة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_19" style="">
<span class="pln">$startMemory </span><span class="pun">=</span><span class="pln"> memory_get_usage</span><span class="pun">();</span><span class="pln">
$randomNumbers </span><span class="pun">=</span><span class="pln"> randomNumbers</span><span class="pun">(</span><span class="lit">1000000</span><span class="pun">);</span><span class="pln">
echo memory_get_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> $startMemory</span><span class="pun">,</span><span class="pln"> </span><span class="str">' bytes'</span><span class="pun">;</span></pre>

<p>
	هذا بسبب توليد مليون رقم عشوائي وإرجاعه مرةً واحدةً، بدلًا من توليد وإرجاع رقم في كل مرة، تعدّ المولِّدات طريقةً سهلةً لحل هذه المشكلة.
</p>

<h2>
	استخدام دالة send()‎ لتمرير القيم إلى مولد
</h2>

<p>
	تُشفَّر المولِّدات بسرعة وتكون في الكثير من الحالات بديلًا خفيفًا عن تنفيذات المكرِّر الثقيلة، ومع التنفيذ السريع يصبح لدينا نقصًا قليلًا في التحكم عندما يجب أن يتوقف المولِّد عن التوليد أو إذا كان يجب أن يولِّد شيئًا آخر. لكن يمكن تحقيق ذلك باستخدام دالة <code>send()‎</code> مما يتيح لدالة الطلب إرسال المعاملات إلى المولِّد بعد كل حلقة.
</p>

<p>
	بفرض أنّه نريد الوصول إلى كمية بيانات كبيرة باستخدام المولِّد في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_21" style="">
<span class="kwd">function</span><span class="pln"> generateDataFromServerDemo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// في هذا المثال نُرسل التغذية الراجعة في كل تكرار للحلقة بدلًا من إرسال بيانات من الخادم</span><span class="pln">
    $indexCurrentRun </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

    $timeout </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">$timeout</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $timeout </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">yield</span><span class="pln"> $indexCurrentRun</span><span class="pun">;</span><span class="pln"> </span><span class="com">//(1)</span><span class="pln">
        $indexCurrentRun</span><span class="pun">++;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">yield</span><span class="pln"> </span><span class="str">'X of bytes are missing. &lt;/br&gt;'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// بدء استخدام المولِّد</span><span class="pln">
$generatorDataFromServer </span><span class="pun">=</span><span class="pln"> generateDataFromServerDemo </span><span class="pun">();</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pun">(</span><span class="pln">$generatorDataFromServer </span><span class="kwd">as</span><span class="pln"> $numberOfRuns</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$numberOfRuns </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        echo $numberOfRuns </span><span class="pun">.</span><span class="pln"> </span><span class="str">"&lt;/br&gt;"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// إرسال البيانات إلى المولِّد</span><span class="pln">
        $generatorDataFromServer</span><span class="pun">-&gt;</span><span class="pln">send</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// الوصول إلى العنصر الأخير (التلميح إلى عدد البايتات المفقودة)</span><span class="pln">
        echo $generatorDataFromServer</span><span class="pun">-&gt;</span><span class="pln">current</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) تُمرَّر القيم إلى المستدعي، وفي المرة التالية يُستدعى المولِّد الذي يبدأ عند هذه التعليمة، إذا استخدمنا الدالة <code>send()‎</code> فإنّ المتغير <code>‎$timeout</code> سيأخذ هذه القيمة.
</p>

<p>
	خرج الشيفرة السابقة:
</p>

<pre class="ipsCode">
0
1
2
3
4
5
6
7
8
9
X bytes are missing
</pre>

<h2>
	المغلف (closure)
</h2>

<h3>
	الاستخدام الأساسي للمغلِّف
</h3>

<p>
	يكافئ المغلِّف الدالة المجهولة (anonymous function) أي الدالة التي ليس لها اسم، حتى لو كان ذلك غير صحيح تقنيًا فإنّ سلوك المغلِّف نفس سلوك الدالة مع ميزات إضافية قليلة. مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_23" style="">
<span class="pun">&lt;?</span><span class="pln">php
$myClosure </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'Hello world!'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

$myClosure</span><span class="pun">();</span><span class="pln">
</span><span class="com">// "Hello world!"</span></pre>

<p>
	تذكر أنّ <code>‎$myClosure</code> هو نسخة من مغلِّف (closure) لذا يجب أن تنتبه لما يمكنك القيام به (اطلع على <a href="https://www.php.net/manual/en/class.closure.php" rel="external nofollow">الرابط</a>).
</p>

<p>
	الحالة التقليدية التي تحتاج فيها استخدام المغلِّف هي عندما تريد إعطاء شيء قابل للاستدعاء إلى دالة ما، مثل الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/usort" rel="">usort</a>، في المثال التالي تُرتَّب المصفوفة حسب عدد الأبناء لكل أب:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_25" style="">
<span class="pun">&lt;?</span><span class="pln">php
$data </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'John'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'nbrOfSiblings'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">],</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Stan'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'nbrOfSiblings'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">],</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Tom'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'nbrOfSiblings'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
</span><span class="pun">];</span><span class="pln">
usort</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$e1</span><span class="pun">,</span><span class="pln"> $e2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$e1</span><span class="pun">[</span><span class="str">'nbrOfSiblings'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> $e2</span><span class="pun">[</span><span class="str">'nbrOfSiblings'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $e1</span><span class="pun">[</span><span class="str">'nbrOfSiblings'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> $e2</span><span class="pun">[</span><span class="str">'nbrOfSiblings'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// ‫سيظهر في الخرج Stan ثم John ثم Tom</span></pre>

<h3>
	استخدام متغيرات خارجية
</h3>

<p>
	من الممكن استخدام متغير خارجي داخل المُغلِّف باستخدام الكلمة المفتاحية الخاصة <code>use</code>، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_27" style="">
<span class="pun">&lt;?</span><span class="pln">php
$quantity </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

$calculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$number</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">use</span><span class="pun">(</span><span class="pln">$quantity</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $number </span><span class="pun">+</span><span class="pln"> $quantity</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">$calculator</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// "3"</span></pre>

<p>
	ويمكنك أيضًا إنشاء دوال مغلِّفة ديناميكية، فمثلًا يمكنك إنشاء دالة تُرجع عملية حسابية معينة بالاعتماد على كمية تريد إضافتها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_29" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">function</span><span class="pln"> createCalculator</span><span class="pun">(</span><span class="pln">$quantity</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$number</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">use</span><span class="pun">(</span><span class="pln">$quantity</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $number </span><span class="pun">+</span><span class="pln"> $quantity</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$calculator1 </span><span class="pun">=</span><span class="pln"> createCalculator</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
$calculator2 </span><span class="pun">=</span><span class="pln"> createCalculator</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">$calculator1</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// "3"</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$calculator2</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// "4"</span></pre>

<h3>
	الربط الأساسي لمغلِّف
</h3>

<p>
	كما لاحظت سابقًا فإنّ المغلِّف هو نسخة من الصنف <code>Closure</code> ويمكن استدعاء توابع مختلفة عليه، مثل التابع <code>bindTo</code> الذي يُعطى مغلِّف ويرجع مغلِّفًا جديدًا مرتبطًا بكائن مُعطى، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_31" style="">
<span class="pun">&lt;?</span><span class="pln">php
$myClosure </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$propertyValue</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $propertyValue</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$myInstance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">);</span><span class="pln">
$myBoundClosure </span><span class="pun">=</span><span class="pln"> $myClosure</span><span class="pun">-&gt;</span><span class="pln">bindTo</span><span class="pun">(</span><span class="pln">$myInstance</span><span class="pun">);</span><span class="pln">
$myBoundClosure</span><span class="pun">();</span><span class="pln"> 

</span><span class="com">// "Hello world!"</span></pre>

<h3>
	ربط المغلف والنطاق
</h3>

<p>
	بفرض لدينا المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_33" style="">
<span class="pun">&lt;?</span><span class="pln">php
$myClosure </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$propertyValue</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $propertyValue</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$myInstance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">);</span><span class="pln">
$myBoundClosure </span><span class="pun">=</span><span class="pln"> $myClosure</span><span class="pun">-&gt;</span><span class="pln">bindTo</span><span class="pun">(</span><span class="pln">$myInstance</span><span class="pun">);</span><span class="pln">
$myBoundClosure</span><span class="pun">();</span><span class="pln"> 
</span><span class="com">// "Hello world!"</span></pre>

<p>
	إذا حاولت تغيير مرئية الخاصيّة إلى محميّة (protected) أو خاصة (private)، ستحصل على خطأ فادح يشير إلى أنّه لا يمكنك الوصول إلى هذه الخاصيّة، وحتى لو كان المغلِّف مرتبطًا بالكائن فإنّ النطاق الذي يُنفَّذ فيه المغلِّف ليس بحاجة ليكون لديه إمكانية الوصول ولهذا السبب نستخدم المعامل الثاني للتابع <code>bindTo</code>.
</p>

<p>
	الطريقة الوحيدة لتكون الخاصيّة الخاصة (private) قابلة للوصول هي الوصول إليها من النطاق الذي يسمح بذلك، أي نطاق الصنف. في مثال الشيفرة السابق لم يُحدَّد النطاق مما يعني أنّ المغلِّف يُنفَّذ في نفس النطاق الذي أُنشئَ فيه، لنغيّر هذا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_35" style="">
<span class="pun">&lt;?</span><span class="pln">php
$myClosure </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln"> 
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$propertyValue</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $propertyValue</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$myInstance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">);</span><span class="pln">
$myBoundClosure </span><span class="pun">=</span><span class="pln"> $myClosure</span><span class="pun">-&gt;</span><span class="pln">bindTo</span><span class="pun">(</span><span class="pln">$myInstance</span><span class="pun">,</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
$myBoundClosure</span><span class="pun">();</span><span class="pln"> 
</span><span class="com">// "Hello world!"</span></pre>

<p>
	إذا لم يُستخدم المعامل الثاني فإنّ المُغلِّف يُنفَّذ في نفس السياق الذي أُنشئ فيه، فمثلًا إذا أُنشئ المغلِّف داخل تابع صنف والذي يُنفَّذ في سياق كائن سيكون له نفس نطاق هذا التابع:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_37" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$propertyValue</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $propertyValue</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getDisplayer</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            echo $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$myInstance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">);</span><span class="pln">
$displayer </span><span class="pun">=</span><span class="pln"> $myInstance</span><span class="pun">-&gt;</span><span class="pln">getDisplayer</span><span class="pun">();</span><span class="pln">
$displayer</span><span class="pun">();</span><span class="pln"> 
</span><span class="com">// "Hello world!"</span></pre>

<h3>
	ربط مغلِّف لاستدعاء واحد
</h3>

<p>
	بدءًا من الإصدار PHP7 أصبح من الممكن ربط مغلِّف باستدعاء واحد فقط بفضل التابع <a href="%E2%80%8Fhttps://www.php.net/manual/fr/closure.call.php" rel=""><code>call</code></a>، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_39" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$propertyValue</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $propertyValue</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$myClosure </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

$myInstance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">);</span><span class="pln">
$myClosure</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="pln">$myInstance</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// "Hello world!"</span></pre>

<p>
	لا داعي للقلق بشأن النطاق على عكس التابع <code>bindTo</code>، إذ أنّ النطاق المستخدم لهذا الاستدعاء هو نفس المستخدم عند الوصول إلى أو تنفيذ خاصية <code>‎$myInstance</code>.
</p>

<h3>
	استخدام المغلِّفات لتنفيذ نمط المراقِب
</h3>

<p>
	بشكل عام المراقب (observer) هو صنف بتابع محدد يُستدعى عندما يحدث إجراء على الكائن المُراقَب، في بعض الحالات قد تكون المغلِّفات كافية لتنفيذ نمط تصميم المراقب.
</p>

<p>
	إليك مثال تفصيلي لمثل هذا التنفيذ، لنصرّح أولًا عن صنف الهدف منه هو إخبار المراقبين عند تغيّر خاصيّاتهم.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_41" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ObservedStuff</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">SplSubject</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $observers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> attach</span><span class="pun">(</span><span class="typ">SplObserver</span><span class="pln"> $observer</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">observers</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $observer</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> detach</span><span class="pun">(</span><span class="typ">SplObserver</span><span class="pln"> $observer</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">false</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> $key </span><span class="pun">=</span><span class="pln"> array_search</span><span class="pun">(</span><span class="pln">$observer</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">observers</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            unset</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">observers</span><span class="pun">[</span><span class="pln">$key</span><span class="pun">]);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> notify</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">observers </span><span class="kwd">as</span><span class="pln"> $observer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $observer</span><span class="pun">-&gt;</span><span class="pln">update</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getProperty</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setProperty</span><span class="pun">(</span><span class="pln">$property</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="kwd">property</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $property</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">notify</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم نصرّح عن الصنف الذي سيمثّل المراقبين المختلفين:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_43" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">NamedObserver</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">SplObserver</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $closure</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">Closure</span><span class="pln"> $closure</span><span class="pun">,</span><span class="pln"> $name</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">closure </span><span class="pun">=</span><span class="pln"> $closure</span><span class="pun">-&gt;</span><span class="pln">bindTo</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> update</span><span class="pun">(</span><span class="typ">SplSubject</span><span class="pln"> $subject</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $closure </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">closure</span><span class="pun">;</span><span class="pln">
        $closure</span><span class="pun">(</span><span class="pln">$subject</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لنبدأ بالاختبار الآن:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2383_45" style="">
<span class="pun">&lt;?</span><span class="pln">php
$o </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ObservedStuff</span><span class="pun">;</span><span class="pln">
$observer1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="typ">SplSubject</span><span class="pln"> $subject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $this</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="str">' has been notified! New property value: '</span><span class="pun">,</span><span class="pln">         $subject</span><span class="pun">-&gt;</span><span class="pln">getProperty</span><span class="pun">(),</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

$observer2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="typ">SplSubject</span><span class="pln"> $subject</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $this</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="str">' has been notified! New property value: '</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">-&gt;</span><span class="pln">getProperty</span><span class="pun">(),</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

$o</span><span class="pun">-&gt;</span><span class="pln">attach</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">NamedObserver</span><span class="pun">(</span><span class="pln">$observer1</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Observer1'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln">attach</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">NamedObserver</span><span class="pun">(</span><span class="pln">$observer2</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Observer2'</span><span class="pun">));</span><span class="pln">
$o</span><span class="pun">-&gt;</span><span class="pln">setProperty</span><span class="pun">(</span><span class="str">'Hello world!'</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
Observer1 has been notified! New property value: Hello world!
Observer2 has been notified! New property value: Hello world!
*/</span></pre>

<p>
	لاحظ أنّ هذا المثال يعمل لأنّ المراقبين يتشاركون نفس الطبيعة (كلاهما "named observers").
</p>

<p>
	ترجمة -وبتصرف- للفصول [Generators - Closure] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-url-%D9%81%D9%8A-php-r1128/" rel="">التعامل مع الروابط URL في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%B1%D8%B4%D8%AD%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%B1%D8%B4%D8%AD-filter-%D8%A7%D9%84%D9%85%D8%B9%D9%82%D9%85%D8%A9-%D9%81%D9%8A-php-r1126/" rel="">المرشحات ودوال المرشح (Filter) المعقمة في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1127</guid><pubDate>Mon, 22 Feb 2021 13:07:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x631;&#x634;&#x62D;&#x627;&#x62A; &#x648;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x645;&#x631;&#x634;&#x62D; (Filter) &#x627;&#x644;&#x645;&#x639;&#x642;&#x645;&#x629; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%B1%D8%B4%D8%AD%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%B1%D8%B4%D8%AD-filter-%D8%A7%D9%84%D9%85%D8%B9%D9%82%D9%85%D8%A9-%D9%81%D9%8A-php-r1126/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/5.png.c8d94b630ed6a6265bb18b8ddbf1750b.png" /></p>

<p>
	ترشِّح هذه الإضافة البيانات إما عن طريق تدقيقها أو تعقيمها (sanitizing)، ويعدّ هذا مفيدًا خاصةً عندما يتضمن مصدر البيانات بيانات غير معروفة (أو غريبة) مثل الدخل الذي يوفره مستخدم ما، قد تأتي هذه البيانات من نموذج HTML مثلًا.
</p>

<table><tbody>
<tr>
<td>
				<strong>المعامل</strong>
			</td>
			<td>
				<strong>تفاصيل</strong>
			</td>
		</tr>
<tr>
<td>
				variable
			</td>
			<td>
				القيمة التي نريد ترشيحها، لاحظ أنّ القيم العددية تُحوَّل إلى سلاسل نصية داخليًا قبل أي ترشيح
			</td>
		</tr>
<tr>
<td>
				filter
			</td>
			<td>
				‫ معرِّف المرشّح الذي نريد تطبيقه، تذكر صفحة أنواع المرشِّحات في توثيق <a href="https://wiki.hsoub.com/PHP" rel="external">PHP </a>جميع المرشِّحات المتاحة، إذا تجاوزت هذا المعامل ستُستخدم افتراضيًا القيمة `FILTER_DEFAULT` والتي تكافئ القيمة `FILTER_UNSAFE_RAW`، مما يؤدي إلى عدم إجراء ترشيح بشكلٍ افتراضي
			</td>
		</tr>
<tr>
<td>
				options
			</td>
			<td>
				‫مصفوفة ترابطية من الخيارات أو عملية ثنائية OR على الرايات، إذا قَبِل المرشّح هذه الخيارات يمكن توفير الرايات في الحقل "flags" من المصفوفة. يجب تمرير نوع قابل للاستدعاء من أجل مرشِّح رد النداء، ويجب أن يقبل رد النداء وسيط واحد (القيمة التي نريد ترشيحها) ويعيد القيمة بعد ترشيحها/تعقيمها
			</td>
		</tr>
</tbody></table>
<style type="text/css">
table {
    width: 100%; 
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<h2>
	التحقق من القيم المنطقية
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_8" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'0'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">''</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">' '</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'true'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'false'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">([],</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// NULL</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln"> FILTER_NULL_ON_FAILURE</span><span class="pun">));</span><span class="pln"> </span><span class="com">// false</span></pre>

<h2>
	التحقق من القيم العشرية
</h2>

<p>
	يتحقق من القيمة على أنّها قيمة عشرية ويحوّلها إلى قيمة عشرية عند النجاح.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_10" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0000</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.00001</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.00001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.00001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">));</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0000</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.00001</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.00001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.00001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
float(1)
float(1)
float(1)
float(1.00001)
float(1)
float(1)
float(1)
float(1.00001)
bool(false)
bool(false)
bool(false)
bool(false)

float(1)
float(1)
float(1)
float(1.00001)
float(1)
float(1)
float(1)
float(1.00001)
float(1000)
float(1000)
float(1000)
float(1000.00001)
</pre>

<h2>
	التحقق من العنوان الفيزيائي (MAC Address)
</h2>

<p>
	يتحقق من قيمة أنّها عنوان فيزيائي صحيح.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_12" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'FA-F9-DD-B2-5E-0D'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_MAC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'DC-BB-17-9A-CE-81'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_MAC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'96-D5-9E-67-40-AB'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_MAC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'96-D5-9E-67-40'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_MAC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">''</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_MAC</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(17) "FA-F9-DD-B2-5E-0D"
string(17) "DC-BB-17-9A-CE-81"
string(17) "96-D5-9E-67-40-AB"
bool(false)
bool(false)
</pre>

<h2>
	تعقيم عناوين البريد الإلكتروني
</h2>

<p>
	يحذف جميع المحارف باستثناء الأحرف والأرقام والمحارف <code>‎!#$%&amp;'*+-=?^_</code>{|}~@.[]‎`.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_14" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'john@example.com'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_EMAIL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">"!#$%&amp;'*+-=?^_`{|}~.[]@example.com"</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_EMAIL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'john/@example.com'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_EMAIL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'john\@example.com'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_EMAIL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'joh n@example.com'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_EMAIL</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(16) "john@example.com"
string(33) "!#$%&amp;'*+-=?^_`{|}~.[]@example.com"
string(16) "john@example.com"
string(16) "john@example.com"
string(16) "john@example.com"
</pre>

<h2>
	تعقيم الأعداد الصحيحة
</h2>

<p>
	يحذف جميع المحارف باستثناء الأرقام وإشارة الناقص والزائد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_16" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(+</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.00</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(+</span><span class="lit">1.00</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(-</span><span class="lit">1.00</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'-1'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'+1'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.00'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'+1.00'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'-1.00'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1 unicorn'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'-1 unicorn'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'+1 unicorn'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">"!#$%&amp;'*+-=?^_`{|}~@.[]0123456789abcdefghijklmnopqrstuvwxyz"</span><span class="pun">,</span><span class="pln">
FILTER_SANITIZE_NUMBER_INT</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(1) "1"
string(2) "-1"
string(1) "1"
string(1) "1"
string(1) "1"
string(2) "-1"
string(1) "1"
string(2) "-1"
string(2) "+1"
string(3) "100"
string(4) "+100"
string(4) "-100"
string(1) "1"
string(2) "-1"
string(2) "+1"
string(12) "+-0123456789"
</pre>

<h2>
	تعقيم الروابط
</h2>

<p>
	يحذف جميع المحارف باستثناء الأحرف والأرقام والمحارف <code>‎$-_.+!*'(),{}|\^~[]</code>&lt;&gt;#%";/?:@&amp;=‎`.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_19" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=y'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">"http://www.example.com/path/to/dir/index.php?test=y!#$%&amp;'*+-=?^_`{|}~.[]"</span><span class="pun">,</span><span class="pln">
FILTER_SANITIZE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=a b c'</span><span class="pun">,</span><span class="pln">
FILTER_SANITIZE_URL</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(72) "http://www.example.com/path/to/dir/index.php?test=y!#$%&amp;'*+-=?^_`{|}~.[]"
string(53) "http://www.example.com/path/to/dir/index.php?test=abc"
</pre>

<h2>
	التحقق من عناوين البريد الإلكتروني
</h2>

<p>
	تعيد الدالة <code>filter_var()‎</code> عند استخدامها للتحقق من عنوان بريد إلكتروني بيانات مرشّحةً، والتي يجب أن تكون عنوان بريد إلكتروني في هذه الحالة أو <code>false</code> إذا لم يكن عنوان البريد إلكتروني صحيحًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_21" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'john@example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_EMAIL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'notValidEmail'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_EMAIL</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(16) "john@example.com"
bool(false)
</pre>

<p>
	لا تتحقق هذه الدالة من المحارف غير اللاتينية، يمكن التحقق من اسم المجال المدول (Internationalized) من خلال نموذج <code>‎xn--</code> الخاص به.
</p>

<p>
	لاحظ أنّه لا يمكن معرفة فيما إذا كان عنوان البريد الإلكتروني صحيحًا قبل إرسال بريد إلكتروني إليه، قد ترغب بالمزيد من عمليات التحقق مثل التحقق من سجل MX، لكن هذا ليس ضروريًا. لا تنسَ إزالة الحسابات غير المستخدمة عند إرسال بريد تأكيد إلكتروني.
</p>

<h2>
	التحقق من القيم الصحيحة
</h2>

<p>
	تعيد الدالة <code>filter_var()‎</code> عند استخدامها للتحقق من قيمة يجب أن تكون عددًا صحيحًا بيانات مرشّحةً والتي يجب أن تكون عددًا صحيحًا في هذه الحالة أو <code>false</code> إذا لم تكن القيمة عددًا صحيحًا. ولا تنسَ أنّ الأعداد العشرية ليست أعدادًا صحيحة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_23" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'10'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'a10'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'10a'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">' '</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'10.00'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'10,000'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'-5'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'+7'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
int(10)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
int(-5)
int(7)
</pre>

<p>
	يمكنك استخدام تعبير نمطي إذا كنت تتوقع أرقامًا فقط:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_25" style="">
<span class="kwd">if</span><span class="pun">(</span><span class="pln">is_string</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'entry'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> preg_match</span><span class="pun">(</span><span class="str">'#^[0-9]+$#'</span><span class="pun">,</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'entry'</span><span class="pun">]))</span><span class="pln">
</span><span class="com">// ‫هذا رقم صحيح (موجب)</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="com">// الرقم المدخل غير صحيح</span></pre>

<p>
	لا تحتاج للقيام بمثل هذا التحقق إذا كنت تحوّل هذه القيمة إلى عدد صحيح لذا يمكنك استخدام <code>filter_var()‎</code>.
</p>

<h2>
	التحقق من وجود عدد صحيح ضمن مجال
</h2>

<p>
	نحتاج إلى تضمين الحد الأقصى والحد الأدنى للمجال للتحقق من وجود عدد صحيح ضمن هذا المجال.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_27" style="">
<span class="pln">$options </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
    </span><span class="str">'options'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
        </span><span class="str">'min_range'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'max_range'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'5'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'10'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'8'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'4'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'11'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'-6'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_INT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
int(5)
int(10)
int(8)
bool(false)
bool(false)
bool(false)
</pre>

<h2>
	التحقق من رابط
</h2>

<p>
	تعيد الدالة <code>filter_var()‎</code> عند استخدامها لترشيح رابط بيانات مرشّحةً والتي يجب أن تكون رابطًا في هذه الحالة أو <code>false</code> إذا لم يكن الرابط صحيحًا:
</p>

<p>
	مثال الرابط <code>example.com</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_29" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_SCHEME_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_HOST_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_PATH_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_QUERY_REQUIRED</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
</pre>

<p>
	الرابط <code><a href="http://example.com" ipsnoembed="true" rel="external nofollow">http://example.com</a></code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_31" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_SCHEME_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_HOST_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_PATH_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_QUERY_REQUIRED</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(18) "http://example.com"
string(18) "http://example.com"
string(18) "http://example.com"
bool(false)
bool(false)
</pre>

<p>
	الرابط <code><a href="http://www.example.com" ipsnoembed="true" rel="external nofollow">http://www.example.com</a></code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_33" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_SCHEME_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_HOST_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_PATH_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_QUERY_REQUIRED</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(22) "http://www.example.com"
string(22) "http://www.example.com"
string(22) "http://www.example.com"
bool(false)
bool(false)
</pre>

<p>
	الرابط <code><a href="http://www.example.com/path/to/dir/%E2%80%8E" ipsnoembed="true" rel="external nofollow">http://www.example.com/path/to/dir/‎</a></code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_35" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_SCHEME_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_HOST_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_PATH_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_QUERY_REQUIRED</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
bool(false)
</pre>

<p>
	الرابط <code><a href="http://www.example.com/path/to/dir/index.php" ipsnoembed="true" rel="external nofollow">http://www.example.com/path/to/dir/index.php</a></code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_37" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_SCHEME_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_HOST_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_PATH_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_QUERY_REQUIRED</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
bool(false)
</pre>

<p>
	الرابط <code><a href="http://www.example.com/path/to/dir/index.php?test=y" ipsnoembed="true" rel="external nofollow">http://www.example.com/path/to/dir/index.php?test=y</a></code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_39" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=y'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=y'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_SCHEME_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=y'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_HOST_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=y'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_PATH_REQUIRED</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'http://www.example.com/path/to/dir/index.php?test=y'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_QUERY_REQUIRED</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
</pre>

<p>
	<strong>تحذير</strong>: يجب التحقق من أنّ البروتوكول يحميك من هجوم البرمجة عبر المواقع (XSS).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_41" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'javascript://comment%0Aalert(1)'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_URL</span><span class="pun">));</span><span class="pln">
</span><span class="com">// string(31) "javascript://comment%0Aalert(1)"</span></pre>

<h2>
	تعقيم الأعداد العشرية
</h2>

<p>
	يحذف جميع المحارف باستثناء الأرقام و<code>‎+-</code> والمحارف <code>‎.,eE</code> اختياريًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_45" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0000</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.00001</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.00001'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.00001'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.8281e-009'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(1) "1"
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(4) "1000"
string(5) "10000"
string(8) "10000000"
string(9) "100000001"
string(9) "18281-009"
</pre>

<p>
	باستخدام خيار <code>FILTER_FLAG_ALLOW_THOUSAND</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_47" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0000</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.00001</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.00001'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.00001'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.8281e-009'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_THOUSAND</span><span class="pun">));</span></pre>

<p>
	يكون الخرج:
</p>

<pre class="ipsCode">
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(5) "1,000"
string(6) "1,0000"
string(9) "1,0000000"
string(10) "1,00000001"
string(9) "18281-009"
</pre>

<p>
	باستخدام الخيار <code>FILTER_FLAG_ALLOW_SCIENTIFIC</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_49" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.0000</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="lit">1.00001</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.0000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.00001'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.0000'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1,000.00001'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'1.8281e-009'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_NUMBER_FLOAT</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_ALLOW_SCIENTIFIC</span><span class="pun">));</span></pre>

<p>
	يكون الخرج:
</p>

<pre class="ipsCode">
string(1) "1"
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(4) "1000"
string(5) "10000"
string(8) "10000000"
string(9) "100000001"
string(10) "18281e-009"
</pre>

<h2>
	التحقق من عنوان IP
</h2>

<p>
	يفحص قيمة فيما إذا كانت عنوان IP صحيح:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_51" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'185.158.24.24'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'2001:0db8:0a0b:12f0:0000:0000:0000:0001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'192.168.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'127.0.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(13) "185.158.24.24"
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
string(11) "192.168.0.1"
string(9) "127.0.0.1"
</pre>

<p>
	التحقق من عنوان IP فيما إذا كان عنوان IPv4 صحيح:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_53" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'185.158.24.24'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_IPV4</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'2001:0db8:0a0b:12f0:0000:0000:0000:0001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_IPV4</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'192.168.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_IPV4</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'127.0.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_IPV4</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(13) "185.158.24.24"
bool(false)
string(11) "192.168.0.1"
string(9) "127.0.0.1"
</pre>

<p>
	التحقق من عنوان IP فيما إذا كان عنوان IPv6 صحيح:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_55" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'185.158.24.24'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_IPV6</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'2001:0db8:0a0b:12f0:0000:0000:0000:0001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_IPV6</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'192.168.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_IPV6</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'127.0.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_IPV6</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
bool(false)
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
bool(false)
bool(false)
</pre>

<p>
	التحقق من كون عنوان IP غير موجود ضمن مجال خاص:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_57" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'185.158.24.24'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_NO_PRIV_RANGE</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'2001:0db8:0a0b:12f0:0000:0000:0000:0001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_NO_PRIV_RANGE</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'192.168.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_NO_PRIV_RANGE</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'127.0.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_NO_PRIV_RANGE</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(13) "185.158.24.24"
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
bool(false)
string(9) "127.0.0.1"
</pre>

<p>
	التحقق من كون عنوان IP غير موجود ضمن مجال محجوز:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_59" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'185.158.24.24'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_NO_RES_RANGE</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'2001:0db8:0a0b:12f0:0000:0000:0000:0001'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln">
FILTER_FLAG_NO_RES_RANGE</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'192.168.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_NO_RES_RANGE</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">filter_var</span><span class="pun">(</span><span class="str">'127.0.0.1'</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_IP</span><span class="pun">,</span><span class="pln"> FILTER_FLAG_NO_RES_RANGE</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
string(13) "185.158.24.24"
bool(false)
string(11) "192.168.0.1"
bool(false)
</pre>

<h2>
	التعقيم بالمرشحات
</h2>

<p>
	يمكننا استخدام المرشِّحات لتعقيم متغير ما وفقًا لاحتياجاتنا، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3463_61" style="">
<span class="pln">$string </span><span class="pun">=</span><span class="pln"> </span><span class="str">"&lt;p&gt;Example&lt;/p&gt;"</span><span class="pun">;</span><span class="pln">
$newstring </span><span class="pun">=</span><span class="pln"> filter_var</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_STRING</span><span class="pun">);</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$newstring</span><span class="pun">);</span><span class="pln"> </span><span class="com">// string(7) "Example"</span></pre>

<p>
	ستحذف الشيفرة السابقة وسوم <code>html</code> من المتغير <code>‎$string</code>.
</p>

<p>
	ترجمة -وبتصرف- للفصل [Filters &amp; Filter Functions] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D9%85%D9%88%D9%84%D8%AF%D8%A7%D8%AA-%D9%88%D8%AA%D9%88%D8%B6%D9%8A%D8%AD-%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D9%85%D8%BA%D9%84%D9%81-closure-%D9%81%D9%8A-php-r1127/" rel="">شرح المولدات وتوضيح مفهوم المغلف (closure) في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%85%D8%B2%D8%A9-%D8%A8%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-utf-8-%D9%81%D9%8A-php-r1125/" rel="">معالجة الملفات والبيانات المرمزة بترميز UTF-8 في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1126</guid><pubDate>Sat, 20 Feb 2021 13:01:00 +0000</pubDate></item><item><title>&#x645;&#x639;&#x627;&#x644;&#x62C;&#x629; &#x627;&#x644;&#x645;&#x644;&#x641;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x631;&#x645;&#x632;&#x629; &#x628;&#x62A;&#x631;&#x645;&#x64A;&#x632; UTF-8 &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%85%D8%B2%D8%A9-%D8%A8%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-utf-8-%D9%81%D9%8A-php-r1125/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/4.png.493c3babc34ed4c15438597feb7bcfb1.png" /></p>
<h2>
	دوال الملاءمة (Convenience functions)
</h2>

<h3>
	الخرج والدخل الخام المباشر
</h3>

<p>
	توفر الدالتان <a href="https://wiki.hsoub.com/PHP/file_get_contents" rel="external"><code>file_get_contents</code></a> و <code><a href="https://wiki.hsoub.com/PHP/file_put_contents" rel="external">file_put_contents</a></code> قابلية القراءة/الكتابة إلى/من ملف من/إلى سلسلة نصية في PHP في استدعاء واحد.
</p>

<p>
	يمكن أن تستخدم الدالة <a href="https://wiki.hsoub.com/PHP/file_put_contents" rel="external"><code>file_put_contents</code></a> أيضًا مع راية القناع البتي <code>FILE_APPEND</code> للإضافة إلى الملف بدلًا من الكتابة فوقه، ويمكن استخدامها مع القناع البتي <code>LOCK_EX</code> للحصول على قفل حصري للملف أثناء إجراء الكتابة. يمكن دمج رايات القناع البتي باستخدام عامل العملية الثنائية <code>OR</code> <code>|</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_8" style=""><span class="pln">$path </span><span class="pun">=</span><span class="pln"> </span><span class="str">"file.txt"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫قراءة محتويات الملف file.txt إلى ‎$contents</span><span class="pln">
$contents </span><span class="pun">=</span><span class="pln"> file_get_contents</span><span class="pun">(</span><span class="pln">$path</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫إذا غيّرنا شيئًا ما مثلًا `CRLF` إلى `LF`</span><span class="pln">
$contents </span><span class="pun">=</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="str">"\r\n"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">,</span><span class="pln"> $contents</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫نكتب هذا التغيير في file.txt مستبدلين المحتويات الأصلية</span><span class="pln">
file_put_contents</span><span class="pun">(</span><span class="pln">$path</span><span class="pun">,</span><span class="pln"> $contents</span><span class="pun">);</span></pre>

<p>
	تفيد الراية <code>FILE_APPEND</code> في الإضافة إلى ملفات السجلات، بينما تساعد الراية <code>LOCK_EX</code> في منع حالة سباق عدة عمليات للكتابة في الملف، فمثلًا لكتابة حالة الجلسة الحالية في ملف سجل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_10" style=""><span class="pln">file_put_contents</span><span class="pun">(</span><span class="str">"logins.log"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"{$_SESSION["</span><span class="pln">username</span><span class="str">"]} logged in"</span><span class="pun">,</span><span class="pln"> FILE_APPEND </span><span class="pun">|</span><span class="pln"> LOCK_EX</span><span class="pun">);</span></pre>

<h3>
	الخرج والدخل بصيغة CSV
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_12" style=""><span class="pln">fgetcsv</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">,</span><span class="pln"> $length</span><span class="pun">,</span><span class="pln"> $separator</span><span class="pun">)</span></pre>

<p>
	تحلل الدالة <a href="https://wiki.hsoub.com/PHP/fgetcsv" rel="external"><code>fgetcsv</code></a> سطرًا من الملف المفتوح وتبحث عن حقول <code>csv</code>، ثم تعيد هذه الحقول في مصفوفة في حالة النجاح وإلا تعيد <code>FALSE</code>. تقرأ بشكلٍ افتراضي سطرًا واحدًا فقط من ملف <code>csv</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_14" style=""><span class="pln">$file </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"contacts.csv"</span><span class="pun">,</span><span class="str">"r"</span><span class="pun">);</span><span class="pln">
print_r</span><span class="pun">(</span><span class="pln">fgetcsv</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">));</span><span class="pln">
print_r</span><span class="pun">(</span><span class="pln">fgetcsv</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="str">" "</span><span class="pun">));</span><span class="pln">
fclose</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">);</span></pre>

<p>
	محتويات ملف <code>contacts.csv</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_16" style=""><span class="typ">Kai</span><span class="pln"> </span><span class="typ">Jim</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Refsnes</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Stavanger</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Norway</span><span class="pln">
</span><span class="typ">Hege</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Refsnes</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Stavanger</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Norway</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">Array
(
    [0] =&gt; Kai Jim
    [1] =&gt; Refsnes
    [2] =&gt; Stavanger
    [3] =&gt; Norway
)
Array
(
    [0] =&gt; Hege,
)
</pre>

<h3>
	قراءة ملف إلى مجرى الخرج القياسي مباشرةً
</h3>

<p>
	تنسخ الدالة <a href="https://wiki.hsoub.com/PHP/readfile" rel="external"><code>readfile</code></a> ملفًا إلى المخزن المؤقت للخرج، ولا تؤدي إلى ظهور أيّة مشاكل في الذاكرة حتى عند إرسال ملفات كبيرة من تلقاء نفسها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_18" style=""><span class="pln">$file </span><span class="pun">=</span><span class="pln"> </span><span class="str">'monkey.gif'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">file_exists</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Content-Description: File Transfer'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Content-Type: application/octet-stream'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Content-Disposition: attachment; filename="'</span><span class="pun">.</span><span class="pln">basename</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">).</span><span class="str">'"'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Expires: 0'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Cache-Control: must-revalidate'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Pragma: public'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Content-Length: '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> filesize</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">));</span><span class="pln">
    readfile</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	القراءة بدءًا من مكان مؤشر في ملف
</h3>

<p>
	نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/fpassthru" rel="external"><code>fpassthru</code></a> بدلًا من ذلك للبحث عن نقطة في الملف للبدء بالنسخ إلى مجرى الخرج القياسي، في المثال التالي يُنسخ آخر 1024 بايت إلى الخرج القياسي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_20" style=""><span class="pln">$fh </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"rb"</span><span class="pun">);</span><span class="pln">
fseek</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1024</span><span class="pun">,</span><span class="pln"> SEEK_END</span><span class="pun">);</span><span class="pln">
fpassthru</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">);</span></pre>

<h3>
	قراءة ملف إلى مصفوفة
</h3>

<p>
	تعيد الدالة <a href="https://wiki.hsoub.com/PHP/file" rel="external"><code>file</code></a> أسطر الملف الممرَّر في مصفوفة، يقابل كل عنصر من المصفوفة سطرًا من الملف مع استمرار إضافة السطر الجديد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_22" style=""><span class="pln">print_r</span><span class="pun">(</span><span class="pln">file</span><span class="pun">(</span><span class="str">"test.txt"</span><span class="pun">));</span></pre>

<p>
	محتويات الملف <code>test.txt</code>:
</p>

<pre class="ipsCode">Welcome to File handling
This is to test file handling
</pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">Array
(
    [0] =&gt; Welcome to File handling
    [1] =&gt; This is to test file handling
)
</pre>

<h2>
	حذف ملفات ومجلدات
</h2>

<h3>
	حذف ملفات
</h3>

<p>
	تحذف الدالة <a href="https://wiki.hsoub.com/PHP/unlink" rel="external"><code>unlink</code></a> ملفًا واحدًا وتعيد القيمة <code>TRUE</code> عند نجاح العملية و<code>FALSE</code> عند فشلها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_24" style=""><span class="pln">$filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/path/to/file.txt'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">file_exists</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $success </span><span class="pun">=</span><span class="pln"> unlink</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">$success</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"Cannot delete $filename"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	حذف مجلدات مع حذف عودي (recursive deletion)
</h3>

<p>
	يمكن حذف المجلدات باستخدام الدالة <a href="https://wiki.hsoub.comhttps://wiki.hsoub.com/PHP/rmdir" rel="external nofollow"><code>rmdir</code></a> إلا أنّ هذه الدالة تحذف المجلدات الفارغة فقط، ولحذف مجلد يحتوي ملفات يجب حذف هذه الملفات أولًا، إذا احتوى المجلد على مجلدات فرعية نحتاج إلى استخدام العودية.
</p>

<p>
	يفحص المثال التالي الملفات في مجلد ويحذف ما بداخله من ملفات ومجلدات بشكلٍ تعاودي ويعيد عدد الملفات (وليس المجلدات) المحذوفة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_26" style=""><span class="kwd">function</span><span class="pln"> recurse_delete_dir</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $dir</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ‫التأكد من أنّ ‎$dir ينتهي بخط مائل لنتمكن من ربطه مع أسماء الملفات مباشرةً</span><span class="pln">
    $dir </span><span class="pun">=</span><span class="pln"> rtrim</span><span class="pun">(</span><span class="pln">$dir</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/\\"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"/"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ‫استخدام dir()‎᠎ للحصول على قائمة الملفات</span><span class="pln">
    $list </span><span class="pun">=</span><span class="pln"> dir</span><span class="pun">(</span><span class="pln">$dir</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// ‫تخزين اسم الملف التالي في ‎$file، إذا كانت قيمة ‎$file هي false أي لا توجد ملفات بعد عندها تُنهى الحلقة</span><span class="pln">
    </span><span class="kwd">while</span><span class="pun">((</span><span class="pln">$file </span><span class="pun">=</span><span class="pln"> $list</span><span class="pun">-&gt;</span><span class="pln">read</span><span class="pun">())</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$file </span><span class="pun">===</span><span class="pln"> </span><span class="str">"."</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> $file </span><span class="pun">===</span><span class="pln"> </span><span class="str">".."</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">is_file</span><span class="pun">(</span><span class="pln">$dir </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            unlink</span><span class="pun">(</span><span class="pln">$dir </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">);</span><span class="pln">
            $count</span><span class="pun">++;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> elseif</span><span class="pun">(</span><span class="pln">is_dir</span><span class="pun">(</span><span class="pln">$dir </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $count </span><span class="pun">+=</span><span class="pln"> recurse_delete_dir</span><span class="pun">(</span><span class="pln">$dir </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// يمكننا الآن حذف المجلد</span><span class="pln">
    rmdir</span><span class="pun">(</span><span class="pln">$dir</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $count</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الحصول على معلومات ملف
</h2>

<h3>
	التحقق من كون المسار ملف أو مجلد
</h3>

<p>
	تتحقق الدالة <a href="https://wiki.hsoub.com/PHP/is_dir" rel="external"><code>is_dir</code></a> إن كان الوسيط الممرر إليها مجلدًا أم لا، فيما تتحقق الدالة <a href="https://wiki.hsoub.com/PHP/is_file" rel="external"><code>is_file</code></a> إن كان الوسيط الممرر إليها ملفًا أم لا، ويمكن استخدام الدالة <a href="https://wiki.hsoub.com/PHP/file_exists" rel="external"><code>file_exists</code></a> للتحقق من وجود ملف أو مجلد محدد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_28" style=""><span class="pln">$dir </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/this/is/a/directory"</span><span class="pun">;</span><span class="pln">

$file </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/this/is/a/file.txt"</span><span class="pun">;</span><span class="pln">

echo is_dir</span><span class="pun">(</span><span class="pln">$dir</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"$dir is a directory"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"$dir is not a directory"</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln">
    is_file</span><span class="pun">(</span><span class="pln">$dir</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"$dir is a file"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"$dir is not a file"</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln">
    file_exists</span><span class="pun">(</span><span class="pln">$dir</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"$dir exists"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"$dir doesn't exist"</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln">
    is_dir</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"$file is a directory"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"$file is not a directory"</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln">
    is_file</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"$file is a file"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"$file is not a file"</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">,</span><span class="pln">
    file_exists</span><span class="pun">(</span><span class="pln">$file</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"$file exists"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"$file doesn't exist"</span><span class="pun">,</span><span class="pln"> PHP_EOL</span><span class="pun">;</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">/this/is/a/directory is a directory
/this/is/a/directory is not a file
/this/is/a/directory exists
/this/is/a/file.txt is not a directory
/this/is/a/file.txt is a file
/this/is/a/file.txt exists
</pre>

<h3>
	التحقق من نوع ملف
</h3>

<p>
	نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/filetype" rel="external"><code>filetype</code></a> لمعرفة نوع ملف محدد والذي قد يكون إمَّا أنبوبة مسماة <code>FIFO</code> أو ملف محرفي خاص <code>char</code> أو مجلد <code>dir</code> أو ملف كتلي خاص <code>block</code> أو وصلة رمزية <code>link</code> أو ملف عادي <code>file</code> أو مقبس <code>socket</code> أو نوع غير معروف <code>unknown</code>.
</p>

<p>
	تمرير اسم الملف إلى الدالة <a href="https://wiki.hsoub.com/PHP/filetype" rel="external"><code>filetype</code></a> مباشرةً:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_30" style=""><span class="pln">echo filetype</span><span class="pun">(</span><span class="str">"~"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// dir</span></pre>

<p>
	لاحظ أنّه إذا لم يكن الملف موجودًا فإنّ الدالة تعيد <code>false</code> وتشغّل <code>E_WARNING</code>.
</p>

<h3>
	التحقق من قابلية القراءة والكتابة
</h3>

<p>
	نمرر اسم الملف للدالتين <a href="https://wiki.hsoub.com/PHP/is_writable" rel="external"><code>is_writable</code></a> و<a href="https://wiki.hsoub.com/PHP/is_readable" rel="external"><code>is_readable</code></a> للتحقق من كون الملف قابلًا للكتابة أو القراءة.
</p>

<p>
	تعيد الدالتان القيمة <code>false</code> إذا لم يكن الملف موجودًا.
</p>

<h3>
	التحقق من وقت الوصول إلى ملف وتعديله
</h3>

<p>
	تعيد الدالتان <a href="https://wiki.hsoub.com/PHP/filemtime" rel="external"><code>filemtime</code></a> و<a href="https://wiki.hsoub.com/PHP/fileatime" rel="external"><code>fileatime</code></a> الختم الزمني لآخر تعديل أو وصول للملف، ويكون الختم الزمني المعاد بصيغة <code>Unix</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_32" style=""><span class="pln">echo </span><span class="str">"File was last modified on "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> date</span><span class="pun">(</span><span class="str">"Y-m-d"</span><span class="pun">,</span><span class="pln"> filemtime</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">));</span><span class="pln">
echo </span><span class="str">"File was last accessed on "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> date</span><span class="pun">(</span><span class="str">"Y-m-d"</span><span class="pun">,</span><span class="pln"> fileatime</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">));</span></pre>

<h3>
	الحصول على أجزاء المسار مع fileinfo
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_34" style=""><span class="pln">$fileToAnalyze </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">'/var/www/image.png'</span><span class="pun">);</span><span class="pln">

$filePathParts </span><span class="pun">=</span><span class="pln"> pathinfo</span><span class="pun">(</span><span class="pln">$fileToAnalyze</span><span class="pun">);</span><span class="pln">

echo </span><span class="str">'&lt;pre&gt;'</span><span class="pun">;</span><span class="pln">
print_r</span><span class="pun">(</span><span class="pln">$filePathParts</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">'&lt;/pre&gt;'</span><span class="pun">;</span></pre>

<p>
	خرج المثال السابق:
</p>

<pre class="ipsCode">Array
(
    [dirname] =&gt; /var/www
    [basename] =&gt; image.png
    [extension] =&gt; png
    [filename] =&gt; image
)
</pre>

<p>
	يمكن استخدام هذا الخرج كالتالي:
</p>

<pre class="ipsCode">$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
</pre>

<table>
	<tbody>
		<tr>
			<td>
				<strong>المعامل</strong>
			</td>
			<td>
				<strong>تفاصيل</strong>
			</td>
		</tr>
		<tr>
			<td>
				‎$path
			</td>
			<td>
				المسار الكامل للملف الذي نريد تحليله
			</td>
		</tr>
		<tr>
			<td>
				‎$option
			</td>
			<td>
				‫أحد الخيارات التالية: PATHINFO_DIRNAME أو PATHINFO_BASENAME أو PATHINFO_EXTENSION أو PATHINFO_FILENAME
			</td>
		</tr>
	</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<ul>
	<li>
		تُعاد مصفوفة ترابطية (associative array) إذا لم يُمرَّر المعامل الثاني وإلا تُعاد سلسلة نصية.
	</li>
	<li>
		لا تتحقق من وجود الملف
	</li>
	<li>
		تُحلَّل السلسلة النصية ببساطة إلى أجزاء ولا يُجرى أي تحقق على الملف (مثل التحقق من نوع الترويسة وغير ذلك)
	</li>
	<li>
		الامتداد هو الامتداد الأخير للمتغير <code>‎$path</code>، سيكون مسار الملف <code>image.jpg.png</code> هو <code>‎.‎png</code> حتى لو كان هو ملف <code>‎.‎jpg</code> تقنيًا، وإذا كان الملف بدون امتداد لن يُعاد عنصر الامتداد في المصفوفة.
	</li>
</ul>

<h2>
	خرج ودخل ملف معتمد على المجرى
</h2>

<h3>
	فتح مجرى
</h3>

<p>
	تفتح الدالة <a href="https://wiki.hsoub.com/PHP/fopen" rel="external"><code>fopen</code></a> ملفًا وتخصص له مقبضًا يشبه مقبض الباب يمكن أن تستخدمه دوالًا أخرى للقراءة والكتابة والبحث وغيرها، هذه القيمة من النوع مورد ولا يمكن تمريرها إلى النياسب الأخرى المستمرة في وظيفتها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_36" style=""><span class="pln">$f </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"errors.log"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"a"</span><span class="pun">);</span></pre>

<p>
	ستحاول الشيفرة السابقة فتح الملف <code>errors.log</code> للكتابة.
</p>

<p>
	المعامل الثاني هو نمط مجرى الملف:
</p>

<table>
	<tbody>
		<tr>
			<td>
				<strong>النمط</strong>
			</td>
			<td>
				<strong>الوصف</strong>
			</td>
		</tr>
		<tr>
			<td>
				r
			</td>
			<td>
				يفتح الملف للقراءة فقط بدءًا من أول الملف
			</td>
		</tr>
		<tr>
			<td>
				r+‎
			</td>
			<td>
				يفتح الملف للقراءة والكتابة بدءًا من أول الملف
			</td>
		</tr>
		<tr>
			<td>
				w
			</td>
			<td>
				يفتح الملف للكتابة فقط بدءًا من أول الملف، إذا كان الملف موجودًا سيفرغه وإذا لم يكن موجودًا سيحاول أن ينشئه
			</td>
		</tr>
		<tr>
			<td>
				w+‎
			</td>
			<td>
				يفتح الملف للقراءة والكتابه بدءًا من أول الملف، إذا كان الملف موجودًا سيفرغه وإذا لم يكن موجودًا سيحاول أن ينشئه
			</td>
		</tr>
		<tr>
			<td>
				a
			</td>
			<td>
				يفتح الملف للكتابة فقط بدءًا من نهاية الملف، إذا لم يكن الملف موجودًا سيحاول أن ينشئه
			</td>
		</tr>
		<tr>
			<td>
				a+‎
			</td>
			<td>
				يفتح الملف للقراءة والكتابة بدءًا من نهاية الملف، إذا لم يكن الملف موجودًا سيحاول أن ينشئه
			</td>
		</tr>
		<tr>
			<td>
				x
			</td>
			<td>
				‫ينشئ ويفتح ملف للكتابة فقط، وإذا كان الملف موجودًا ستفشل الدالة fopen ‏
			</td>
		</tr>
		<tr>
			<td>
				x+‎
			</td>
			<td>
				‫ينشئ ويفتح ملف للكتابة فقط، وإذا كان الملف موجودًا ستفشل الدالة fopen ‏
			</td>
		</tr>
		<tr>
			<td>
				c
			</td>
			<td>
				يفتح الملف للكتابة فقط، إذا لم يكن موجودًا سيحاول أن ينشئه، يبدأ الكتابة من أول الملف لكنه لا يفرغ الملف قبل الكتابة
			</td>
		</tr>
		<tr>
			<td>
				c+‎
			</td>
			<td>
				يفتح الملف للقراءة والكتابة، إذا لم يكن موجودًا سيحاول أن ينشئه، يبدأ الكتابة من أول الملف لكنه لا يفرغ الملف قبل الكتابة
			</td>
		</tr>
	</tbody>
</table>

<p>
	إنّ إضافة المحرف <code>t</code> بعد النمط (مثل <code>a+b</code>، <code>‏wt</code> وغير ذلك) في نظام التشغيل ويندوز ستترجم نهايات الأسطر "‎\n" إلى "‎\r\n" عند العمل مع الملف، نضيف المحرف <code>b</code> بعد النمط إذا لم يكن هذا مقصودًا خاصةً إذا كان الملف ثنائيًا.
</p>

<p>
	يجب أن يغلق تطبيق PHP أي مجرى بعد الانتهاء من استخدامه باستخدام الدالة <a href="https://wiki.hsoub.com/PHP/fclose" rel="external"><code>fclose</code></a> وذلك منعًا لظهور الخطأ <code>Too many open files</code>، يعدّ هذا مهمًا خاصةً في برامج واجهة سطر الأوامر (CLI) بما أنّ المجاري تُغلق عند إيقاف التشغيل فقط، وهذا يعني أن ذلك ليس ضروريًا جدًا في خوادم الويب (لكن يجب استخدامه أيضًا كممارسة لمنع تسرب المورد) إذا لم تتوقع تنفيذ العملية لوقتٍ طويل ولن تفتح عدة مجاري.
</p>

<h3>
	القراءة
</h3>

<p>
	نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/fread" rel="external"><code>fread</code></a> لقراءة عدد مُعطى من البايتات بدءًا من مؤشر الملف أو حتى الوصول إلى نهاية الملف (EOF).
</p>

<h3>
	قراءة أسطر
</h3>

<p>
	نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/fgets" rel="external"><code>fgets</code></a> لقراءة ملف وتستمر بالقراءة حتى تصل إلى نهاية السطر (EOL) أو حتى تنتهي قراءة العدد المُعطى.
</p>

<p>
	ستحرِّك كل من الدالتين <a href="https://wiki.hsoub.com/PHP/fread" rel="external"><code>fread</code></a> و<a href="https://wiki.hsoub.com/PHP/fgets" rel="external"><code>fgets</code></a> مؤشر الملف أثناء القراءة.
</p>

<h3>
	قراءة كل البايتات المتبقية
</h3>

<p>
	تضع الدالة <a href="https://www.php.net/stream-get-contents" rel="external nofollow"><code>stream_get_contents</code></a> كل البايتات المتبقية في المجرى في سلسلة نصية وتعيدها.
</p>

<h3>
	تعديل موضع مؤشر ملف
</h3>

<p>
	يكون مؤشر الملف عند فتح المجرى افتراضيًا في بداية الملف (أو في نهايته إذا اُستعمل النمط)، نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/fseek" rel="external"><code>fseek</code></a> لنحرّك مؤشر الملف إلى موضع جديد، نسبةً لإحدى القيم الثلاثة:
</p>

<ul>
	<li>
		<code>SEEK_SET</code>: هذه هي القيمة الافتراضية، تكون إزاحة موقع مؤشر الملف نسبةً لبدايته.
	</li>
	<li>
		<code>SEEK_CUR</code>: إزاحة موقع مؤشر الملف نسبةً للموقع الحالي.
	</li>
	<li>
		<code>SEEK_END</code>: إزاحة موقع مؤشر الملف نسبةً إلى نهاية الملف، ومن الشائع تمرير إزاحة سالبة لهذه القيمة، ستحرّك موقع مؤشر الملف عددًا محددًا من البايتات قبل نهاية الملف.
	</li>
</ul>

<p>
	تعد الدالة <a href="https://wiki.hsoub.com/PHP/rewind" rel="external"><code>rewind</code></a> اختصارًا ملائمًا للشيفرة <code>fseek($fh, 0, SEEK_SET)‎</code>.
</p>

<p>
	يُظهر استخدام الدالة <a href="https://wiki.hsoub.com/PHP/ftell" rel="external"><code>ftell</code></a> الموقع المطلق لمؤشر الملف.
</p>

<p>
	يتخطى السكربت التالي أول 10 بايتات، ويقرأ 10 بايتات التالية ثم يتخطى 10 بايتات ويقرأ 10 بايتات ثم يقرأ 10 بايتات الأخيرة من الملف <code>file.txt</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_38" style=""><span class="pln">$fh </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"rb"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫البدء من الإزاحة 10</span><span class="pln">
fseek</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قراءة 10 بايتات</span><span class="pln">
echo fread</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">

</span><span class="com">// تخطي 10 بايتات</span><span class="pln">
fseek</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> SEEK_CUR</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قراءة 10 بايتات</span><span class="pln">
echo fread</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">

</span><span class="com">// تخطي 10 بايتات قبل نهاية الملف</span><span class="pln">
fseek</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> SEEK_END</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قراءة 10 بايتات</span><span class="pln">
echo fread</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
fclose</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">);</span></pre>

<h3>
	الكتابة
</h3>

<p>
	نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/fwrite" rel="external"><code>fwrite</code></a> لكتابة سلسلة في ملف بدءًا من موقع المؤشر الحالي.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_40" style=""><span class="pln">fwrite</span><span class="pun">(</span><span class="pln">$fh</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Some text here\n"</span><span class="pun">);</span></pre>

<h2>
	نقل ونسخ ملفات ومجلدات
</h2>

<h3>
	نسخ ملفات
</h3>

<p>
	تنسخ الدالة <a href="https://wiki.hsoub.com/PHP/copy" rel="external"><code>copy</code></a> الملف المصدر المحدد في الوسيط الأول إلى الهدف المحدد في الوسيط الثاني، يجب أن يكون الهدف في مجلد مُنشأ بالفعل.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_42" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">copy</span><span class="pun">(</span><span class="str">'test.txt'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dest.txt'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'File has been copied successfully'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'Failed to copy file to destination given.'</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	نسخ مجلدات مع عودية (recursion)
</h3>

<p>
	يشبه نسخ الملفات حذفها إلى درجة كبيرة، باستثناء أننا نستخدم الدالة <a href="https://wiki.hsoub.com/PHP/copy" rel="external"><code>copy</code></a> بدلًا من <a href="https://wiki.hsoub.com/PHP/unlink" rel="external"><code>unlink</code></a> للملفات و<a href="https://wiki.hsoub.com/PHP/mkdir" rel="external"><code>mkdir</code></a> بدلًا من <a href="https://wiki.hsoub.com/PHP/rmdir" rel="external"><code>rmdir</code></a> للمجلدات في بداية بدلًا من كونها في نهاية الدالة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_44" style=""><span class="kwd">function</span><span class="pln"> recurse_delete_dir</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $src</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $dest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ‫التأكد من أنّ كل من ‎$src و‎$dest ينتهي بخط مائل حتى يمكننا دمجه مع أسماء الملفات</span><span class="pln">
    $src </span><span class="pun">=</span><span class="pln"> rtrim</span><span class="pun">(</span><span class="pln">$dest</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/\\"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"/"</span><span class="pun">;</span><span class="pln">
    $dest </span><span class="pun">=</span><span class="pln"> rtrim</span><span class="pun">(</span><span class="pln">$dest</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/\\"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"/"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ‫استخدام dir()‎ للحصول على قائمة الملفات</span><span class="pln">
    $list </span><span class="pun">=</span><span class="pln"> dir</span><span class="pun">(</span><span class="pln">$src</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// ‫إنشاء المجلد ‎$dest إذا لم يكن موجودًا</span><span class="pln">
    </span><span class="lit">@mkdir</span><span class="pun">(</span><span class="pln">$dest</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// ‫تخزين اسم الملف التالي في ‎$file، إذا أصبحت قيمة ‎$file هي false تُنهى الحلقة</span><span class="pln">
    </span><span class="kwd">while</span><span class="pun">((</span><span class="pln">$file </span><span class="pun">=</span><span class="pln"> $list</span><span class="pun">-&gt;</span><span class="pln">read</span><span class="pun">())</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$file </span><span class="pun">===</span><span class="pln"> </span><span class="str">"."</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> $file </span><span class="pun">===</span><span class="pln"> </span><span class="str">".."</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">is_file</span><span class="pun">(</span><span class="pln">$src </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            copy</span><span class="pun">(</span><span class="pln">$src </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">,</span><span class="pln"> $dest </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">);</span><span class="pln">
            $count</span><span class="pun">++;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> elseif</span><span class="pun">(</span><span class="pln">is_dir</span><span class="pun">(</span><span class="pln">$src </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $count </span><span class="pun">+=</span><span class="pln"> recurse_copy_dir</span><span class="pun">(</span><span class="pln">$src </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">,</span><span class="pln"> $dest </span><span class="pun">.</span><span class="pln"> $file</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $count</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إعادة التسمية/النقل
</h3>

<p>
	عملية إعادة التسمية/النقل أبسط بكثير، إذ يمكن نقل أو إعادة تسمية كامل المجلد في استدعاء واحد للدالة <a href="https://wiki.hsoub.com/PHP/rename" rel="external"><code>rename</code></a>، أمثلة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_46" style=""><span class="pln">rename</span><span class="pun">(</span><span class="str">"~/file.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"~/file.html"</span><span class="pun">);</span><span class="pln">
rename</span><span class="pun">(</span><span class="str">"~/dir"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"~/old_dir"</span><span class="pun">);</span><span class="pln">
rename</span><span class="pun">(</span><span class="str">"~/dir/file.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"~/dir2/file.txt"</span><span class="pun">);</span></pre>

<h2>
	تقليل استخدام الذاكرة عند التعامل مع ملفات كبيرة
</h2>

<p>
	يمكننا استخدام إحدى الدالتين <code>file</code> أو <code>file_get_contents</code> إذا احتجنا إلى تحليل ملف كبير مثل ملف <code>CSV</code> يتضمن ملايين الأسطر وحجمه أكبر من 10 ميجابايت وينتهي الأمر بالحصول على الخطأ:
</p>

<pre class="ipsCode">Allowed memory size of XXXXX bytes exhausted
</pre>

<p>
	بفرض أنّ المصدر التالي <code>top-1m.csv</code> يحتوي على مليون سطر وحجمه حوالي 22 ميجابايت.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_48" style=""><span class="pln">var_dump</span><span class="pun">(</span><span class="pln">memory_get_usage</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">));</span><span class="pln">
$arr </span><span class="pun">=</span><span class="pln"> file</span><span class="pun">(</span><span class="str">'top-1m.csv'</span><span class="pun">);</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">memory_get_usage</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">int(262144)
int(210501632)
</pre>

<p>
	بما أنّ المفسّر يحتاج إلى حمل الأسطر في مصفوفة <code>‎$arr</code> لذا فإنّه يستهلك 200 ميجابايت من ذاكرة الوصول العشوائي (RAM)، لاحظ أنّه لا يمكننا فعل أي شيء مع محتويات المصفوفة.
</p>

<p>
	بفرض أنّه لدينا الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_50" style=""><span class="pln">var_dump</span><span class="pun">(</span><span class="pln">memory_get_usage</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">));</span><span class="pln">
$index </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">$handle </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"top-1m.csv"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"r"</span><span class="pun">))</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> FALSE</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">((</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> fgetcsv</span><span class="pun">(</span><span class="pln">$handle</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">,</span><span class="pln"> </span><span class="str">","</span><span class="pun">))</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> FALSE</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        file_put_contents</span><span class="pun">(</span><span class="str">'top-1m-reversed.csv'</span><span class="pun">,</span><span class="pln">$index </span><span class="pun">.</span><span class="pln"> </span><span class="str">','</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> strrev</span><span class="pun">(</span><span class="pln">$row</span><span class="pun">[</span><span class="lit">1</span><span class="pun">])</span><span class="pln"> </span><span class="pun">.</span><span class="pln">     PHP_EOL</span><span class="pun">,</span><span class="pln">FILE_APPEND</span><span class="pun">);</span><span class="pln">
        $index</span><span class="pun">++;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    fclose</span><span class="pun">(</span><span class="pln">$handle</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">memory_get_usage</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">));</span></pre>

<p>
	خرج الشيفرة السابقة:
</p>

<pre class="ipsCode">int(262144)
int(262144)
</pre>

<p>
	لا نستخدم بايتًا واحدًا إضافيًا من الذاكرة لكن نحلل كامل ملف <code>CSV</code> ونحفظه إلى ملف آخر مع عكس قيمة العمود الثاني، وذلك لأنّ الدالة <code>fgetcsv</code> تقرأ سطر واحد فقط ويُكتب فوق <code>‎$row</code> عند كل تكرار.
</p>

<h2>
	المجاري (streams)
</h2>

<table>
	<tbody>
		<tr>
			<td>
				<strong>اسم المعامل</strong>
			</td>
			<td>
				<strong>الوصف</strong>
			</td>
		</tr>
		<tr>
			<td>
				Stream Resource
			</td>
			<td>
				‫ يتألف مزود البيانات من الصيغة `‎<scheme>://‎<target>` </target></scheme>
			</td>
		</tr>
	</tbody>
</table>

<h3>
	تسجيل مغلِّف مجرى
</h3>

<p>
	يوفر مغلِّف المجرى مقبضًا لمخطط محدد أو أكثر، يُظهر المثال التالي مُغلِّف مجرى بسيط يرسل طلبات <code>PATCH HTTP</code> عند إغلاق المجرى.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_52" style=""><span class="com">// ‫تسجيل الصنف FooWrapper مغلِّفًا لمجرى روابط ‎foo://‎</span><span class="pln">
stream_wrapper_register</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FooWrapper</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> STREAM_IS_URL</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> </span><span class="kwd">die</span><span class="pun">(</span><span class="str">"Duplicate stream wrapper
registered"</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">FooWrapper</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫‫سيُعدَّل هذا من PHP لإظهار السياق الممرَّر في الاستدعاء الحالي</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $context</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// يستخدم هذا داخليًا في هذا المثال لتخزين الرابط</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $url</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ‫عند استدعاء fopen()‎ مع بروتوكول لهذا المغلِّف، يمكن تنفيذ هذا التابع لتخزين بيانات مثل المضيف.</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> stream_open</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $path</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $mode</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> $options</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">$openedPath</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="kwd">bool</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $url </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="pln">$path</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$url </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">url </span><span class="pun">=</span><span class="pln"> $url</span><span class="pun">[</span><span class="str">"host"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"/"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $url</span><span class="pun">[</span><span class="str">"path"</span><span class="pun">];</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫معالجة استدعاءات الدالة fwrite()‎ على هذا المجرى        </span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> stream_write</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">buffer </span><span class="pun">.=</span><span class="pln"> $data</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫معالجة استدعاءات الدالة fclose()‎ على هذا المجرى</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> stream_close</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $curl </span><span class="pun">=</span><span class="pln"> curl_init</span><span class="pun">(</span><span class="str">"http://"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
        curl_setopt</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">,</span><span class="pln"> CURLOPT_POSTFIELDS</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">buffer</span><span class="pun">);</span><span class="pln">
        curl_setopt</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">,</span><span class="pln"> CURLOPT_CUSTOMREQUEST</span><span class="pun">,</span><span class="pln"> </span><span class="str">"PATCH"</span><span class="pun">);</span><span class="pln">
        curl_exec</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">);</span><span class="pln">
        curl_close</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">buffer </span><span class="pun">=</span><span class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫مُعالج استثناء قيمة تراجعية في حال القيام بعملية غير مدعومة</span><span class="pln">
    </span><span class="com">// هذا ليس ضروريًا‎</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __call</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">,</span><span class="pln"> $args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \RuntimeException</span><span class="pun">(</span><span class="str">"This wrapper does not support $name"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫تُستدعى الشيفرة التالية عند استدعاء unlink("foo://something-else")‎</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> unlink</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $path</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $url </span><span class="pun">=</span><span class="pln"> parse_url</span><span class="pun">(</span><span class="pln">$path</span><span class="pun">);</span><span class="pln">
        $curl </span><span class="pun">=</span><span class="pln"> curl_init</span><span class="pun">(</span><span class="str">"http://"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $url</span><span class="pun">[</span><span class="str">"host"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"/"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $url</span><span class="pun">[</span><span class="str">"path"</span><span class="pun">]);</span><span class="pln">
        curl_setopt</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">,</span><span class="pln"> CURLOPT_CUSTOMREQUEST</span><span class="pun">,</span><span class="pln"> </span><span class="str">"DELETE"</span><span class="pun">);</span><span class="pln">
        curl_exec</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">);</span><span class="pln">
        curl_close</span><span class="pun">(</span><span class="pln">$curl</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُظهر هذا المثال بعض الأمثلة على ما قد يحتويه مُغلِّف مجرى عام، ليست هذه كل التوابع المتوفرة، يمكنك أن تجد <a href="http://php.net/streamWrapper" rel="external nofollow">هنا</a> كل التوابع المتوفرة والتي يمكن تنفيذها.
</p>

<h2>
	ترميز UTF-8
</h2>

<h3>
	الدخل
</h3>

<p>
	يجب التحقق من كل سلسلة نصية مُستقبَلة أنّها مكتوبة بترميز <code>UTF-8</code> صحيح قبل محاولة تخزينها في أي مكان، تقوم دالة <a href="https://www.php.net/manual/en/function.mb-check-encoding.php" rel="external nofollow">mb<em>check</em>encoding()<code>‎</code></a> بهذا العمل لكن يجب أن تستخدمها بشكلٍ منتظم، لا توجد طريقة لحل هذه المشكلة إذ يمكن للعملاء الضارّين إرسال البيانات بأي تشفير يريدونه.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_54" style=""><span class="pln">$string </span><span class="pun">=</span><span class="pln"> $_REQUEST</span><span class="pun">[</span><span class="str">'user_comment'</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">mb_check_encoding</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫ترميز السلسلة النصية ليس UTF-8 لذا أعد تشفيرها</span><span class="pln">
    $actualEncoding </span><span class="pun">=</span><span class="pln"> mb_detect_encoding</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">);</span><span class="pln">
    $string </span><span class="pun">=</span><span class="pln"> mb_convert_encoding</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">,</span><span class="pln"> $actualEncoding</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك تجاهل النقطة الأخيرة إذا كنت تستخدم <code>HTML5</code>، إذ أنّ الطريقة الموثوقة الوحيدة لتكون كل البيانات المرسلة إليك عبر المتصفحات بالترميز <code>UTF-8</code> هي إضافة السمة <code>accept-charset</code> لكل وسوم <code>&lt;form&gt;</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_595_56" style=""><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"somepage.php"</span><span class="pln"> </span><span class="atn">accept-charset</span><span class="pun">=</span><span class="atv">"UTF-8"</span><span class="tag">&gt;</span></pre>

<h3>
	الخرج
</h3>

<p>
	إذا كان تطبيقك ينقل نصًا إلى الأنظمة الأخرى فأنت تحتاج إلى التأكد من ترميز المحارف، يمكنك في PHP استخدام خيار <a href="https://www.php.net/manual/en/ini.core.php#ini.default-charset" rel="external nofollow"><code>default_charset</code></a> في <code>php.ini</code> أو التصريح عن نوع المحتوى يدويًا <code>Content-Type MIME</code> في الترويسة وهذه الطريقة الأفضل عند استهداف المتصفحات الحديثة.
</p>

<pre class="ipsCode">header('Content-Type: text/html; charset=utf-8');
</pre>

<p>
	يمكنك ضبط الترميز في ملف <code>HTML</code> باستخدام <a href="https://wiki.hsoub.com/HTML/Topics/Document_Metadata" rel="external">البيانات الوصفية</a> إذا كنت غير قادرٍ على ضبط ترويسة الرد.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_595_58" style=""><span class="pln">// HTML5
</span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">&gt;</span><span class="pln">

// ‫الإصدارات الأقدم من HTML‫
</span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">http-equiv</span><span class="pun">=</span><span class="atv">"Content-Type"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"text/html; charset=utf-8"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<h3>
	تخزين البيانات والوصول إليها
</h3>

<p>
	تتحدث هذه الفقرة بشكلٍ أساسي عن الترميز <code>UTF-8</code> ودوافع استخدامه مع قاعدة البيانات.
</p>

<p>
	<strong>تخزين البيانات في قاعدة بيانات MySQL:</strong> عندما تحدد مجموعة المحارف (character set) <code>‏utf8mb4</code> لكل الجداول والأعمدة النصية في قاعدة البيانات فأنت تجعل <code>MySQL</code> تخزّن وتستعيد القيم المرمّزة محليًا بالترميز <code>UTF-8</code>.
</p>

<p>
	تستخدم <code>MySQL</code> ضمنيًا الترميز <code>utf8mb4</code> إذا حُدِّد الترتيب <code>utf8mb4_*‎</code> (دون أي مجموعة محارف صريحة).
</p>

<p>
	لا تدعم النسخ القديمة من <code>MySQL</code> (الإصدار ما قبل ‏‎5.5.3‏) الترميز <code>utf8mb4</code> لذا ستضطر إلى استخدام الترميز <code>utf8</code> الذي يدعم مجموعة فرعية من محارف يونيكود (Unicode).
</p>

<p>
	<strong>الوصول إلى البيانات في قاعدة بيانات MySQL:</strong> في شيفرة التطبيق (PHP مثلًا)، مهما كانت الطريقة التي تستخدمها للوصول إلى قاعدة البيانات فأنت تحتاج إلى ضبط ترميز محارف الاتصال لتكون <code>utf8mb4</code>، بهذه الطريقة لا تحوّل <code>MySQL</code> من ترميز <code>UTF-8</code> الأصلي عند تسليم البيانات إلى تطبيقك وبالعكس.
</p>

<p>
	توفر بعض برامج التشغيل آلية خاصة بها لضبط ترميز محارف الاتصال والتي تحدّث حالتها الداخلية وتُخبر <code>MySQL</code> بالترميز الذي سيُستخدم في الاتصال، وهذه هي الطريقة المفضّلة عادةً.
</p>

<p>
	مثلًا (نطبق نفس الدوافع التي في الأعلى فيما يتعلق باستخدام <code>‎utf8mb4/utf8‎</code><span class="ipsEmoji">?</span>
</p>

<ul>
	<li>
		يمكنك تحديد ترميز المحارف باستخدام <a href="https://www.php.net/manual/en/ref.pdo-mysql.connection.php" rel="external nofollow">DSN</a> إذا كنت تستخدم طبقة التجريد <a href="https://www.php.net/manual/en/book.pdo.php" rel="external nofollow">PDO</a> ᠎مع إصدار PHP ≥ 5.3.6:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_60" style=""><span class="pln">$handle </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="str">'mysql:charset=utf8mb4'</span><span class="pun">);</span></pre>

<ul>
	<li>
		يمكنك استدعاء الدالة <a href="https://www.php.net/manual/en/mysqli.set-charset.php" rel="external nofollow"><code>set_charset()‎</code></a> إذا كنت تستخدم <a href="https://www.php.net/manual/en/book.mysqli.php" rel="external nofollow"><code>mysqli</code></a>:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_62" style=""><span class="pln">$conn </span><span class="pun">=</span><span class="pln"> mysqli_connect</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'my_user'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'my_password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'my_db'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// نمط كائني التوجه</span><span class="pln">
$conn</span><span class="pun">-&gt;</span><span class="pln">set_charset</span><span class="pun">(</span><span class="str">'utf8mb4'</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// نمط إجرائي</span><span class="pln">
mysqli_set_charset</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> </span><span class="str">'utf8mb4'</span><span class="pun">);</span></pre>

<ul>
	<li>
		يمكنك استدعاء الدالة <a href="http://www.php.net/manual/en/function.mysql-set-charset.php" rel="external nofollow"><code>mysql_set_charset</code></a> إذا كنت تستخدم <code>MySQL</code> البسيطة وإصدار PHP ≥ 5.2.3.
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_64" style=""><span class="pln">$conn </span><span class="pun">=</span><span class="pln"> mysql_connect</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'my_user'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'my_password'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// نمط كائني التوجه</span><span class="pln">
$conn</span><span class="pun">-&gt;</span><span class="pln">set_charset</span><span class="pun">(</span><span class="str">'utf8mb4'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// نمط إجرائي</span><span class="pln">
mysql_set_charset</span><span class="pun">(</span><span class="pln">$conn</span><span class="pun">,</span><span class="pln"> </span><span class="str">'utf8mb4'</span><span class="pun">);</span></pre>

<ul>
	<li>
		إذا لم يوفر نظام تشغيل قاعدة البيانات آلية خاصة به لضبط ترميز محارف الاتصال، قد تضطر إلى إصدار استعلام لإخبار <code>MySQL</code> عن الطريقة التي يتوقع بها تطبيقك تشفير البيانات عند الاتصال بالشكل: <a href="https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html" rel="external nofollow">SET NAMES 'utf8mb4'</a>‎.
	</li>
</ul>

<h2>
	دعم يونيكود في PHP
</h2>

<h3>
	تحويل محارف يونيكود إلى تنسيق "‎\uxxxx" باستخدام PHP
</h3>

<p>
	يمكنك استخدام الشيفرة التالية للترميز وفك الترميز:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_66" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'codepoint_encode'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> codepoint_encode</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">json_encode</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">),</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'codepoint_decode'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> codepoint_decode</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">sprintf</span><span class="pun">(</span><span class="str">'"%s"'</span><span class="pun">,</span><span class="pln"> $str</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>طريقة الاستخدام</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_68" style=""><span class="pln">echo </span><span class="str">"\\nUse JSON encoding / decoding\\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">codepoint_encode</span><span class="pun">(</span><span class="str">"我好"</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">codepoint_decode</span><span class="pun">(</span><span class="str">'\\u6211\\u597d'</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">Use JSON encoding / decoding
string(12) "\\u6211\\u597d"
string(6) "我好"
</pre>

<h3>
	تحويل محارف يونيكود إلى قيمها الرقمية و/أو كيانات HTML باستخدام PHP
</h3>

<p>
	يمكنك استخدام الشيفرة التالية للترميز وفك الترميز:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_70" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'mb_internal_encoding'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> mb_internal_encoding</span><span class="pun">(</span><span class="pln">$encoding </span><span class="pun">=</span><span class="pln"> NULL</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$from_encoding </span><span class="pun">===</span><span class="pln"> NULL</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> iconv_get_encoding</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> iconv_set_encoding</span><span class="pun">(</span><span class="pln">$encoding</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'mb_convert_encoding'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> mb_convert_encoding</span><span class="pun">(</span><span class="pln">$str</span><span class="pun">,</span><span class="pln"> $to_encoding</span><span class="pun">,</span><span class="pln"> $from_encoding </span><span class="pun">=</span><span class="pln"> NULL</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> iconv</span><span class="pun">((</span><span class="pln">$from_encoding </span><span class="pun">===</span><span class="pln"> NULL</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> mb_internal_encoding</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> $from_encoding</span><span class="pun">,</span><span class="pln">$to_encoding</span><span class="pun">,</span><span class="pln"> $str</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'mb_chr'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> mb_chr</span><span class="pun">(</span><span class="pln">$ord</span><span class="pun">,</span><span class="pln"> $encoding </span><span class="pun">=</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$encoding </span><span class="pun">===</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> pack</span><span class="pun">(</span><span class="str">"N"</span><span class="pun">,</span><span class="pln"> $ord</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> mb_convert_encoding</span><span class="pun">(</span><span class="pln">mb_chr</span><span class="pun">(</span><span class="pln">$ord</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">),</span><span class="pln"> $encoding</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'mb_ord'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> mb_ord</span><span class="pun">(</span><span class="pln">$char</span><span class="pun">,</span><span class="pln"> $encoding </span><span class="pun">=</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$encoding </span><span class="pun">===</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            list</span><span class="pun">(,</span><span class="pln"> $ord</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">$char</span><span class="pun">)</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">@unpack</span><span class="pun">(</span><span class="str">'N'</span><span class="pun">,</span><span class="pln"> $char</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="lit">@unpack</span><span class="pun">(</span><span class="str">'n'</span><span class="pun">,</span><span class="pln"> $char</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> $ord</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> mb_ord</span><span class="pun">(</span><span class="pln">mb_convert_encoding</span><span class="pun">(</span><span class="pln">$char</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">,</span><span class="pln"> $encoding</span><span class="pun">),</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'mb_htmlentities'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> mb_htmlentities</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> $hex </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> $encoding </span><span class="pun">=</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> preg_replace_callback</span><span class="pun">(</span><span class="str">'/[\x{80}-\x{10FFFF}]/u'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$match</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$hex</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> sprintf</span><span class="pun">(</span><span class="pln">$hex </span><span class="pun">?</span><span class="pln"> </span><span class="str">'&amp;#x%X;'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">'&amp;#%d;'</span><span class="pun">,</span><span class="pln"> mb_ord</span><span class="pun">(</span><span class="pln">$match</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]));</span><span class="pln">
        </span><span class="pun">},</span><span class="pln"> $string</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">function_exists</span><span class="pun">(</span><span class="str">'mb_html_entity_decode'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> mb_html_entity_decode</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> $flags </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> $encoding </span><span class="pun">=</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> html_entity_decode</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$flags </span><span class="pun">===</span><span class="pln"> NULL</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> ENT_COMPAT </span><span class="pun">|</span><span class="pln"> ENT_HTML401 </span><span class="pun">:</span><span class="pln"> $flags</span><span class="pun">,</span><span class="pln">$encoding</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>طريقة الاستخدام</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_72" style=""><span class="pln">echo </span><span class="str">"Get string from numeric DEC value\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_chr</span><span class="pun">(</span><span class="lit">50319</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_chr</span><span class="pun">(</span><span class="lit">271</span><span class="pun">));</span><span class="pln">

echo </span><span class="str">"\nGet string from numeric HEX value\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_chr</span><span class="pun">(</span><span class="lit">0xC48F</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_chr</span><span class="pun">(</span><span class="lit">0x010F</span><span class="pun">));</span><span class="pln">

echo </span><span class="str">"\nGet numeric value of character as DEC string\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_ord</span><span class="pun">(</span><span class="str">'ď'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_ord</span><span class="pun">(</span><span class="str">'ď'</span><span class="pun">));</span><span class="pln">

echo </span><span class="str">"\nGet numeric value of character as HEX string\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">dechex</span><span class="pun">(</span><span class="pln">mb_ord</span><span class="pun">(</span><span class="str">'ď'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UCS-4BE'</span><span class="pun">)));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">dechex</span><span class="pun">(</span><span class="pln">mb_ord</span><span class="pun">(</span><span class="str">'ď'</span><span class="pun">)));</span><span class="pln">

echo </span><span class="str">"\nEncode / decode to DEC based HTML entities\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_htmlentities</span><span class="pun">(</span><span class="str">'tchüß'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_html_entity_decode</span><span class="pun">(</span><span class="str">'tchüß'</span><span class="pun">));</span><span class="pln">

echo </span><span class="str">"\nEncode / decode to HEX based HTML entities\n"</span><span class="pun">;</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_htmlentities</span><span class="pun">(</span><span class="str">'tchüß'</span><span class="pun">));</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">mb_html_entity_decode</span><span class="pun">(</span><span class="str">'tchüß'</span><span class="pun">));</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">Get string from numeric DEC value
string(4) "ď"
string(2) "ď"

Get string from numeric HEX value
string(4) "ď"
string(2) "ď"

Get numeric value of character as DEC int
int(50319)
int(271)

Get numeric value of character as HEX string
string(4) "c48f"
string(3) "10f"

Encode / decode to DEC based HTML entities
string(15) "tch&amp;#252;&amp;#223;"
string(7) "tchüß"

Encode / decode to HEX based HTML entities
string(15) "tch&amp;#xFC;&amp;#xDF;"
string(7) "tchüß"
</pre>

<h3>
	استخدام الإضافة Intl لدعم يونيكود
</h3>

<p>
	تُربط دوال السلسلة النصية الأصلية إلى دوال البايت المفرد ولا تعمل بشكلٍ جيد مع ترميز يونيكود (unicode)، توفر الإضافات <code>iconv</code> و<code>mbstring</code> بعض الدعم لترميز يونيكود بينما توفر الإضافة <code>Intl</code> الدعم الكامل. تعدّ الإضافة <code>Intl</code> مغلّفة للمعيار المعتمد لمكتبة ICU (‏International Components for unicode)، يمكنك الاطلاع على <a href="http://site.icu-project.org" rel="external nofollow">الموقع</a> لمعرفة المزيد من المعلومات التفصيلية غير الموجودة <a href="https://www.php.net/manual/en/book.intl.php" rel="external nofollow">هنا</a>. اطّلع على <a href="https://github.com/symfony/symfony/blob/3.2/src/Symfony/Component/Intl/Intl.php" rel="external nofollow">تنفيذ بديل للإضافة Intl من بيئة العمل Symfony</a> إذا لم تتمكن من تثبيت الإضافة.
</p>

<p>
	توفر ICU تدويلًا كاملًا وترميز يونيكود هو جزء صغير منه، يمكنك التحويل بسهولة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_74" style=""><span class="com">// إزالة البايتات السيئة للحماية من الهجمات</span><span class="pln">
\U</span><span class="typ">Converter</span><span class="pun">::</span><span class="pln">transcode</span><span class="pun">(</span><span class="pln">$sString</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'UTF-8'</span><span class="pun">);</span></pre>

<p>
	لكن يجب ألا تتخلى عن الإضافة <code>iconv</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_595_76" style=""><span class="pln">\iconv</span><span class="pun">(</span><span class="str">'UTF-8'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'ASCII//TRANSLIT'</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Cliënt"</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// "Client"</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [File handling - Streams - UTF-8 - Unicode Support in PHP] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%B1%D8%B4%D8%AD%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%B1%D8%B4%D8%AD-filter-%D8%A7%D9%84%D9%85%D8%B9%D9%82%D9%85%D8%A9-%D9%81%D9%8A-php-r1126/" rel="">المرشحات ودوال المرشح (Filter) المعقمة في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%A7%D9%84%D8%B3%D8%AD%D8%B1%D9%8A%D8%A9-magic-methods-%D9%81%D9%8A-php-r1124/" rel="">التوابع السحرية (Magic Methods) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1125</guid><pubDate>Wed, 17 Feb 2021 13:02:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x648;&#x627;&#x628;&#x639; &#x627;&#x644;&#x633;&#x62D;&#x631;&#x64A;&#x629; (Magic Methods) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%A7%D9%84%D8%B3%D8%AD%D8%B1%D9%8A%D8%A9-magic-methods-%D9%81%D9%8A-php-r1124/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/3.png.a17b4f7a26ae79dba6dd62b1aea639a2.png" /></p>

<h2>
	‎call()‎__ و‎callStatic()‎__
</h2>

<p>
	يُستدعى التابعين <code>‎__call()‎</code> و<code>‎__callStatic()‎</code> عندما تريد استدعاء تابع كائن غير موجود في سياق تابع أو سياق ساكن.
</p>

<p>
	في الشيفرة التالية يُستدعى التابع <code>‎__call()‎</code> عندما يحاول شخص ما استدعاء تابع في سياق كائن غير موجود مثل <code>‎$foo-&gt;method($arg, $arg1);‎</code>، سيحتوي الوسيط الأول على اسم التابع وهو <code>method</code> في مثالنا وسيحتوي الوسيط الثاني على قيم <code>‎$arg</code> و<code>‎$arg1</code> كمصفوفة.
</p>

<p>
	ويُستدعى التابع <code>‎__callStatic()‎</code> من محتوى ساكن عند استدعاء تابع ساكن غير موجود، مثلًا <code>Foo::buildSomethingCool($arg);‎</code>، سيحتوي الوسيط الأول على اسم التابع وهو <code>buildSomethingCool</code> في مثالنا ويحتوي الوسيط الثاني على قيمة <code>‎$arg</code> في مصفوفة. لاحظ أنّ بصمة هذا التابع مختلفة (يتطلب الكلمة المفتاحية static)، هذا التابع لم يكن موجودًا قبل الإصدار PHP 5.3.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_7" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __call</span><span class="pun">(</span><span class="pln">$method</span><span class="pun">,</span><span class="pln"> $arguments</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (1)</span><span class="pln">
        $snakeName </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CaseHelper</span><span class="pun">::</span><span class="pln">camelToSnake</span><span class="pun">(</span><span class="pln">$method</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// الحصول على البادئة</span><span class="pln">
        $subMethod </span><span class="pun">=</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$snakeName</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// إسقاط اسم التابع</span><span class="pln">
        $propertyName </span><span class="pun">=</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$snakeName</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$subMethod</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">case</span><span class="pln"> </span><span class="str">"get"</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$propertyName</span><span class="pun">];</span><span class="pln">
            </span><span class="kwd">case</span><span class="pln"> </span><span class="str">"set"</span><span class="pun">:</span><span class="pln">
                $this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$propertyName</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $arguments</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
                </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">case</span><span class="pln"> </span><span class="str">"has"</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$propertyName</span><span class="pun">]);</span><span class="pln">
            </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">BadMethodCallException</span><span class="pun">(</span><span class="str">"Undefined method $method"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __callStatic</span><span class="pun">(</span><span class="pln">$method</span><span class="pun">,</span><span class="pln"> $arguments</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// يمكن استخدام هذا التابع عندما تحتاج شيء ما مثل مصنع عام أو شيء ما آخر</span><span class="pln">
        print_r</span><span class="pun">(</span><span class="pln">func_get_args</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) نفعل شيء ما مع المعلومات مثل زيادة التحميل أو شيء عام، فمثلًا لنفرض أننا نكتب صنفًا عامًا يحمل بعض البيانات ويسمح للمستخدم بأن يجلبها ويضبطها باستخدام التوابع الجالب والضابط، وكان لدينا الصنف <code>CaseHelper</code> يساعد على تحويل نمط سنام الجمل (camelCase) إلى نمط الثعبان (snake_case). هذا التابع مبسّط لذا لا يتحقق من صلاحية الاسم أو عدمها.
</p>

<p>
	<strong>مثال:</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_9" style="">
<span class="pln">$instance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">();</span><span class="pln">
$instance</span><span class="pun">-&gt;</span><span class="pln">setSomeState</span><span class="pun">(</span><span class="str">"foo"</span><span class="pun">);</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">$instance</span><span class="pun">-&gt;</span><span class="pln">hasSomeState</span><span class="pun">());</span><span class="pln"> </span><span class="com">// bool(true)</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$instance</span><span class="pun">-&gt;</span><span class="pln">getSomeState</span><span class="pun">());</span><span class="pln"> </span><span class="com">// string "foo"</span><span class="pln">

</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln">exampleStaticCall</span><span class="pun">(</span><span class="str">"test"</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
Array
(
    [0] =&gt; exampleCallStatic
    [1] =&gt; test
)
*/</span></pre>

<h2>
	‎get()‎__ و‎__set()‎ و‎__isset()‎ و‎__unset()‎
</h2>

<p>
	كلما حاولت استعادة حقل معين من صنف كما في الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_11" style="">
<span class="pln">$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">();</span><span class="pln">
$height </span><span class="pun">=</span><span class="pln"> $animal</span><span class="pun">-&gt;</span><span class="pln">height</span><span class="pun">;</span></pre>

<p>
	تستدعي PHP التابع السحري <code>‎__get($name)‎</code> ويكون <code>‎$name</code> هو "height" في حالتنا. كتابة حقل ما من الصنف كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_13" style="">
<span class="pln">$animal</span><span class="pun">-&gt;</span><span class="pln">height </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span></pre>

<p>
	ستستدعي التابع السحري <code>‎__set($name, $value),‎</code> ويكون <code>‎$name</code> هو "height" و<code>‎$value</code> هو 10.
</p>

<p>
	لدينا في PHP أيضًا تابعين مدمجين هما <code>‎isset()‎</code> الذي يتحقق من وجود متغير، و<code>unset‎()‎</code> الذي يدمر متغير.
</p>

<p>
	إنّ الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_15" style="">
<span class="pln">isset</span><span class="pun">(</span><span class="pln">$animal</span><span class="pun">-&gt;</span><span class="pln">height</span><span class="pun">);</span></pre>

<p>
	ستستدعي الدالة <code>‎__isset($name)‎</code> على ذلك الكائن، كما أنّ إزالة تعيين متغير كما في الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_17" style="">
<span class="pln">unset</span><span class="pun">(</span><span class="pln">$animal</span><span class="pun">-&gt;</span><span class="pln">height</span><span class="pun">);</span></pre>

<p>
	ستستدعي الدالة <code>‎__unset($name)‎</code> على ذلك الكائن.
</p>

<p>
	تستعيد PHP الحقل كما هو مخزن في الصنف عندما لاتعرّف هذه التوابع في صنفك، لكن يمكنك تجاوز هذه التوابع لإنشاء أصناف يمكنها أن تحمل بيانات مثل المصفوفة لكنها قابلة للاستخدام ككائن:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_19" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $data </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __set</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">,</span><span class="pln"> $value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$name</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $value</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __get</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">array_key_exists</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">,</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$name</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __isset</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$name</span><span class="pun">]);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __unset</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        unset</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="pln">$name</span><span class="pun">]);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$example </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">();</span><span class="pln">

</span><span class="com">// وقيمتها 15 $data في المصفوفة 'a' تخزين</span><span class="pln">
$example</span><span class="pun">-&gt;</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">15</span><span class="pun">;</span><span class="pln">

</span><span class="com">// $data من المصفوفة 'a' استعادة مفتاح المصفوفة</span><span class="pln">
echo $example</span><span class="pun">-&gt;</span><span class="pln">a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 15</span><span class="pln">

</span><span class="com">// null محاولة استعادة مفتاح غير موجود في المصفوفة تُعيد</span><span class="pln">
echo $example</span><span class="pun">-&gt;</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
</span><span class="com">// لا يطبع شيء</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$example</span><span class="pun">-&gt;</span><span class="pln">a</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    unset</span><span class="pun">(</span><span class="pln">$example</span><span class="pun">-&gt;</span><span class="pln">a</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الدالة empty()‎‍ والتوابع السحرية</strong><br>
	لاحظ أنّ استدعاء الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/empty" rel="">empty()‎</a> على خاصيّة صنف ستستدعي الدالة <code>‎__isset($name)‎</code> حسب ما ورد في توثيق PHP: <code>‏empty()‎</code> هي المكافئ المختصر للشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_21" style="">
<span class="pun">!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$var</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> $var </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">false</span></pre>

<h2>
	‎__construct()‎ و‎__destruct()‎
</h2>

<p>
	<code>‎__construct()‎</code> هو التابع السحري الأشهر في PHP لأنّه يُستخدم لضبط صنف عند تهيئته، أما التابع العكسي له <code>‎__destruct()‎</code> فإنّه يُستدعى عندما لا يوجد مراجع متبقية للكائن الذي أنشأته أو عندما تفرض حذفه وعندها ستقوم مجموعة المهملات بتنظيف الكائن عن طريق استدعاء الهادم أولًا ثمّ حذفه من الذاكرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_23" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"Shape created!\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $width</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $height</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$width</span><span class="pun">,</span><span class="pln"> $height</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        parent</span><span class="pun">::</span><span class="pln">__construct</span><span class="pun">();</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">width </span><span class="pun">=</span><span class="pln"> $width</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">height </span><span class="pun">=</span><span class="pln"> $height</span><span class="pun">;</span><span class="pln">
        echo </span><span class="str">"Created {$this-&gt;width}x{$this-&gt;height} Rectangle\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __destruct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"Destroying {$this-&gt;width}x{$this-&gt;height} Rectangle\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> createRectangle</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    $rectangle </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pun">(</span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// (2)</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

createRectangle</span><span class="pun">();</span><span class="pln">
</span><span class="com">// (3)</span><span class="pln">

</span><span class="com">// (4)</span><span class="pln">
unset</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pun">(</span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">));</span></pre>

<p>
	في الموضع (1) ستستدعي تهيئة الكائن الباني مع الوسطاء المحددين.
</p>

<p>
	في الموضع (2) سيُطبع 'Shape Created' ثم 'Created 20x50 Rectangle'.
</p>

<p>
	في الموضع (3) سيُطبع 'Destroying 20x50 Rectangle' لأنّ الكائن <code>‎$rectangle</code> هو كائن محلي بالنسبة للدالة <code>createRectangle</code> لذا عندما ينتهي نطاق الدالة سيُدمَّر الكائن ويُستدعى هادمه.
</p>

<p>
	في الموضع (4) سيُستدعى هادم الكائن عند استخدام الدالة <code>unset</code>.
</p>

<h2>
	‎__toString()‎
</h2>

<p>
	يُستدعى التابع <code>‎__toString()‎</code> عندما يُعامل الكائن على أنّه سلسلة نصية، ويعيد سلسلة نصية تمثّل الصنف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_25" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">User</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $first_name</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $last_name</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $age</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __toString</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"{$this-&gt;first_name} {$this-&gt;last_name} ($this-&gt;age)"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$user </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">User</span><span class="pun">();</span><span class="pln">
$user</span><span class="pun">-&gt;</span><span class="pln">first_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Chuck"</span><span class="pun">;</span><span class="pln">
$user</span><span class="pun">-&gt;</span><span class="pln">last_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Norris"</span><span class="pun">;</span><span class="pln">
$user</span><span class="pun">-&gt;</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">76</span><span class="pun">;</span><span class="pln">

</span><span class="com">// في سياق سلسلة $user كلما اُستخدم الكائن‏ __toString() سيُستدعى التابع‏‏</span><span class="pln">
echo $user</span><span class="pun">;</span><span class="pln">
</span><span class="com">// Chuck Norris (76)</span><span class="pln">

</span><span class="com">// Selected user: Chuck Norris (76) :أصبحت قيمة السلسلة النصية</span><span class="pln">
$selected_user_string </span><span class="pun">=</span><span class="pln"> sprintf</span><span class="pun">(</span><span class="str">"Selected user: %s"</span><span class="pun">,</span><span class="pln"> $user</span><span class="pun">);</span><span class="pln">

</span><span class="com">// __toString() التحويل إلى سلسلة نصية يستدعي أيضًا</span><span class="pln">
$user_as_string </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">string</span><span class="pun">)</span><span class="pln"> $user</span><span class="pun">;</span></pre>

<h2>
	‎__clone()‎
</h2>

<p>
	يُستدعَى التابع <code>‎__clone</code> باستخدام الكلمة المفتاحية <code>clone</code>، ويستخدم لمعالجة حالة كائن عند النسخ بعد أن يكون الكائن قد نُسخَ فعلًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_27" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">CloneableUser</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $lastName</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// "Copy " سيُستدعى هذا التابع بعامل النسخ ويضيف قبل خاصيّات‏‏‏ الاسم والاسم الأخير الكلمة‏</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __clone</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Copy "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">lastName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Copy "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">lastName</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_29" style="">
<span class="pln">$user1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CloneableUser</span><span class="pun">();</span><span class="pln">
$user1</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"John"</span><span class="pun">;</span><span class="pln">
$user1</span><span class="pun">-&gt;</span><span class="pln">lastName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Doe"</span><span class="pun">;</span><span class="pln">

</span><span class="com">//  __clone تنفيذ التابع السحري</span><span class="pln">
$user2 </span><span class="pun">=</span><span class="pln"> clone $user1</span><span class="pun">;</span><span class="pln"> 

echo $user2</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Copy John</span><span class="pln">
echo $user2</span><span class="pun">-&gt;</span><span class="pln">lastName</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Copy Doe</span></pre>

<h2>
	‎__invoke()‎
</h2>

<p>
	يُستدعى هذا التابع السحري عندما يحاول المستخدم استدعاء كائن كدالة، قد تتضمن حالات الاستخدام الممكنة بعض الطرق مثل البرمجة الوظيفية أو بعض ردود النداء.
</p>

<p>
	سيُستدعى التابع في الشيفرة التالية إذا نُفِّذ الكائن كدالة: <code>‎$invokable();‎</code> وستمرر الوسائط كما في استدعاء التابع العادي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_31" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Invokable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __invoke</span><span class="pun">(</span><span class="pln">$arg</span><span class="pun">,</span><span class="pln"> $arg</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        print_r</span><span class="pun">(</span><span class="pln">func_get_args</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_33" style="">
<span class="pln">$invokable </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Invokable</span><span class="pun">();</span><span class="pln">
$invokable</span><span class="pun">([</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">]);</span><span class="pln">

</span><span class="com">/*
Array
(
    [0] =&gt; 1
    [1] =&gt; 2
    [2] =&gt; 3
)
*/</span></pre>

<h2>
	‎⁠__sleep()‎ و‎__wakeup()‎
</h2>

<p>
	يرتبط التابعان <code>‎__sleep</code> و<code>‎__wakeup</code> بعملية السَلسَلة، تتحقق الدالة <code>serialize</code> إذا كان للصنف تابع <code>‎__sleep‎</code>، إذا كان موجودًا سيُنفَّذ قبل أي سَلسَلة ويُفترض أن يعيد مصفوفة من أسماء كل المتغيرات للكائن الذي يجب أن يُسلسَل.
</p>

<p>
	وسيُنفَّذ التابع <code>‎__wakeup</code> بدوره من قبل الدالة <code>unserialize</code> إذا وُجد في الصنف، ويهدف إلى إعادة إنشاء الموارد والأشياء الأخرى التي نحتاج تهيئتها بعد إلغاء التسلسل.
</p>

<p>
	في الشيفرة التالية سيُنفَّذ التابع السحري <code>‎__sleep</code> من قِبل الدالة <code>serialize</code> ولاحظ أنّ <code>‎$dbConnection</code> مُستبعد، وسيُنفَّذ التابع السحري <code>‎__wakeup</code> من قِبل الدالة <code>unserialize</code>، لنفرض مثلًا أنّ <code>‎$this-&gt;c</code> الذي لم يُسَلسَل هو نوع من الاتصال بقاعدة البيانات سيُعيد الاتصال عندما نستخدم تابع الاستيقاظ.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_35" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Sleepy</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $tableName</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $tableFields</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $dbConnection</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __sleep</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// فقط $this-&gt;tableNameو $this-&gt;tableFields سيُسَلسَل</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="str">'tableName'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tableFields'</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __wakeup</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// الاتصال بقاعدة البيانات الافتراضية وتخزين المُعالج/المُغلِّف فيها</span><span class="pln">
        </span><span class="com">// $this-&gt;dbConnection</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">dbConnection </span><span class="pun">=</span><span class="pln"> DB</span><span class="pun">::</span><span class="pln">connect</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	‎__debugInfo()‎
</h2>

<p>
	يُستدعى هذا التابع من قِبل الدالة <code>var_dump()‎</code> عند تفريغ كائن للحصول على الخاصيّات التي يجب عرضها، إذا لم يُعرَّف التابع على الكائن ستُعرَض كل الخاصيّات العامة والمحمية والخاصة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_37" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">DeepThought</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __debugInfo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="lit">42</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار PHP ≤ 5.6</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_39" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DeepThought</span><span class="pun">());</span></pre>

<p>
	خرج الشيفرة السابقة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_41" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">DeepThought</span><span class="com">#1 (0) {</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار PHP ≥ 5.6</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_43" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DeepThought</span><span class="pun">());</span></pre>

<p>
	خرج الشيفرة السابقة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4229_45" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">DeepThought</span><span class="com">#1 (1) {</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $</span><span class="pun">{</span><span class="lit">0</span><span class="pun">}</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="kwd">int</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصل [Magic Methods] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%85%D8%B2%D8%A9-%D8%A8%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-utf-8-%D9%81%D9%8A-php-r1125/" rel="">معالجة الملفات والبيانات المرمزة بترميز UTF-8 في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/" rel="">مدخل إلى الملحن composer: مدير الاعتماديات والحزم في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1124</guid><pubDate>Mon, 15 Feb 2021 13:07:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x627;&#x644;&#x645;&#x644;&#x62D;&#x646; composer: &#x645;&#x62F;&#x64A;&#x631; &#x627;&#x644;&#x627;&#x639;&#x62A;&#x645;&#x627;&#x62F;&#x64A;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x62D;&#x632;&#x645; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/2.png.8a710b777f1945503027f92d222fa8c7.png" /></p>

<p>
	<a href="https://ar.wikipedia.org/wiki/%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86_(%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9)" rel="external nofollow">الملحِّن</a> أو composer (كومبوزر) هو مدير حزم/اعتماديات PHP، يمكن استخدامه لتثبيت وتتبع وتحديث اعتماديات مشروعك، ويهتم أيضًا بالتحميل التلقائي للاعتماديات التي يعتمد عليها تطبيقك مما يجعلك تستخدم الاعتمادية بسهولة داخل مشروعك دون القلق بشأن تضمينها في بداية كل ملف.
</p>

<p>
	يعدّ المُلحِّن <a href="https://getcomposer.org/" rel="external nofollow">composer</a> أشهر مدير اعتمادية، وهو يماثل <code>npm</code> في <code>Node</code> و<code>pip</code> في <code>Python</code> و<code>NuGet</code> في <code>‎.NET</code>.
</p>

<p>
	توجد اعتماديات مشروعك ضمن ملف <code>composer.json</code> الموجود عادةً في جذر المشروع، ويحمل هذا الملف معلومات الإصدارات المطلوبة للحزم في مرحلتي تطوير المشروع وإنتاجه، يمكن تعديل هذا الملف بشكلٍ يدوي باستخدام أي محرر نصوص أو تلقائيًا باستخدام أوامر سطر الأوامر مثل <code>composer require &lt;package&gt;‎</code> أو <code>composer require-dev &lt;package&gt;‎</code>.
</p>

<p>
	تحتاج لبدء استخدام المُحلِّن في مشروعك إلى إنشاء ملف <code>composer.json</code>، يمكنك إنشاؤه يدويًا أو بتنفيذ الأمر <code>composer init</code> وبعد تنفيذ هذا الأمر في الطرفية ستسألك عن بعض المعلومات الأساسية لمشروعك: اسم الحزمة (vendor/package مثل laravel/laravel) - الوصف وهو اختياري - الكاتب وبعض المعلومات الأخرى مثل حد الاستقرار الأدنى والرخصة والحزم المطلوبة.
</p>

<p>
	يصف المفتاح <code>require</code> في ملف <code>composer.json</code> الحزم التي يعتمد عليها مشروعك، ويأخذ كائنًا يربط اسم الحزمة (مثل monolog/monolog) بقيود الإصدار (مثل ‎1.0.*‎).
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7834_14" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="str">"require"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"composer/composer"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"1.2.*"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تحتاج لتثبيت الاعتماديات المعرّفة إلى تنفيذ الأمر <code>composer install</code> ثم يجد composer الحزم المعرّفة المطابقة لقيد <code>version</code> الموجود ويحمّلها في مجلد <code>vendor</code>، هذا اصطلاح لوضع شيفرة من طرف ثالث في مجلد اسمه <code>vendor</code>.
</p>

<p>
	ستلاحظ أنّ الأمر <code>install</code> يُنشئ الملف <code>composer.lock</code> تلقائيًا، يستخدم هذا الملف لتتبع الإصدارات المنصَّبة حاليًا وحالة اعتمادياتك، وسيثبّت تنفيذ الأمر <code>composer install</code> الحزم إلى الحالة المخزّنة في ملف القفل.
</p>

<table><tbody>
<tr>
<td>
				المعامل
			</td>
			<td>
				تفاصيل
			</td>
		</tr>
<tr>
<td>
				license
			</td>
			<td>
				يعرّف نوع الرخصة التي تريد استخدامها في المشروع
			</td>
		</tr>
<tr>
<td>
				authors
			</td>
			<td>
				يعرّف كاتبي المشروع وتفاصيل عنهم
			</td>
		</tr>
<tr>
<td>
				support
			</td>
			<td>
				يعرّف البريد الإلكتروني للدعم وقناة الدردشة على الإنترنت والروابط المختلفة
			</td>
		</tr>
<tr>
<td>
				require
			</td>
			<td>
				يعرّف الاعتماديات الفعلية بالإضافة إلى إصدارات الحزمة
			</td>
		</tr>
<tr>
<td>
				require-dev
			</td>
			<td>
				يعرّف الحزم الضرورية لتطوير المشروع
			</td>
		</tr>
<tr>
<td>
				suggest
			</td>
			<td>
				يعرّف اقتراحات الحزمة، مثال الحزم التي تساعد في التثبيت
			</td>
		</tr>
<tr>
<td>
				autoload
			</td>
			<td>
				يعرّف سياسات التحميل التلقائي للمشروع
			</td>
		</tr>
<tr>
<td>
				autoload-dev
			</td>
			<td>
				يعرّف سياسات التحميل التلقائي لتطوير المشروع
			</td>
		</tr>
</tbody></table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<h2>
	التحميل التلقائي مع المحلن
</h2>

<p>
	بينما يوفر المُلحِّن نظامًا لإدارة اعتماديات مشروعك من <a href="%E2%80%8Fhttps://packagist.org/%E2%80%8F" rel="">Packagist</a> مثلًا، يمكن أن يعمل أيضًا كمحمّل تلقائي يصف أين يبحث عن فضاء أسماء محددة أو يضمّن ملفات الدوال العامة.
</p>

<p>
	يبدأ مع ملف <code>composer.json</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7834_16" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="str">"autoload"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"psr-4"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="str">"MyVendorName\\MyProject"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"src/"</span><span class="pln">
        </span><span class="pun">},</span><span class="pln">
        </span><span class="str">"files"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            </span><span class="str">"src/functions.php"</span><span class="pln">
        </span><span class="pun">]</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
    </span><span class="str">"autoload-dev"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"psr-4"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="str">"MyVendorName\\MyProject\\Tests"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"tests/"</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تضمن شيفرة الإعداد هذه أنّ كل الأصناف في فضاء الاسم <code>MyVendorName\MyProject</code> رُبطت إلى مجلد <code>src</code> وكل الأصناف في <code>MyVendorName\MyProject\Tests</code> رُبطت إلى مجلد <code>tests</code> (نسبةً إلى المجلد الجذر) وسيضمّن تلقائيًا ملف <code>functions.php</code>.
</p>

<p>
	بعد إضافة هذا الإعداد إلى ملف <code>composer.json</code> ننفذ الأمر <code>composer update</code> في الطرفية ليحدّث المُحلِّن الاعتماديّات وملف القفل ويولّد ملف <code>autoload.php</code>، ستستخدم عند النشر إلى بيئة الإنتاج الأمر <code>install --no-dev</code>، ويمكن إيجاد ملف <code>autoload.php</code> في مجلد <code>vendor</code> الذي يجب أن يتولّد في نفس المجلد الموجود به <code>composer.json</code>، ويجب تضمينه مبكرًا عند نقطة إعداد في دورة حياة تطبيقك باستخدام سطر مشابه للتالي:
</p>

<pre class="ipsCode">
require_once __DIR__ . '/vendor/autoload.php';
</pre>

<p>
	بعد التضمين سيهتم ملف <code>autoload.php</code> بتحميل كل الاعتماديّات المذكورة في ملف <code>composer.json</code>.
</p>

<p>
	بعض أمثلة ربط مسار الصنف بالمجلد:
</p>

<pre class="ipsCode">
MyVendorName\MyProject\Shapes\Square ➔ src/Shapes/Square.php.

MyVendorName\MyProject\Tests\Shapes\Square ➔ tests/Shapes/Square.php.
</pre>

<h2>
	الفرق بين 'composer install' و'composer update'
</h2>

<h3>
	composer update
</h3>

<p>
	يحدّث هذا الأمر الاعتماديات المحددة في ملف <code>composer.json</code>، فإذا كان المشروع يستخدم هذا الإعداد مثلًا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7834_18" style="">
<span class="str">"require"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"laravelcollective/html"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"2.0.*"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بفرض كان الإصدار 2.0.1 لهذه الحزمة مثبتًا، سيؤدي تنفيذ الأمر <code>composer update</code> إلى ترقية هذه الحزمة (إلى 2.0.2 مثلًا إذا كانت قد أُصدرت)، أي أنّ هذا الأمر سوف:
</p>

<ul>
<li>
		يقرأ ملف <code>composer.json</code>
	</li>
	<li>
		يزيل الحزم المثبتة التي لم تعد مطلوبة في <code>composer.json</code>
	</li>
	<li>
		يتحقق من توافرية الإصدارات الأخيرة من الحزم المطلوبة
	</li>
	<li>
		يوفر الإصدارات الأخيرة من الحزم
	</li>
	<li>
		يحدّث ملف <code>composer.lock</code> لتخزين إصدار الحزم المثبتة
	</li>
</ul>
<h3>
	composer install
</h3>

<p>
	سيثبت الأمر <code>composer install</code> كل الاعتماديات المحددة في ملف <code>composer.lock</code> وفقًا للنسخة المحددة دون تحديث أي شيء، أي أنّ هذا الأمر:
</p>

<ul>
<li>
		يقرأ ملف <code>composer.lock</code>
	</li>
	<li>
		ينصّب الحزم المحددة في ملف <code>composer.lock</code>
	</li>
</ul>
<p>
	متى تثبِّت ومتى نحدِّث؟ نستخدم <code>composer update</code> غالبًا في مرحلة التطوير لتحديث حزم المشروع ونستخدم <code>composer install</code> بشكلٍ أساسي في مرحلة النشر لتثبيت التطبيق على خادم الإنتاج أو على بيئة الاختبار باستخدام نفس الاعتماديات المخزنة في ملف <code>composer.lock</code> المُنشأ من قِبل <code>composer update</code>.
</p>

<h2>
	أوامر المحلن composer المتاحة
</h2>

<table><tbody>
<tr>
<td>
				الأمر
			</td>
			<td>
				الاستخدام
			</td>
		</tr>
<tr>
<td>
				about
			</td>
			<td>
				معلومات قليلة حول المُحلِّن
			</td>
		</tr>
<tr>
<td>
				archive
			</td>
			<td>
				ينشئ أرشيفًا من حزم المُحلِّن
			</td>
		</tr>
<tr>
<td>
				browse
			</td>
			<td>
				يفتح رابط مستودع الحزمة أو الصفحة الرئيسية في المتصفح
			</td>
		</tr>
<tr>
<td>
				clear-cache
			</td>
			<td>
				يمسح ذاكرة التخزين المؤقت الداخلية للمُلحِّن
			</td>
		</tr>
<tr>
<td>
				clear-cache
			</td>
			<td>
				يمسح ذاكرة التخزين المؤقت الداخلية للمُلحِّن
			</td>
		</tr>
<tr>
<td>
				config
			</td>
			<td>
				يضبط خيارات الإعداد
			</td>
		</tr>
<tr>
<td>
				create-project
			</td>
			<td>
				ينشئ مشروعًا جديدًا من حزمة في المجلد المحدد
			</td>
		</tr>
<tr>
<td>
				depends
			</td>
			<td>
				يعرض الحزم التي تتسبب في تثبيت الحزمة الحالية
			</td>
		</tr>
<tr>
<td>
				diagnose
			</td>
			<td>
				يشخّص النظام لتحديد الأخطاء المعروفة
			</td>
		</tr>
<tr>
<td>
				dump-autoload
			</td>
			<td>
				يفرّغ المحمّل التلقائي
			</td>
		</tr>
<tr>
<td>
				dumpautoload
			</td>
			<td>
				يفرّغ المحمّل التلقائي
			</td>
		</tr>
<tr>
<td>
				exec
			</td>
			<td>
				ينفّذ سكربت/ثنائي مقدم
			</td>
		</tr>
<tr>
<td>
				global
			</td>
			<td>
				($COMPOSER_HOME) يسمح بتنفيذ الأوامر في مجلد المُلحِّن العام
			</td>
		</tr>
<tr>
<td>
				help
			</td>
			<td>
				يعرض المساعدة لأمر ما
			</td>
		</tr>
<tr>
<td>
				home
			</td>
			<td>
				يفتح رابط مستودع الحزمة أو الصفحة الرئيسية في المتصفح
			</td>
		</tr>
<tr>
<td>
				info
			</td>
			<td>
				يعرض معلومات الحزم
			</td>
		</tr>
<tr>
<td>
				init
			</td>
			<td>
				أساسي في المجلد الحالي composer.json ينشئ ملف
			</td>
		</tr>
<tr>
<td>
				install
			</td>
			<td>
				composer.json إذا وجد أو يعود إلى composer.lock ينصّب اعتماديات المشروع من
			</td>
		</tr>
<tr>
<td>
				licenses
			</td>
			<td>
				يعرض معلومات رِخص الاعتماديات
			</td>
		</tr>
<tr>
<td>
				list
			</td>
			<td>
				يعرض الأوامر في قائمة
			</td>
		</tr>
<tr>
<td>
				outdated
			</td>
			<td>
				يعرض قائمة بالحزم المنصّبة والتي تتوفر تحديثات لها مع إصدارها الأخيرة
			</td>
		</tr>
<tr>
<td>
				prohibits
			</td>
			<td>
				يعرض الحزم التي تمنع تثبيت الحزمة الحالية
			</td>
		</tr>
<tr>
<td>
				remove
			</td>
			<td>
				‏require-dev أو requireيزيل حزمة من
			</td>
		</tr>
<tr>
<td>
				require
			</td>
			<td>
				وينصّبها composer.json يضيف الحزم المطلوبة إلى
			</td>
		</tr>
<tr>
<td>
				run-script
			</td>
			<td>
				composer.json ينفّذ السكربتات المعرفة في‏
			</td>
		</tr>
<tr>
<td>
				search
			</td>
			<td>
				يبحث عن الحزم
			</td>
		</tr>
<tr>
<td>
				self-update
			</td>
			<td>
				إلى الإصدار الأخير composer.phar يحدّث‏
			</td>
		</tr>
<tr>
<td>
				selfupdate
			</td>
			<td>
				إلى الإصدار الأخير composer.phar يحدّث‏
			</td>
		</tr>
<tr>
<td>
				show
			</td>
			<td>
				يعرض معلومات حول الحزم
			</td>
		</tr>
<tr>
<td>
				status
			</td>
			<td>
				يعرض قائمة بالحزم المعدّلة محليًا
			</td>
		</tr>
<tr>
<td>
				suggests
			</td>
			<td>
				يعرض اقتراحات الحزم
			</td>
		</tr>
<tr>
<td>
				update
			</td>
			<td>
				‏composer.lock ويحدّث composer.jsonيحدّث الاعتماديات إلى آخر إصدار وفقًا لملف ‏‏‏
			</td>
		</tr>
<tr>
<td>
				validate
			</td>
			<td>
				composer.lock‏و‏ composer.json يتحقق من صحة‏
			</td>
		</tr>
<tr>
<td>
				why
			</td>
			<td>
				يعرض الحزم التي تتسبب في تثبيت الحزمة الحالية
			</td>
		</tr>
<tr>
<td>
				why-not
			</td>
			<td>
				يعرض الحزم التي تمنع تثبيت الحزمة الحالية
			</td>
		</tr>
</tbody></table>
<h2>
	فوائد استخدام الملحن composer
</h2>

<p>
	يتتبع المُحلِّن إصدارات الحزم المنصّبة في ملف يسمّى <code>composer.lock</code> والذي يهدف إلى التحكم في الإصدار، لذا عندما يُنسخ مشروعك مستقبلًا فإنّ تنفيذ الأمر <code>composer install</code> سينصّب ويحمّل كل اعتماديات المشاركة.
</p>

<p>
	يتعامل المُلحِّن composer مع اعتماديات PHP على أساس المشروع، مما يجعل من السهل وجود عدة مشاريع على جهاز واحد يعتمد على إصدارات منفصلة لحزمة PHP واحدة.
</p>

<p>
	يتتبع المُحلِّن الاعتماديات المخصصة لبيئات التطوير فقط.
</p>

<pre class="ipsCode">
composer require --dev phpunit/phpunit
</pre>

<p>
	يوفر المُحلِّن محمّلًا تلقائيًا مما يجعل من السهل أن تبدأ بالعمل مع أي حزمة، مثلًا بعد تثبيت <a href="%E2%80%8Fhttps://github.com/FriendsOfPHP/Goutte" rel="">Goutte</a> باستخدام الأمر <code>‎composer require fabpot/goutte,‎</code> يمكنك البدء مباشرةً باستخدام <code>Goutte</code> في مشروع جديد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7834_20" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">require</span><span class="pln"> __DIR__ </span><span class="pun">.</span><span class="pln"> </span><span class="str">'/vendor/autoload.php'</span><span class="pun">;</span><span class="pln">

$client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Goutte</span><span class="pln">\Client</span><span class="pun">();</span><span class="pln">
</span><span class="com">// Goutte البدء باستخدام</span></pre>

<p>
	يسمح لك المُحلِّن بتحديث مشروعك بسهولة إلى الإصدار الأخير الذي يسمح به <code>composer.json</code> مثل <code>composer update fabpot/goutte</code> أو بتحديث كل من اعتماديات مشروعك: <code>composer update</code>.
</p>

<h2>
	التثبيت
</h2>

<p>
	قد تثبّت المُحلِّن محليًا كجزء من مشروعك أو عامًا كنظام عريض قابل للتنفيذ.
</p>

<h3>
	محليًا
</h3>

<p>
	عن طريق تنفيذ هذه الأوامر في الطرفية:
</p>

<pre class="ipsCode">
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
</pre>

<p>
	للتأكد من صلاحية المنصِّب المحمّل افحصه عبر هذا <a href="https://composer.github.io/pubkeys.html" rel="external nofollow">الرابط</a> ضد SHA-384.
</p>

<p>
	ستؤدي الشيفرة السابقة إلى تحميل <code>composer.phar</code> (ملف أرشيف PHP) إلى المجلد الحالي، ويمكنك الآن تنفيذ الأمر <code>php composer.phar</code> لاستخدام المُلحِّن، مثال:
</p>

<pre class="ipsCode">
php composer.phar install
</pre>

<h3>
	عامًّا
</h3>

<p>
	ضع ملف <code>composer.phar</code> في مجلد يكون جزء من مسارك لاستخدام المُلحِّن بشكلٍ عام.
</p>

<pre class="ipsCode">
mv composer.phar /usr/local/bin/composer
</pre>

<p>
	يمكنك الآن استخدام المُلحِّن في أي مكان بدلًا من <code>php composer.phar</code> مثال:
</p>

<pre class="ipsCode">
composer install
</pre>

<p>
	ترجمة -وبتصرف- للفصل [Composer Dependency Manager] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%A7%D9%84%D8%B3%D8%AD%D8%B1%D9%8A%D8%A9-magic-methods-%D9%81%D9%8A-php-r1124/" rel="">التوابع السحرية (Magic Methods) في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%B3%D9%85%D8%A7%D8%AA-traits-%D9%81%D9%8A-php-r1122/" rel="">مفهوم السمات (Traits) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1123</guid><pubDate>Fri, 12 Feb 2021 13:01:00 +0000</pubDate></item><item><title>&#x645;&#x641;&#x647;&#x648;&#x645; &#x627;&#x644;&#x633;&#x645;&#x627;&#x62A; (Traits) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%B3%D9%85%D8%A7%D8%AA-traits-%D9%81%D9%8A-php-r1122/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_02/1.png.4590ae1e30bceebfe132c82657958b35.png" /></p>

<h2>
	ما هي السمة (Traits)؟
</h2>

<p>
	تسمح PHP بالوراثة المفردة فقط أي أنّ الصنف يمكن أن يرث صنفًا واحدًا فقط، لكن ماذا لو احتجت لتضمين شيء ما لا ينتمي للصنف الأب؟ قبل الإصدار PHP 5.4 كان عليك أن تكون مبدعًا أما الإصدار PHP 5.4 فقد قدم السمات التي تسمح لك بنسخ ولصق جزء من صنف ما إلى الصنف الذي تريده.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_9" style="">
<span class="pln">trait </span><span class="typ">Talk</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/** @var string */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $phrase </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Well Wilbur...'</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> speak</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo $this</span><span class="pun">-&gt;</span><span class="pln">phrase</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MrEd</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Horse</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Talk</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">speak</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setPhrase</span><span class="pun">(</span><span class="pln">$phrase</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">phrase </span><span class="pun">=</span><span class="pln"> $phrase</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لدينا في الشيفرة السابقة الصنف <code>MrEd</code> يوسّع الصنف <code>Horse</code>، لكن ليس كل كائنات الصنف <code>Horse</code> لديها السمة <code>Talk</code>، لنرى ما تأثير ذلك.
</p>

<p>
	نعرّف أولًا السمة (Traits) ويمكننا استخدامها مع التحميل التلقائي وفضاء الأسماء ثمّ نضمنها في الصنف <code>MrEd</code> باستخدام الكلمة المفتاحية <code>use</code>، ستلاحظ أنّ <code>MrEd</code> يستخدم دوال ومتغيرات <code>Talk</code> دون تعريفها أي أنّ هذه الدوال والمتغيرات كلها معرفة في الصنف <code>MrEd</code> الآن وكأننا عرفناها داخل الصنف (نسخنا ولصقنا المتغيرات والدوال).
</p>

<p>
	ترتبط السمات ارتباطًا وثيقًا بالأصناف المجردة في أنّه يمكنك تعريف متغيرات ودوال، ولا يمكنك نسخ السمة أيضًا بشكلٍ مباشر (أي كتابة <code>new Trait()‎</code>)، ولا يمكن للسمات أن تفرض على الصنف تعريف دالة بشكلٍ ضمني مثلما يفعل الصنف المجرد أو الواجهة إذ أنّ السمات للتعاريف الصريحة فقط.
</p>

<p>
	متى يجب أن أستخدم السمة؟ عندما تريد استخدام السمة يجب أن تسأل نفسك السؤال المهم: هل يمكنني تجنب استخدام السمة بإعادة هيكلة شيفرتي؟ غالبًا سيكون الجواب نعم، السمات هي حالات هامشيّة تسببها الوراثة المفردة ويمكن أن يكون استخدامها بشكل مفرط مغريًا لكنها تقدم مصدرًا آخر لشيفرتك مما يعني أنّ هناك طبقة أخرى من التعقيد. تعاملنا في المثال السابق مع 3 أصناف فقط لكن السمات تعني أنّه يمكنك التعامل مع أكثر من ذلك بكثير، ومن أجل كل سمة يصبح التعامل مع صنفك أصعب بكثير إذ يجب عليك الرجوع إلى كل سمة لمعرفة ما الذي تعرّفه، كنتيجة يجب أن تحافظ على عدد سمات قليل قدر الإمكان.
</p>

<h2>
	السمات لتسهيل إعادة استخدام الشيفرة الأفقية
</h2>

<p>
	بفرض أنّه لدينا واجهة للتسجيل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_11" style="">
<span class="kwd">interface</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولدينا صنفين ينفذان هذه الواجهة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_13" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">FileLogger</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// إضافة رسالة تسجيل إلى ملف ما</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ConsoleLogger</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// رسالة تسجيل إلى الطرفية</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا عرّفت الآن صنفًا آخر <code>Foo</code> والذي تريده أيضًا أن يؤدي مهام التسجيل باستخدام الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_15" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setLogger</span><span class="pun">(</span><span class="typ">Logger</span><span class="pln"> $logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logger </span><span class="pun">=</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">logger</span><span class="pun">-&gt;</span><span class="pln">log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ينفّذ الآن الصنف <code>Foo</code> الواجهة <code>Logger</code> لكنه يعتمد وظيفيًا على تنفيذ <code>Logger</code> الممرر إليه عبر الدالة <code>setLogger()‎</code>، إذا أردنا الآن أن يكون لدينا الصنف <code>Bar</code> وله نفس آلية التسجيل هذه يجب نسخ هذا الجزء من المنطق داخله، لكن نعرّف سمة بدلًا من تكرار الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_17" style="">
<span class="pln">trait </span><span class="typ">LoggableTrait</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setLogger</span><span class="pun">(</span><span class="typ">Logger</span><span class="pln"> $logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logger </span><span class="pun">=</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">logger</span><span class="pun">-&gt;</span><span class="pln">log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	عرّفنا الآن المنطق في سمة ويمكننا استخدامها لإضافته إلى الأصناف <code>Foo</code> و<code>Bar</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_19" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">LoggableTrait</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">LoggableTrait</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويمكننا استخدام الصنف <code>Foo</code> كما في الشيفرة التالية مثلًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_21" style="">
<span class="pln">$foo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">();</span><span class="pln">
$foo</span><span class="pun">-&gt;</span><span class="pln">setLogger</span><span class="pun">(</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileLogger</span><span class="pun">()</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
$foo</span><span class="pun">-&gt;</span><span class="pln">log</span><span class="pun">(</span><span class="str">'my beautiful message'</span><span class="pun">);</span></pre>

<p>
	لاحظ كيف استخدمنا السمة كوكيل (proxy) لاستدعاء تابع التسجيل على نسخة <code>Foo</code>.
</p>

<h2>
	حل التضارب
</h2>

<p>
	يمكن أن تؤدي محاولة استخدام عدة سمات في صف واحد إلى مشاكل تتعلق بالتوابع المتضاربة، عندها تحتاج لحل هذه التضاربات يدويًا، إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_23" style="">
<span class="pln">trait </span><span class="typ">MeowTrait</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> say</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Meow \n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

trait </span><span class="typ">WoofTrait</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> say</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Woof \n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">abstract</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UnMuteAnimals</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">abstract</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> say</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Dog</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">UnMuteAnimals</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">WoofTrait</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Cat</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">UnMuteAnimals</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">MeowTrait</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لنحاول الآن إنشاء الصنف التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_25" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">TalkingParrot</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">UnMuteAnimals</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">MeowTrait</span><span class="pun">,</span><span class="pln"> </span><span class="typ">WoofTrait</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيرجع مفسر PHP خطأً فادحًا:
</p>

<pre class="ipsCode">
Fatal error: Trait method say has not been applied, because there are collisions with other trait methods
on TalkingParrot
</pre>

<p>
	لحل مشكلة التضارب يمكننا القيام بما يلي:
</p>

<ul>
<li>
		نستخدم الكلمة المفتاحية <code>insteadof</code> لاستخدام تابع من سمة بدلًا من تابع من سمة أخرى.
	</li>
	<li>
		ننشئ كنية للتابع مع الباني مثل <code>WoofTrait::say as sayAsDog;‎</code>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_28" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">TalkingParrotV2</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">UnMuteAnimals</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">MeowTrait</span><span class="pun">,</span><span class="pln"> </span><span class="typ">WoofTrait</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">MeowTrait</span><span class="pun">::</span><span class="pln">say insteadof </span><span class="typ">WoofTrait</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">WoofTrait</span><span class="pun">::</span><span class="pln">say </span><span class="kwd">as</span><span class="pln"> sayAsDog</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$talkingParrot </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TalkingParrotV2</span><span class="pun">();</span><span class="pln">
$talkingParrot</span><span class="pun">-&gt;</span><span class="pln">say</span><span class="pun">();</span><span class="pln">
$talkingParrot</span><span class="pun">-&gt;</span><span class="pln">sayAsDog</span><span class="pun">();</span></pre>

<p>
	ستنتج هذه الشيفرة الخرج التالي:
</p>

<pre class="ipsCode">
Meow
Woof
</pre>

<h2>
	تنفيذ نمط مفردة (Singleton) باستخدام السمات
</h2>

<p>
	<strong>ملاحظة</strong>: لا يؤيد هذا المثال استخدام <a href="https://wiki.hsoub.com/Design_Patterns/singleton" rel="external">نمط المفردة</a> كثيرًا إنما يجب استخدامها بكثير من الحذر.
</p>

<p>
	يوجد في PHP طريقة معيارية لتنفيذ المفردة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_30" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Singleton</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $instance</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getInstance</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$instance</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// new Singleton() تكافئ الشيفرة new self()</span><span class="pln">
            </span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$instance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$instance</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// منع نسخ الكائن</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __clone</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// منع سَلسَلة الكائن</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __sleep</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// منع عدم سَلسَلة الكائن</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __wakeup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	من الجيد استخلاص هذا السلوك ضمن سمة لمنع تكرار الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_33" style="">
<span class="pln">trait </span><span class="typ">SingletonTrait</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $instance</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getInstance</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$instance</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// إلى الصنف الذي يستخدم السمة new self() يشير</span><span class="pln">
            </span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$instance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$instance</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __clone</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __sleep</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __wakeup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن الآن لأي صنف يريد أن يعمل كمفردة أن يستخدم السمة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_35" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">SingletonTrait</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// خطأ! مرئية الباني ليست عامة</span><span class="pln">
$myClass </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">();</span><span class="pln">
$myClass </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">::</span><span class="pln">getInstance</span><span class="pun">();</span><span class="pln">

</span><span class="com">// كل الاستدعاءات التالية ستفشل بسبب مرئية التابع</span><span class="pln">
$myClassCopy </span><span class="pun">=</span><span class="pln"> clone $myClass</span><span class="pun">;</span><span class="pln"> 
$serializedMyClass </span><span class="pun">=</span><span class="pln"> serialize</span><span class="pun">(</span><span class="pln">$myClass</span><span class="pun">);</span><span class="pln"> 
$myClass </span><span class="pun">=</span><span class="pln"> deserialize</span><span class="pun">(</span><span class="pln">$serializedMyclass</span><span class="pun">);</span></pre>

<p>
	على الرغم من أنّه من المستحيل الآن سَلسَلة المفردة إلا أنّه لا يزال من المفيد حجب تابع عدم السَلسلة.
</p>

<h2>
	السمات للمحافظة على الأصناف نظيفة
</h2>

<p>
	قد تنفّذ أصنافنا بمرور الوقت المزيد والمزيد من الواجهات، وعندما يكون لهذه الواجهات عدة توابع فإنّ العدد الكلي للتوابع في الصنف يصبح كبيرًا جدًا.
</p>

<p>
	لنفرض مثلًا أنّه لدينا واجهتين وصف ينفّذ هاتين الواجهتين:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_37" style="">
<span class="kwd">interface</span><span class="pln"> </span><span class="typ">Printable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// ...توابع الواجهة الأخرى</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">interface</span><span class="pln"> </span><span class="typ">Cacheable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// توابع الواجهة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Article</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Cachable</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Printable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// يجب أن ننفذ هنا كل توابع الواجهة</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(){</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* شيفرة لطباعة المقالة */</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام سمات مستقلة لتنفيذ هذه الواجهة بدلًا من تنفيذ كل توابع الواجهة في الصنف <code>Article</code> للحفاظ على الصنف أصغر وفصل شيفرة تنفيذ الواجهة من الصنف.
</p>

<p>
	مثلًا لتنفيذ الواجهة <code>Printable</code> يمكننا إنشاء هذه السمة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_39" style="">
<span class="pln">trait </span><span class="typ">PrintableArticle</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// هنا تنفيذ توابع الواجهة</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* شيفرة لطباعة المقالة */</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم نجعل الصنف يستخدم السمة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_41" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Article</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Cachable</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Printable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">PrintableArticle</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">CacheableArticle</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تتمثل الفوائد الأساسية في أنّ توابع تنفيذ الواجهة ستنفصل عن بقية الصنف وتُخزَّن في سمة وهذه السمة تتحمل وحدها مسؤولية تنفيذ الواجهة من أجل هذا النوع المعين من الكائنات.
</p>

<h2>
	استخدام عدة سمات
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_43" style="">
<span class="pln">trait </span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> sayHello</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'Hello '</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

trait </span><span class="typ">World</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> sayWorld</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'World'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyHelloWorld</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> </span><span class="typ">World</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> sayExclamationMark</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'!'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$o </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyHelloWorld</span><span class="pun">();</span><span class="pln">
$o</span><span class="pun">-&gt;</span><span class="pln">sayHello</span><span class="pun">();</span><span class="pln">
$o</span><span class="pun">-&gt;</span><span class="pln">sayWorld</span><span class="pun">();</span><span class="pln">
$o</span><span class="pun">-&gt;</span><span class="pln">sayExclamationMark</span><span class="pun">();</span></pre>

<p>
	خرج المثال السابق:
</p>

<pre class="ipsCode">
Hello World!
</pre>

<h2>
	تغيير مرئية التابع
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_45" style="">
<span class="pln">trait </span><span class="typ">HelloWorld</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> sayHello</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">'Hello World!'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// sayHello تغيير مرئية</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass1</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HelloWorld</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> sayHello </span><span class="kwd">as</span><span class="pln"> </span><span class="kwd">protected</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// كنية تابع مع تغيير مرئية</span><span class="pln">
</span><span class="com">// لم تتغير sayHello مرئية</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass2</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HelloWorld</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> sayHello </span><span class="kwd">as</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> myPrivateHello</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تنفيذ هذا المثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8945_47" style="">
<span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass1</span><span class="pun">())-&gt;</span><span class="pln">sayHello</span><span class="pun">();</span><span class="pln">
</span><span class="com">// Fatal error: Uncaught Error: Call to protected method MyClass1::sayHello()</span><span class="pln">

</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass2</span><span class="pun">())-&gt;</span><span class="pln">myPrivateHello</span><span class="pun">();</span><span class="pln">
</span><span class="com">// Fatal error: Uncaught Error: Call to private method MyClass2::myPrivateHello()</span><span class="pln">

</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyClass2</span><span class="pun">())-&gt;</span><span class="pln">sayHello</span><span class="pun">();</span><span class="pln">
</span><span class="com">// Hello World!</span></pre>

<p>
	انتبه أنّه في المثال الأخير في <code>MyClass2</code> التابع الأصلي غير المُكنّى من <code>trait HelloWorld</code> يبقى كما هو قابلًا للوصول.
</p>

<p>
	ترجمة -وبتصرف- للفصل [Traits] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/" rel="">مدخل إلى الملحن composer: مدير الاعتماديات والحزم في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-regexppcre-%D9%81%D9%8A-php-r1085/" rel="">التعابير النمطية (regexp/PCRE) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1122</guid><pubDate>Tue, 09 Feb 2021 13:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x627;&#x628;&#x64A;&#x631; &#x627;&#x644;&#x646;&#x645;&#x637;&#x64A;&#x629; (regexp/PCRE) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-regexppcre-%D9%81%D9%8A-php-r1085/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_12/20.png.02e8ed52dd89ff6209d9b48d999b39a0.png" /></p>

<table><tbody>
<tr>
<td>
				<strong>المعامل</strong>
			</td>
			<td>
				<strong>تفاصيل</strong>
			</td>
		</tr>
<tr>
<td>
				‎$pattern
			</td>
			<td>
				‎سلسلة نصية مع تعبير منطقي (نمط PCRE)
			</td>
		</tr>
</tbody></table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<h2>
	مطابقة تعبير نمطي عام
</h2>

<p>
	يمكن إجراء المطابقة باستخدام الدالة <a href="%E2%80%8F%E2%80%8Fhttps://wiki.hsoub.com/PHP/preg_match_all" rel=""><code>preg_match_all</code></a> التي تعيد كل النتائج المطابقة في السلسلة النصية المُدخلة (على عكس الدالة <code>preg_match</code> التي تعيد النتيجة الأولى فقط).
</p>

<p>
	تعيد الدالة <code>preg_match_all</code> عدد التطابقات، وسيحتوي المعامل الثالث <code>‎$matches</code> على التطابقات بتنسيق تتحكم به الرايات التي يمكن وضعها في المعامل الرابع.
</p>

<p>
	إذا كان لديك مصفوفة سيحتوي المعامل <code>‎$matches</code> على مصفوفة بتنسيق مشابه لمصفوفتك مع الدالة <code>preg_match</code>، باستثناء أن <code>preg_match</code> تتوقف عند التطابق الأول، حيث تكرر <code>preg_match_all</code> عبر السلسلة النصية حتى تنتهي وتعرض نتيجة كل تكرار في مصفوفة متعددة الأبعاد والتي يمكن التحكم بتنسيقها باستخدام الراية في المعامل الرابع.
</p>

<p>
	يتحكم المعامل الرابع <code>‎$flags</code> في بنية مصفوفة <code>‎$matches</code>، النمط الافتراضي هو <code>PREG_PATTERN_ORDER</code> والرايات الممكنة <code>PREG_SET_ORDER</code> و<code>PREG_PATTERN_ORDER</code>.
</p>

<p>
	توضح الشيفرة التالية استخدام <code>preg_match_all</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_6" style="">
<span class="pln">$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">"a1b c2d3e f4g"</span><span class="pun">;</span><span class="pln">
$pattern </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/[a-z]([0-9])[a-z]/'</span><span class="pun">;</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">preg_match_all</span><span class="pun">(</span><span class="pln">$pattern</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $matches</span><span class="pun">,</span><span class="pln"> PREG_SET_ORDER</span><span class="pun">));</span><span class="pln"> </span><span class="com">// int(3)</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$matches</span><span class="pun">);</span><span class="pln">
preg_match_all</span><span class="pun">(</span><span class="pln">$pattern</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $matches</span><span class="pun">);</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$matches</span><span class="pun">);</span><span class="pln">

</span><span class="com">// preg_match نفس التعبير المنطقي يُنفَّذ بالدالة</span><span class="pln">
preg_match</span><span class="pun">(</span><span class="pln">$pattern</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">,</span><span class="pln"> $matches</span><span class="pun">);</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$matches</span><span class="pun">);</span></pre>

<p>
	خرج الشيفرة <code>var_dump($matches);‎</code> الأولى:
</p>

<pre class="ipsCode">
array(3) {
    [0]=&gt;
    array(2) {
        [0]=&gt;
        string(3) "a1b"
        [1]=&gt;
        string(1) "1"
    }
    [1]=&gt;
    array(2) {
        [0]=&gt;
        string(3) "c2d"
        [1]=&gt;
        string(1) "2"
    }
    [2]=&gt;
    array(2) {
        [0]=&gt;
        string(3) "f4g"
        [1]=&gt;
        string(1) "4"
    }
}
</pre>

<p>
	لدى <code>‎$matches</code> ثلاث مصفوفات متداخلة تمثل كل منها تطابقًا لها نفس تنسيق القيمة المعادة من <code>preg_match</code>.
</p>

<p>
	خرج الشيفرة <code>var_dump($matches);‎</code> الثانية حيث الراية هي الراية الافتراضية <code>PREG_PATTERN_ORDER</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_9" style="">
<span class="pln">array</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]=&gt;</span><span class="pln">
    array</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="str">"a1b"</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="str">"c2d"</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">2</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="str">"f4g"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]=&gt;</span><span class="pln">
    array</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="str">"1"</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="str">"2"</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">2</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="str">"4"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	عندما يُنفّذ نفس التعبير المنطقي باستخدام <code>preg_match</code> تكون المصفوفة المُعادة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_11" style="">
<span class="pln">array</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="str">"a1b"</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="str">"1"</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	تطابق سلسلة نصية مع تعبير نمطي
</h2>

<p>
	تتحقق الدالة <code>preg_match</code> من تطابق سلسلة نصية مع تعبير نمطي.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_13" style="">
<span class="pln">$string </span><span class="pun">=</span><span class="pln"> </span><span class="str">'This is a string which contains numbers: 12345'</span><span class="pun">;</span><span class="pln">

$isMatched </span><span class="pun">=</span><span class="pln"> preg_match</span><span class="pun">(</span><span class="str">'%^[a-zA-Z]+: [0-9]+$%'</span><span class="pun">,</span><span class="pln"> $string</span><span class="pun">);</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$isMatched</span><span class="pun">);</span><span class="pln"> </span><span class="com">// bool(true)</span></pre>

<p>
	إذا مررت معاملًا ثالثًا سيُملأ بالبيانات المُطابقة من التعبير النمطي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_15" style="">
<span class="pln">preg_match</span><span class="pun">(</span><span class="str">'%^([a-zA-Z]+): ([0-9]+)$%'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'This is a string which contains numbers: 12345'</span><span class="pun">,</span><span class="pln">
$matches</span><span class="pun">);</span><span class="pln">

</span><span class="com">// الآن على نتائج مطابقة التعبير النمطي في مصفوفة $matches تحتوي </span><span class="pln">
echo json_encode</span><span class="pun">(</span><span class="pln">$matches</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ["numbers: 12345", "numbers", "12345"]</span></pre>

<p>
	تحتوي <code>‎$matches</code> على مصفوفة لكل المطابقات ثم السلاسل النصية الجزئية في التعبير النمطي محاطة بقوسين، بترتيب إزاحة الأقواس المفتوحة. أي إذا كان لديك التعبير المنطقي <code>‎/z(a(b))/‎</code> سيحتوي الفهرس 0 على كامل السلسلة النصية <code>zab</code> ويحتوي الفهرس 1 على السلسلة النصية الجزئية مُحاطة بالأقواس الخارجية <code>ab</code> ويحتوي الفهرس 2 على السلسلة النصية الجزئية المحاطة بالأقواس الداخلية <code>b</code>.
</p>

<h2>
	تقسيم سلسلة نصية إلى مصفوفة باستخدام تعبير نمطي
</h2>

<p>
	إليك معاني أجزاء التعبير المنطقي <code>‎/[0-9]+\|/‎</code> في الشيفرة أدناه:
</p>

<ul>
<li>
		[0-9]: أي محرف مفرد في المجال من 0 إلى 9.
	</li>
	<li>
		+: واحد أو أكثر من 0 إلى 9.
	</li>
</ul>
<p>
	ومعاني أجزاء التعبير المنطقي <code>‎/[\d]+\|/‎</code>:
</p>

<ul>
<li>
		[]: صنف المحارف
	</li>
	<li>
		‎\d‎: أي رقم
	</li>
	<li>
		+: رقم أو أكثر
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_17" style="">
<span class="pln">$string </span><span class="pun">=</span><span class="pln"> </span><span class="str">"0| PHP 1| CSS 2| HTML 3| AJAX 4| JSON"</span><span class="pun">;</span><span class="pln">

$array </span><span class="pun">=</span><span class="pln"> preg_split</span><span class="pun">(</span><span class="str">"/[0-9]+\|/"</span><span class="pun">,</span><span class="pln"> $string</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> PREG_SPLIT_NO_EMPTY</span><span class="pun">);</span><span class="pln">
</span><span class="com">// أو</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> preg_split</span><span class="pun">(</span><span class="str">"/[\d]+\|/"</span><span class="pun">,</span><span class="pln"> $string</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> PREG_SPLIT_NO_EMPTY</span><span class="pun">);</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
Array
(
    [0] =&gt; PHP
    [1] =&gt; CSS
    [2] =&gt; HTML
    [3] =&gt; AJAX
    [4] =&gt; JSON
)
</pre>

<p>
	يمكنك ببساطة تقسيم سلسلة نصية إلى مصفوفة بتمرير السلسلة النصية والتعبير النمطي للدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/preg_split" rel=""><code>preg_split()‎</code></a>، وللمطابقة والبحث نضيف المعامل الثالث <code>(limit)</code> الذي يسمح لنا بضبط عدد التطابقات التي نريدها وتُضاف السلسلة النصية الباقية إلى نهاية المصفوفة.
</p>

<p>
	ضبطنا المعامل الرابع <code>(flags)</code> في مثالنا إلى القيمة <code>PREG_SPLIT_NO_EMPTY</code> التي تمنع المصفوفة من الاحتواء على أي قيم / مفاتيح فارغة.
</p>

<h2>
	استبدال السلسلة النصية مع التعبير النمطي
</h2>

<p>
	يمثل <code>‎$1</code> و<code>‎$2</code> و<code>‎‎$3</code> في الشيفرة التالية المجموعات الملتقطة الأولى والثانية والثالثة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_19" style="">
<span class="pln">$string </span><span class="pun">=</span><span class="pln"> </span><span class="str">"a;b;c\nd;e;f"</span><span class="pun">;</span><span class="pln">
echo preg_replace</span><span class="pun">(</span><span class="str">"(^([^;]+);([^;]+);([^;]+)$)m"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"$3;$2;$1"</span><span class="pun">,</span><span class="pln"> $string</span><span class="pun">);</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
c;b;a
f;e;d
</pre>

<p>
	تبحث عن كل ما هو بين الفواصل المنقوطة وتعكس الترتيب.
</p>

<h2>
	استبدال سلسلة نصية مع رد النداء
</h2>

<p>
	تعمل الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/preg_replace_callback" rel=""><code>preg_replace_callback</code></a> بإرسال كل مجموعة ملتقطة مطابقة إلى رد النداء المعرَّف وتستبدلها مع القيمة المعادة من رد النداء، وهذا يسمح لنا باستبدال سلسلة نصية اعتمادًا على أي نوع من المنطق.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6504_21" style="">
<span class="pln">$subject </span><span class="pun">=</span><span class="pln"> </span><span class="str">"He said 123abc, I said 456efg, then she said 789hij"</span><span class="pun">;</span><span class="pln">
$regex </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/\b(\d+)\w+/"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// تستبدل هذه الدالة المداخل المطابقة شرطيًا بالاعتماد على المحرف الأول للمجموعة الملتقطة</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> regex_replace</span><span class="pun">(</span><span class="pln">$matches</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">switch</span><span class="pun">(</span><span class="pln">$matches</span><span class="pun">[</span><span class="lit">1</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]){</span><span class="pln">
        </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'7'</span><span class="pun">:</span><span class="pln">
            $replacement </span><span class="pun">=</span><span class="pln"> </span><span class="str">"&lt;b&gt;{$matches[0]}&lt;/b&gt;"</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
            $replacement </span><span class="pun">=</span><span class="pln"> </span><span class="str">"&lt;i&gt;{$matches[0]}&lt;/i&gt;"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $replacement</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$replaced_str </span><span class="pun">=</span><span class="pln"> preg_replace_callback</span><span class="pun">(</span><span class="pln">$regex</span><span class="pun">,</span><span class="pln"> </span><span class="str">"regex_replace"</span><span class="pun">,</span><span class="pln"> $subject</span><span class="pun">);</span><span class="pln">

print_r</span><span class="pun">(</span><span class="pln">$replaced_str</span><span class="pun">);</span><span class="pln">

</span><span class="com">// He said &lt;i&gt;123abc&lt;/i&gt;, I said &lt;i&gt;456efg&lt;/i&gt;, then she said &lt;b&gt;789hij&lt;/b&gt;</span></pre>

<p>
	ترجمة -وبتصرف- للفصل [Regular Expressions (regexp/PCRE)‎] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%B3%D9%85%D8%A7%D8%AA-traits-%D9%81%D9%8A-php-r1122/" rel="">مفهوم السمات (Traits) في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A7%D9%86%D8%B9%D9%83%D8%A7%D8%B3-reflection-%D9%88%D8%AD%D9%82%D9%86-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A9-%D9%81%D9%8A-php-r1084/" rel="">الانعكاس (Reflection) وحقن الاعتمادية في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1085</guid><pubDate>Sun, 13 Dec 2020 13:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x627;&#x646;&#x639;&#x643;&#x627;&#x633; (Reflection) &#x648;&#x62D;&#x642;&#x646; &#x627;&#x644;&#x627;&#x639;&#x62A;&#x645;&#x627;&#x62F;&#x64A;&#x629; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A7%D9%86%D8%B9%D9%83%D8%A7%D8%B3-reflection-%D9%88%D8%AD%D9%82%D9%86-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A9-%D9%81%D9%8A-php-r1084/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_12/19.png.e93d703ea75e517694c83c1834eb41ec.png" /></p>

<h2>
	الانعكاس
</h2>

<h3>
	كشف ميزة الأصناف أو الكائنات
</h3>

<p>
	يمكن إجراء كشف ميزة الأصناف جزئيًا مع الدالتين <code>property_exists</code> و<code>method_exists</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_7" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $public_field</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $protected_field</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $private_field</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> $static_field</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> CONSTANT </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> public_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> protected_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> private_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> static_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// التحقق من الخاصيات</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'public_field'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'protected_field'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

</span><span class="com">// PHP 5.3.0 بدءًا من true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'private_field'</span><span class="pun">);</span><span class="pln"> 
$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'static_field'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'other_field'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span><span class="pln">

</span><span class="com">// التحقق من التوابع</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> method_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'public_function'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> method_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'protected_function'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> method_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'private_function'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> method_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'static_function'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">

$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'CONSTANT'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> property_exists</span><span class="pun">(</span><span class="pln">$object</span><span class="pun">,</span><span class="pln"> </span><span class="str">'CONSTANT'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	يمكننا باستخدام الصنف <code>ReflectionClass</code> كشف الثوابت أيضًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_9" style="">
<span class="pln">$r </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ReflectionClass</span><span class="pun">(</span><span class="str">'MyClass'</span><span class="pun">);</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> $r</span><span class="pun">-&gt;</span><span class="pln">hasProperty</span><span class="pun">(</span><span class="str">'public_field'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> $r</span><span class="pun">-&gt;</span><span class="pln">hasMethod</span><span class="pun">(</span><span class="str">'public_function'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
$check </span><span class="pun">=</span><span class="pln"> $r</span><span class="pun">-&gt;</span><span class="pln">hasConstant</span><span class="pun">(</span><span class="str">'CONSTANT'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true</span></pre>

<p>
	تعمل الشيفرة السابقة أيضًا مع أعضاء الصنف الخاصة والمحمية و/أو الساكنة.
</p>

<p>
	<strong>ملاحظة</strong>: يمكن استخدام الدالتين <code>property_exists</code> و<code>method_exists</code> مع كائن من الصنف بدلًا من الصنف أما لاستخدام الانعكاس مع الكائنات نستخدم الصنف <code>ReflectionObject</code> بدلًا من <code>ReflectionClass</code>.
</p>

<h3>
	اختبار التوابع الخاصة/المحمية
</h3>

<p>
	من المفيد أحيانًا اختبار التوابع الخاصة والمحمية والعامة أيضًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_11" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Car</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> drive</span><span class="pun">(</span><span class="pln">$argument</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $argument</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> stop</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أسهل طريقة لاختبار تابع قيادة (drive method) هي استخدام الانعكاس.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_13" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">DriveTest</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * @ اختبار
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testDrive</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التهيئة</span><span class="pln">
        $argument </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
        $expected </span><span class="pun">=</span><span class="pln"> $argument</span><span class="pun">;</span><span class="pln">
        $car </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Car</span><span class="pun">();</span><span class="pln">
        $reflection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ReflectionClass</span><span class="pun">(</span><span class="pln">\Car</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
        $method </span><span class="pun">=</span><span class="pln"> $reflection</span><span class="pun">-&gt;</span><span class="pln">getMethod</span><span class="pun">(</span><span class="str">'drive'</span><span class="pun">);</span><span class="pln">
        $method</span><span class="pun">-&gt;</span><span class="pln">setAccessible</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// منطق الاستدعاء</span><span class="pln">
        $result </span><span class="pun">=</span><span class="pln"> $method</span><span class="pun">-&gt;</span><span class="pln">invokeArgs</span><span class="pun">(</span><span class="pln">$car</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$argument</span><span class="pun">]);</span><span class="pln">

        </span><span class="com">// الاختبار</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertEquals</span><span class="pun">(</span><span class="pln">$expected</span><span class="pun">,</span><span class="pln"> $result</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نمرر <code>null</code> مكان نسخة الصنف إذا كان التابع ساكنًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_15" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">StopTest</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * @test
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testStop</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التهيئة</span><span class="pln">
        $expected </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
        $reflection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ReflectionClass</span><span class="pun">(</span><span class="pln">\Car</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
        $method </span><span class="pun">=</span><span class="pln"> $reflection</span><span class="pun">-&gt;</span><span class="pln">getMethod</span><span class="pun">(</span><span class="str">'stop'</span><span class="pun">);</span><span class="pln">
        $method</span><span class="pun">-&gt;</span><span class="pln">setAccessible</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// منطق الاستدعاء</span><span class="pln">
        $result </span><span class="pun">=</span><span class="pln"> $method</span><span class="pun">-&gt;</span><span class="pln">invoke</span><span class="pun">(</span><span class="kwd">null</span><span class="pun">);</span><span class="pln">
        </span><span class="com">// الاختبار</span><span class="pln">

        $this</span><span class="pun">-&gt;</span><span class="pln">assertEquals</span><span class="pun">(</span><span class="pln">$expected</span><span class="pun">,</span><span class="pln"> $result</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الوصول إلى متغيرات الأعضاء الخاصة والمحمية
</h3>

<p>
	يستخدم الانعكاس غالبًا كجزء من عملية تطوير البرمجيات مثل إنشاء/استنساخ كائنات وهمية وقت التنفيذ، وهو ممتاز أيضًا لفحص حالة كائن عند أي نقطة زمنية، إليك مثال لاستخدام الانعكاس في اختبار وحدة لتأكيد أنّ عضو الصنف المحمي يتضمن القيمة المتوقعة.
</p>

<p>
	الصنف التالي هو صنف بسيط يعبر عن سيارة، فيه عضو متغير محمي سيحتوي على القيمة الممثلة للون السيارة وبما أنّ المتغير محمي لا نستطيع الوصول إليه مباشرةً ويجب أن نستخدم التوابع الجالبة والضابطة لاستعادة وضبط قيمته.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_17" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Car</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $color

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setColor</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">color </span><span class="pun">=</span><span class="pln"> $color</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getColor</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">color</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ينشئ العديد من المطورين كائنًا من الصنف السابق لاختباره، يضبطون لون السيارة باستخدام <code>Car::setColor()‎</code> ويستعيدونه باستخدام <code>Car::getColor()‎</code> ويوازنون القيمة المُستعادة مع القيمة المضبوطة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_19" style="">
<span class="com">/**
* @اختبار
* @ \Car::setColor يغطي
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testSetColor</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $color </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Red'</span><span class="pun">;</span><span class="pln">

    $car </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Car</span><span class="pun">();</span><span class="pln">
    $car</span><span class="pun">-&gt;</span><span class="pln">setColor</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">);</span><span class="pln">
    $getColor </span><span class="pun">=</span><span class="pln"> $car</span><span class="pun">-&gt;</span><span class="pln">getColor</span><span class="pun">();</span><span class="pln">

    $this</span><span class="pun">-&gt;</span><span class="pln">assertEquals</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">,</span><span class="pln"> $reflectionColor</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قد تبدو الأمور جيدة، يعيد كل <code>Car::getColor()‎</code> قيمة المتغير المحمي <code>Car::$color</code> لكن هذا الاختبار خاطئ بطريقتين:
</p>

<ul>
<li>
		ينفذ <code>Car::getColor()‎</code> الذي هو خارج نطاق هذا الاختبار.
	</li>
	<li>
		يعتمد على <code>Car::getColor()‎</code> الذي قد يكون فيه خطأ مما يجعل الاختبار إيجابيًا أو سلبيًا بشكلٍ خاطئ.
	</li>
</ul>
<p>
	لنلقي نظرة لماذا يجب أن نستخدم الانعكاس بدلًا من <code>Car::getColor()‎</code> في وحدة الاختبار، بفرض أُسندت مهمة للمطور لإضافة "Metallic" لكل لون سيارة لذا سيحاول تعديل <code>Car::getColor()‎</code> لإضافة "Metallic" قبل لون السيارة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_21" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Car</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $color

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setColor</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">color </span><span class="pun">=</span><span class="pln"> $color</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getColor</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Metallic "</span><span class="pun">;</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">color</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّ المطور استخدم فاصلة منقوطة بدلًا من عامل الدمج لإضافة "Metallic" قبل لون السيارة، وفي النتيجة كلما استُدعي التابع <code>Car::getColor()‎</code> ستكون القيمة المعادة "Metallic" بغض النظر عن لون السيارة الفعلي وستفشل نتيجة اختبار الوحدة حتى لو عمل التابع <code>Car::setColor()‎</code> بشكلٍ صحيح ولم يتأثر بهذا التغيير.
</p>

<p>
	إذن كيف نتحقق من أنّ <code>Car::$color</code> يتضمن القيمة التي ضبطناها باستخدام <code>Car::setColor()‎</code>؟ يمكننا استخدام الانعكاس لفحص العضو المتغير المحمي بشكلٍ مباشر بأن نجعل هذا العضو قابلًا للوصول إلى شيفرتنا ثم يمكننا استعادة القيمة.
</p>

<p>
	لنطّلع على الشيفرة ثم نقسّمها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_23" style="">
<span class="com">/**
* @ اختبار
* @ \Car::setColor يغطي
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testSetColor</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $color </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Red'</span><span class="pun">;</span><span class="pln">

    $car </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Car</span><span class="pun">();</span><span class="pln">
    $car</span><span class="pun">-&gt;</span><span class="pln">setColor</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">);</span><span class="pln">

    $reflectionOfCar </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \ReflectionObject</span><span class="pun">(</span><span class="pln">$car</span><span class="pun">);</span><span class="pln">
    $protectedColor </span><span class="pun">=</span><span class="pln"> $reflectionOfForm</span><span class="pun">-&gt;</span><span class="pln">getProperty</span><span class="pun">(</span><span class="str">'color'</span><span class="pun">);</span><span class="pln">
    $protectedColor</span><span class="pun">-&gt;</span><span class="pln">setAccessible</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
    $reflectionColor </span><span class="pun">=</span><span class="pln"> $protectedColor</span><span class="pun">-&gt;</span><span class="pln">getValue</span><span class="pun">(</span><span class="pln">$car</span><span class="pun">);</span><span class="pln">

    $this</span><span class="pun">-&gt;</span><span class="pln">assertEquals</span><span class="pun">(</span><span class="pln">$color</span><span class="pun">,</span><span class="pln"> $reflectionColor</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إليك الآن كيف نستخدم الانعكاس لنحصل على قيمة <code>Car::$color</code> في الشيفرة السابقة:
</p>

<ul>
<li>
		ننشئ كائن <a href="%E2%80%8Fhttps://www.php.net/manual/en/class.reflectionobject.php" rel=""><code>ReflectionObject</code></a> يمثّل كائن السيارة لدينا.
	</li>
	<li>
		نحصل على <a href="%E2%80%8Fhttps://www.php.net/manual/en/class.reflectionproperty.php" rel=""><code>ReflectionProperty</code></a> من أجل <code>Car::$color</code> (يمثل هذا المتغير <code>Car::$color</code>)
	</li>
	<li>
		نجعل <code>Car::$color</code> قابلًا للوصول.
	</li>
	<li>
		نحصل على القيمة من <code>Car::$color</code>.
	</li>
</ul>
<p>
	كما لاحظت يمكننا الحصول على قيمة <code>Car::$color</code> باستخدام الانعكاس دون استدعاء <code>Car::getColor()‎</code> أو أي دالة مساعدة أخرى مما قد يسبب نتائج اختبار غير صالحة، الأن أصبحت وحدة اختبار <code>Car::setColor()‎</code> آمنة ودقيقة.
</p>

<h2>
	حقن الاعتمادية
</h2>

<p>
	حقن الاعتمادية (Dependency Injection) هو مصطلح زائف "لتمرير الأشياء"، وما يعنيه حقًا هو تمرير اعتماديات كائن عبر الباني و/أو التوابع الضابطة بدلًا من إنشائهم عند إنشاء كائن داخل كائن، وقد يشير حقن الاعتمادية إلى حاويات حقن الاعتمادية التي تشغّل البناء والحقن.
</p>

<h3>
	حقن الباني
</h3>

<p>
	تعتمد الكائنات عادةً على كائنات أخرى، بدلًا من إنشاء الاعتمادية في الباني تُمرَّر إليه كمعامل، يضمن هذا عدم وجود ترابط محصور بين الكائنات ويتيح تغيير الاعتمادية عند استنساخ الصنف وهذا له عدة فوائد منها جعل الشيفرة أسهل في القراءة من خلال جعل الاعتماديات واضحة بالإضافة إلى جعل الاختبار أبسط بما أنّ الاعتماديات يمكن تبديلها ومحاكاتها بسهولة.
</p>

<p>
	في المثال التالي يعتمد الصنف <code>Component</code> على نسخة من الصنف <code>Logger</code> لكنه لا ينشئ واحدة، بدلًا من ذلك يتطلب نسخة لتمريرها كمعامل إلى الباني:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_25" style="">
<span class="kwd">interface</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">Logger</span><span class="pln"> $logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logger </span><span class="pun">=</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تبدو الشيفرة مشابهًا لما يلي دون حقن الاعتمادية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_27" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logger </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FooLogger</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يشير استخدام الكلمة المفتاحية <code>new</code> لإنشاء كائنات جديدة في الباني إلى أنّ حقن الاعتمادية لم يُستخدم (أو اُستخدم بشكل غير كامل) وأنّ الشيفرة أصبحت مترابطة بشكلٍ محصور، وهو أيضًا إشارة إلى أنّ الشيفرة اُختبرت بشكلٍ غير كامل أو باختبارات ضعيفة أنتجت افتراضات خاطئة حول حالة البرنامج.
</p>

<p>
	في المثال السابق حيث نستخدم حقن الاعتمادية بدلًا من ذلك، يمكننا التغيير ببساطة إلى <code>Logger</code> مختلفة إذا اضطررنا لذلك، فمثلًا قد نستخدم تنفيذ <code>Logger</code> يسجل الدخول إلى موقع مختلف أو يستخدم تنسيق تسجيل دخول مختلف أو يسجل الدخول إلى قاعدة البيانات بدلًا من ملف.
</p>

<h3>
	حقن التابع الضابط
</h3>

<p>
	يمكن أن تحقن التوابع الضابطة أيضًا الاعتماديات.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_29" style="">
<span class="kwd">interface</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $databaseConnection</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">DatabaseConnection</span><span class="pln"> $databaseConnection</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">databaseConnection </span><span class="pun">=</span><span class="pln"> $databaseConnection</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setLogger</span><span class="pun">(</span><span class="typ">Logger</span><span class="pln"> $logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logger </span><span class="pun">=</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> core</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logSave</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">databaseConnection</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> logSave</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">logger</span><span class="pun">-&gt;</span><span class="pln">log</span><span class="pun">(</span><span class="str">'saving'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يعدّ هذا أمرًا مهمًا عندما لا تعتمد الوظيفة الأساسية للصنف على الاعتمادية للعمل.
</p>

<p>
	الاعتمادية الوحيدة المطلوبة هنا هي <code>DatabaseConnection</code> لذا فهي في الباني، الاعتمادية <code>Logger</code> اختيارية لذا لا نحتاج لتكون جزءًا من الباني مما يجعل الصنف أسهل في الاستخدام.
</p>

<p>
	لاحظ أنّه عند استخدام حقن التابع الضابط من الأفضل توسيع الوظيفة بدلًا من استبدالها، عند ضبط اعتمادية لا يوجد ما يؤكد أنّ الاعتمادية لن تتغير عند نقطة معينة مما قد يؤدي إلى نتائج غير متوقعة، فمثلًا يمكن ضبط <code>FileLogger</code> في البداية ثم ضبط <code>MailLogger</code> وهذا يكسر التغليف ويجعل من الصعب العثور على تسجيلات الدخول لأننا نستبدل التبعية.
</p>

<p>
	يجب أن نضيف اعتمادية مع حقن التابع الضابط لمنع حدوث هذا كما في التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_31" style="">
<span class="kwd">interface</span><span class="pln"> </span><span class="typ">Logger</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> log</span><span class="pun">(</span><span class="pln">$message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $loggers </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $databaseConnection</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">DatabaseConnection</span><span class="pln"> $databaseConnection</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">databaseConnection </span><span class="pun">=</span><span class="pln"> $databaseConnection</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> addLogger</span><span class="pun">(</span><span class="typ">Logger</span><span class="pln"> $logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loggers</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $logger</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> core</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">logSave</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">databaseConnection</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> logSave</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loggers </span><span class="kwd">as</span><span class="pln"> $logger</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $logger</span><span class="pun">-&gt;</span><span class="pln">log</span><span class="pun">(</span><span class="str">'saving'</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في مثل هذا المثال كلما سنستخدم الوظيفة الأساسية فإنّها لن تنكسر حتى لو لم تُضاف اعتمادية مسجل وأي مسجل سيُضاف سيُستخدم مع أنّه يمكن إضافة مسجل آخر، نحن نوسع الوظيفة بدلًا من استبدالها.
</p>

<h3>
	حقن الحاوية
</h3>

<p>
	يمكن أن ننظر إلى حقن الاعتمادية في سياق استخدام حاوية حقن الاعتمادية (DIC) على أنّه مجموعة عليا من حقن الباني، تحلل حاوية حقن الاعتمادية تلميحات نوع باني الصنف وتعالج احتياجاته، نحتاج حقن الاعتماديات بشكلٍ فعال من أجل تنفيذ النسخ.
</p>

<p>
	يتجاوز التنفيذ الدقيق نطاق هذا الملف ولكن في أصله تعتمد حاوية حقن الاعتمادية على استخدام بصمة الصنف.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_33" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Documentation</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Example</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $meaning</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">Meaning</span><span class="pln"> $meaning</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">meaning </span><span class="pun">=</span><span class="pln"> $meaning</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لنسخه بطريقة تلقائية يعتمد معظم الوقت على نظام التحميل التلقائي.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1249_35" style="">
<span class="com">// القديمة PHP إصدارات</span><span class="pln">
$container</span><span class="pun">-&gt;</span><span class="pln">make</span><span class="pun">(</span><span class="str">'Documentation\Example'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// PHP 5.5 بدءًا من الإصدار</span><span class="pln">
$container</span><span class="pun">-&gt;</span><span class="pln">make</span><span class="pun">(</span><span class="pln">\Documentation\Example</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span></pre>

<p>
	إذا كنت تستخدم إصدار PHP 5.5 على الأقل وتريد الحصول على اسم صنف كما في الطريقة في الشيفرة السابقة فإنّ الطريقة الصحيحة هي الثانية، بهذه الطريقة يمكنك إيجاد استخدامات الصنف بسرعة باستخدام بيئة تطوير متكاملة (IDE) حديثة مما يساعدك بشكلٍ كبير مع عملية إعادة التصميم (potential) المحتملة.
</p>

<p>
	يعلم الصنف <code>Documentation\Example</code> في هذه الحالة أنّه يحتاج <code>Meaning</code> وستنشئ حاوية حقن الاعتمادية بدورها نسخة من النوع <code>Meaning</code>، لا يحتاج التنفيذ الفعلي إلى الاعتماد على النسخة المستهلَكة.
</p>

<p>
	بدلًا من ذلك نضع قواعد في الحاوية قبل إنشاء الكائن توضح كيفية نسخ أنواع محددة عند الحاجة وهذا له عدة إيجابيات، كما أنّ حاوية حقن الاعتمادية تستطيع:
</p>

<ul>
<li>
		مشاركة النسخ المشتركة
	</li>
	<li>
		توفير مصنع (factory) لحل بصمة النوع
	</li>
	<li>
		حل بصمة واجهة
	</li>
</ul>
<p>
	إذا عرّفنا قواعد تصف كيف يحتاج نوع محدد للإدارة يمكننا تحقيق تحكم دقيق على الأنواع المشتركة أو المنسوخة أو المُنشأة من مصنع.
</p>

<p>
	ترجمة -وبتصرف- للفصول [Reflection - Dependency Injection] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-regexppcre-%D9%81%D9%8A-php-r1085/" rel="">التعابير النمطية (regexp/PCRE) في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%A4%D9%82%D8%AA-%D9%84%D9%84%D8%AE%D8%B1%D8%AC-%D9%81%D9%8A-php-r1083/" rel="">التخزين المؤقت للخرج في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1084</guid><pubDate>Fri, 11 Dec 2020 13:06:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x627;&#x644;&#x645;&#x624;&#x642;&#x62A; &#x644;&#x644;&#x62E;&#x631;&#x62C; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%A4%D9%82%D8%AA-%D9%84%D9%84%D8%AE%D8%B1%D8%AC-%D9%81%D9%8A-php-r1083/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_12/18.png.22e24f3a7d76a58c55c7d9fd62642a90.png" /></p>

<table><tbody>
<tr>
<td>
				<strong>الدالة</strong>
			</td>
			<td>
				<strong>تفاصيل</strong>
			</td>
		</tr>
<tr>
<td>
				ob_start()‎
			</td>
			<td>
				تبدأ إظهار المخزن المؤقت وأي خرج يوضع بعده سيُلتقط ولن يُعرض
			</td>
		</tr>
<tr>
<td>
				ob_get_contents()‎
			</td>
			<td>
				تُرجع كل المحتوى المُلتقط بالدالة ob_start()‎
			</td>
		</tr>
<tr>
<td>
				ob_end_clean()‎
			</td>
			<td>
				تُفرغ المخزن المؤقت للخرج وتوقف تشغيله للمستوى المتداخل الحالي
			</td>
		</tr>
<tr>
<td>
				ob_get_clean()‎
			</td>
			<td>
				ينفّذ كل من ob_end_clean()‎ و ob_get_contents()‎
			</td>
		</tr>
<tr>
<td>
				ob_get_level()‎
			</td>
			<td>
				يُرجع مستوى التداخل الحالي للمخزن المؤقت للخرج
			</td>
		</tr>
<tr>
<td>
				ob_flush()‎
			</td>
			<td>
				تُفرّغ محتوى المخزن المؤقت وترسله إلى المتصفح دون إنهاء المخزن المؤقت
			</td>
		</tr>
<tr>
<td>
				ob_implicit_flush()‎
			</td>
			<td>
				تُمكّن التفريغ الضمني بعد كل استدعاء للخرج
			</td>
		</tr>
<tr>
<td>
				ob_end_flush()‎
			</td>
			<td>
				تُفرّغ محتوى المخزن المؤقت وترسله إلى المتصفح مع إنهاء المخزن المؤقت
			</td>
		</tr>
</tbody></table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<h2>
	الاستخدام الأساسي للحصول على المحتوى بين المخازن المؤقتة والتفريغ
</h2>

<p>
	يسمح لك التخزين المؤقت للخرج بتخزين أي محتوى نصي (نص، HTML) في متغير وإرساله إلى المتصفح كجزء واحد في نهاية السكربت، بشكلٍ افتراضي تُرسل PHP المحتوى كما تترجمه.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_7" style="">
<span class="pun">&lt;?</span><span class="pln">php
    </span><span class="com">// تشغيل التخزين المؤقت للخرج</span><span class="pln">
    ob_start</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// طباعة خرج ما للمخزن المؤقت</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="str">'Hello '</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// يمكنك أيضًا الخروج من شيفرة PHP</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">

</span><span class="tag">&lt;em&gt;</span><span class="pln">World</span><span class="tag">&lt;/em&gt;</span><span class="pln">

</span><span class="pun">&lt;?</span><span class="pln">php

    </span><span class="com">// إرجاع المخزن المؤقت وإفراغه</span><span class="pln">
    $content </span><span class="pun">=</span><span class="pln"> ob_get_clean</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// إرجاع المخزن المؤقت ثم إفراغه</span><span class="pln">
    </span><span class="com"># $content = ob_get_contents();</span><span class="pln">
    </span><span class="com"># $did_clear_buffer = ob_end_clean();</span><span class="pln">

    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">$content</span><span class="pun">);</span><span class="pln">
    </span><span class="com">#&gt; "Hello &lt;em&gt;World&lt;/em&gt;"</span></pre>

<p>
	أي محتوى خرج بين <code>ob_start()‎</code> و<code>ob_get_clean()‎</code> سيُلتقط ويوضع في المتغير <code>‎$content</code>.
</p>

<p>
	ينفذ استدعاء <code>ob_get_clean()‎</code> كل من <code>ob_get_contents()‎</code> و<code>ob_end_clean()‎</code>.
</p>

<h2>
	معالجة المخزن المؤقت عبر رد النداء
</h2>

<p>
	يمكنك تطبيق أي نوع من المعالجة الإضافية على الخرج بتمرير معامل قابل للاستدعاء للدالة <code>ob_start()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_9" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">function</span><span class="pln"> clearAllWhiteSpace</span><span class="pun">(</span><span class="pln">$buffer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="pln">array</span><span class="pun">(</span><span class="str">"\n"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\t"</span><span class="pun">,</span><span class="pln"> </span><span class="str">' '</span><span class="pun">),</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln"> $buffer</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

ob_start</span><span class="pun">(</span><span class="str">'clearAllWhiteSpace'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">

</span><span class="tag">&lt;h1&gt;</span><span class="pln">Lorem Ipsum</span><span class="tag">&lt;/h1&gt;</span><span class="pln">

</span><span class="tag">&lt;p&gt;&lt;strong&gt;</span><span class="pln">Pellentesque habitant morbi tristique</span><span class="tag">&lt;/strong&gt;</span><span class="pln"> senectus et netus et malesuada fames ac
turpis egestas. </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">Donec non enim</span><span class="tag">&lt;/a&gt;</span><span class="pln"> in turpis pulvinar facilisis.</span><span class="tag">&lt;/p&gt;</span><span class="pln">

</span><span class="tag">&lt;h2&gt;</span><span class="pln">Header Level 2</span><span class="tag">&lt;/h2&gt;</span><span class="pln">

</span><span class="tag">&lt;ol&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;</span><span class="pln">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</span><span class="tag">&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;</span><span class="pln">Aliquam tincidunt mauris eu risus.</span><span class="tag">&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;/ol&gt;</span><span class="pln">

</span><span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">/* ob_end_flush(); سيُفرّغ الخرج ويُعالج عندما ينتهي السكربت أو تُستدعى */</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
&lt;h1&gt;LoremIpsum&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;Pellentesquehabitantmorbitristique&lt;/strong&gt;senectusetnetusetmalesuada
famesacturpisegestas.&lt;ahref="#"&gt;Donecnonenim&lt;/a&gt;inturpispulvinarfacilisis.&lt;/p&gt;&lt;h2&gt;HeaderLevel2&lt;/h2&gt;
&lt;ol&gt;&lt;li&gt;Loremipsumdolorsitamet,consectetueradipiscingelit.&lt;/li&gt;&lt;li&gt;Aliquamtinciduntmauriseurisus.&lt;/
li&gt;&lt;/ol&gt;
</pre>

<h2>
	المخازن المؤقتة للخرج المتداخل
</h2>

<p>
	يمكنك أن تحصل على تداخل المخازن المؤقتة للخرج ومستواها لتوفير محتوى مختلف باستخدام الدالة <code>ob_get_level()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_11" style="">
<span class="pun">&lt;?</span><span class="pln">php

$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
$output </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">while</span><span class="pun">(</span><span class="pln"> $i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// `level` تُنشئ كل حلقة مخزن مؤقت خرج جديد</span><span class="pln">
    ob_start</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Current nest level: "</span><span class="pun">.</span><span class="pln"> ob_get_level</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    $i</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// نحن الآن في المستوى 5</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="str">'Ended up at level: '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> ob_get_level</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">;</span><span class="pln">

</span><span class="com">// محتويات المستوى الأعلى (5) وتحذفه ob_get_clean() ستفرّغ الدالة</span><span class="pln">
$output </span><span class="pun">.=</span><span class="pln"> ob_get_clean</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> $output</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">print</span><span class="pln"> </span><span class="str">'Popped level 5, so we now start from 4'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL</span><span class="pun">;</span><span class="pln">
</span><span class="com">// نحن الآن في المستوى 4</span><span class="pln">

</span><span class="com">// كلما أردنا أن نزيد مستوى نعود للأسفل ونحصل على المخزن المؤقت</span><span class="pln">
</span><span class="kwd">while</span><span class="pun">(</span><span class="pln"> $i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Current nest level: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> ob_get_level</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    echo ob_get_clean</span><span class="pun">();</span><span class="pln">
    $i</span><span class="pun">--;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode">
Current nest level: 1
Current nest level: 2
Current nest level: 3
Current nest level: 4
Current nest level: 5
Ended up at level: 5
Popped level 5, so we now start from 4
Current nest level: 4
Current nest level: 3
Current nest level: 2
Current nest level: 1
</pre>

<h2>
	تشغيل المخزن المؤقت للخرج قبل أي محتوى
</h2>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_13" style="">
<span class="pln">ob_start</span><span class="pun">();</span><span class="pln">

$user_count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">foreach</span><span class="pun">(</span><span class="pln"> $users </span><span class="kwd">as</span><span class="pln"> $user </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> $user</span><span class="pun">[</span><span class="str">'access'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">?&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">li </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"users user-&lt;?php echo $user['id']; ?&gt;"</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"&lt;?php echo $user['link']; ?&gt;"</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="pun">&lt;?</span><span class="pln">php echo $user</span><span class="pun">[</span><span class="str">'name'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
        </span><span class="pun">&lt;/</span><span class="pln">a</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php
    $user_count</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
$users_html </span><span class="pun">=</span><span class="pln"> ob_get_clean</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!</span><span class="pln">$user_count </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'Location: /404.php'</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">
</span><span class="str">&lt;html&gt;</span><span class="pln">
</span><span class="str">&lt;head&gt;</span><span class="pln">
    </span><span class="str">&lt;title&gt;</span><span class="typ">Level</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> user results </span><span class="pun">(&lt;?</span><span class="pln">php echo $user_count</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;)&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">head</span><span class="pun">&gt;</span><span class="pln">

</span><span class="str">&lt;body&gt;</span><span class="pln">
</span><span class="str">&lt;h2&gt;</span><span class="typ">We</span><span class="pln"> have a total of </span><span class="pun">&lt;?</span><span class="pln">php echo $user_count</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln"> users </span><span class="kwd">with</span><span class="pln"> access level </span><span class="lit">7</span><span class="pun">&lt;/</span><span class="pln">h2</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">ul </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"user-list"</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;?</span><span class="pln">php echo $users_html</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">ul</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">body</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">html</span><span class="pun">&gt;</span></pre>

<p>
	نفرض في هذا المثال أنّ <code>‎$users‎</code> مصفوفة متعددة الأبعاد ونريد تمريرها عبر حلقة لإيجاد كل المستخدمين مع الوصول للمستوى 7، إذا لم توجد نتائج سيُعاد توجيهنا إلى صفحة خطأ.
</p>

<p>
	نستخدم هنا المخزن المؤقت للخرج لأننا نفذنا إعادة توجيه <code>header()‎</code> بالاعتماد على نتيجة الحلقة.
</p>

<h2>
	خرج مجرى التدفق إلى العميل
</h2>

<p>
	تمكّن الشيفرة التالية مجرى تدفق المخزن المؤقت للخرج، يفرّغ استدعاء هذه الدالة مباشرةً المخزن المؤقت للعميل وأي خرج لاحق سيُرسل مباشرةً له.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_15" style="">
<span class="kwd">function</span><span class="pln"> _stream</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    ob_implicit_flush</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
    ob_end_flush</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	استخدام المخزن المؤقت للخرج لتخزين المحتويات في ملف
</h2>

<p>
	يعدّ هذا مفيدًا للتقارير والفواتير وغير ذلك.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_17" style="">
<span class="pun">&lt;?</span><span class="pln">php
ob_start</span><span class="pun">();</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">
    </span><span class="tag">&lt;html&gt;</span><span class="pln">
    </span><span class="tag">&lt;head&gt;</span><span class="pln">
        </span><span class="tag">&lt;title&gt;</span><span class="pln">Example invoice</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    </span><span class="tag">&lt;/head&gt;</span><span class="pln">
    </span><span class="tag">&lt;body&gt;</span><span class="pln">
        </span><span class="tag">&lt;h1&gt;</span><span class="pln">Invoice #0000</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
        </span><span class="tag">&lt;h2&gt;</span><span class="pln">Cost: £15,000</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
        ...
    </span><span class="tag">&lt;/body&gt;</span><span class="pln">
    </span><span class="tag">&lt;/html&gt;</span><span class="pln">

</span><span class="pun">&lt;?</span><span class="pln">php
$html </span><span class="pun">=</span><span class="pln"> ob_get_clean</span><span class="pun">();</span><span class="pln">

$handle </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">'invoices/example-invoice.html'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">);</span><span class="pln">
fwrite</span><span class="pun">(</span><span class="pln">$handle</span><span class="pun">,</span><span class="pln"> $html</span><span class="pun">);</span><span class="pln">
fclose</span><span class="pun">(</span><span class="pln">$handle</span><span class="pun">);</span></pre>

<p>
	يأخذ هذا المثال كامل المستند ويكتبه إلى ملف وهذا لا يُظهر المستند في المتصفح إنما نحتاج لكتابة <code>echo $html;‎</code> لعرضه.
</p>

<h2>
	أسباب استخدام ob_start وكيفية الاستخدام النموذجي لها
</h2>

<p>
	يعدّ استخدام <code>ob_start</code> مفيدًا بشكلٍ خاص عندما يكون لديك عمليات إعادة توجيه في صفحتك. الشيفرة التالية لن تعمل عملًا صحيحًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_19" style="">
<span class="typ">Hello</span><span class="pun">!</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php
    header</span><span class="pun">(</span><span class="str">"Location: somepage.php"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	سيظهر خطأ مشابه لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_21" style="">
<span class="pln">headers already sent </span><span class="kwd">by</span><span class="pln"> </span><span class="str">&lt;xxx&gt;</span><span class="pln"> on line </span><span class="str">&lt;xxx&gt;</span><span class="pun">.</span></pre>

<p>
	لإصلاح هذه المشكلة نكتب الشيفرة التالية في بداية الصفحة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_25" style="">
<span class="pun">&lt;?</span><span class="pln">php
    ob_start</span><span class="pun">();</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	ونضيف ما يلي إلى نهايتها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_27" style="">
<span class="pun">&lt;?</span><span class="pln">php
    ob_end_flush</span><span class="pun">();</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	يخزّن ذلك كل المحتوى المتولد في المخزن المؤقت للخرج ويعرضه دفعةً واحدة، لذا إن كان لديك أي استدعاءات إعادة توجيه في صفحتك ستُنفّذ قبل إرسال أي بيانات وعندها تتجنب الخطأ <code>headers already sent</code>.
</p>

<h2>
	التقاط المخزن المؤقت للخرج لإعادة الاستخدام لاحقًا
</h2>

<p>
	لدينا في هذا المثال مصفوفة تتضمن بعض البيانات، نلتقط المخزن المؤقت للخرج في المتغير <code>‎$items_li_html</code> ونستخدمه مرتين في الصفحة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8461_29" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="com">// ابدأ التقاط الخرج</span><span class="pln">
ob_start</span><span class="pun">();</span><span class="pln">

$items </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Home'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Blog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'FAQ'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Contact'</span><span class="pun">];</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pun">(</span><span class="pln">$items </span><span class="kwd">as</span><span class="pln"> $item</span><span class="pun">):</span><span class="pln">

</span><span class="com">// PHP يمكننا الآن الخروج من شيفرة</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;</span><span class="pun">&lt;?</span><span class="pln">php echo $item </span><span class="pun">?&gt;</span><span class="tag">&lt;/li&gt;</span><span class="pln">

</span><span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// PHP العودة إلى شيفرة</span><span class="pln">
endforeach</span><span class="pun">;</span><span class="pln">

</span><span class="com">// على كل المحتوى المُلتقط من المخزن المؤقت للخرج $items_lists سيحتوي المتغير</span><span class="pln">
$items_li_html </span><span class="pun">=</span><span class="pln"> ob_get_clean</span><span class="pun">();</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">

</span><span class="com">&lt;!-- Menu 1: يمكننا الآن إعادة استخدام هذه القوائم عدة مرات في صفحتنا --&gt;</span><span class="pln">
</span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"header-nav"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="pun">&lt;?</span><span class="pln">php echo $items_li_html </span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;/ul&gt;</span><span class="pln">

</span><span class="com">&lt;!-- Menu 2 --&gt;</span><span class="pln">
</span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"footer-nav"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="pun">&lt;?</span><span class="pln">php echo $items_li_html </span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;/ul&gt;</span></pre>

<p>
	احفظ الشيفرة السابقة في ملف <code>output_buffer.php</code> ونفذّه باستخدام <code>php output_buffer.php</code>، يجب أن تحصل على قائمتي العناصر اللتين أنشأناهما في الشيفرة السابقة مع نفس عناصر القائمة المتولدة في PHP باستخدام المخزن المؤقت للخرج:
</p>

<pre class="ipsCode" id="ips_uid_8461_33">
&lt;!-- Menu 1: يمكننا الآن إعادة استخدام هذه القوائم عدة مرات في صفحتنا --&gt;
&lt;ul class="header-nav"&gt;
    &lt;li&gt;Home&lt;/li&gt;
    &lt;li&gt;Blog&lt;/li&gt;
    &lt;li&gt;FAQ&lt;/li&gt;
    &lt;li&gt;Contact&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- Menu 2 --&gt;
&lt;ul class="footer-nav"&gt;
    &lt;li&gt;Home&lt;/li&gt;
    &lt;li&gt;Blog&lt;/li&gt;
    &lt;li&gt;FAQ&lt;/li&gt;
    &lt;li&gt;Contact&lt;/li&gt;
&lt;/ul&gt;
</pre>

<p>
	ترجمة -وبتصرف- للفصل [Output Buffering] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A7%D9%86%D8%B9%D9%83%D8%A7%D8%B3-reflection-%D9%88%D8%AD%D9%82%D9%86-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A9-%D9%81%D9%8A-php-r1084/" rel="">الانعكاس (Reflection) وحقن الاعتمادية في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D9%81%D8%B6%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B3%D9%85%D8%A7%D8%A1-namespaces-%D9%81%D9%8A-php-r1082/" rel="">فضاء الأسماء (namespaces) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1083</guid><pubDate>Tue, 08 Dec 2020 13:01:00 +0000</pubDate></item><item><title>&#x641;&#x636;&#x627;&#x621; &#x627;&#x644;&#x623;&#x633;&#x645;&#x627;&#x621; (namespaces) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%81%D8%B6%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B3%D9%85%D8%A7%D8%A1-namespaces-%D9%81%D9%8A-php-r1082/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_12/17.png.6d6eba1b0f3c060885e2ae085ebecc3e.png" /></p>

<h2>
	التصريح عن فضاء اسم
</h2>

<p>
	يُصرَّح عن فضاء الاسم كالتالي:
</p>

<ul>
<li>
		للتصريح عن فضاء الاسم <code>MyProject</code> نكتب الشيفرة التالية:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_7" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pun">;</span></pre>

<ul>
<li>
		للتصريح عن فضاء اسم متداخل نكتب:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_9" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Security\Cryptography</span><span class="pun">;</span></pre>

<ul>
<li>
		للتصريح عن فضاء اسم مع أقواس مغلقة نكتب:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_11" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	من الأفضل أن تصرّح عن فضاء اسم واحد في الملف بالرغم من أنّه يمكنك التصريح عن العدد الذي تريده من فضاءات الأسماء في ملف واحد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_13" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">First</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// First في فضاء الاسم A تعريف الصنف</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Second</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Second في فضاء الاسم B تعريف الصنف</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> B </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// في فضاء الاسم الجذر  C تعريف الصنف</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	عندما تصرّح عن فضاء اسم فإنّ كل الأصناف التي تعرّفها بعده تنتمي إليه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_15" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Square</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Circle</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	يمكن أن يستخدم التصريح عن فضاء اسم عدة مرات في ملفات مختلفة، يعرّف المثال السابق ثلاثة أصناف في فضاء الاسم <code>MyProject\Shapes</code> في ملف واحد لكن يُفضَّل أن يُقسم إلى ثلاث ملفات يبدأ كل منها بشيفرة فضاء الاسم <code>MyProject\Shapes</code>.
</p>

<h2>
	الإشارة إلى صنف أو دالة في فضاء الاسم
</h2>

<p>
	يمكننا التعريف عن صنف في فضاء الاسم كما وضحنا في الفقرة السابقة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_17" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	نحتاج للحصول على المسار الكامل (المتضمن فضاء الاسم) للإشارة إلى هذا الصنف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_19" style="">
<span class="pln">$rectangle </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes\Rectangle</span><span class="pun">();</span></pre>

<p>
	يمكن أن نختصر الشيفرة السابقة باستيراد الصنف باستخدام التعليمة <code>use</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_21" style="">
<span class="com">// MyProject\Shapes\Rectangle كنية Rectangle تصبح</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes\Rectangle</span><span class="pun">;</span><span class="pln">
$rectangle </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pun">();</span></pre>

<p>
	يمكنك بدءًا من الإصدار PHP 7.0 تجميع تعليمات <code>use</code> مختلفة في تعليمة واحدة مستخدمًا الأقواس:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_23" style="">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes\{
    </span><span class="com">// `use MyProject\Shapes\Rectangle` نفس تعليمة</span><span class="pln">
    </span><span class="typ">Rectangle</span><span class="pun">,</span><span class="pln"> 
    </span><span class="com">// `use MyProject\Shapes\Circle` نفس تعليمة</span><span class="pln">
    </span><span class="typ">Circle</span><span class="pun">,</span><span class="pln">
    </span><span class="com">// `use MyProject\Shapes\Triangle` نفس تعليمة </span><span class="pln">
    </span><span class="typ">Triangle</span><span class="pun">,</span><span class="pln"> 
    </span><span class="com">// التجميعية use يمكنك أيضًا استيراد فضاءات الأسماء الفرعية في تعليمة</span><span class="pln">
    </span><span class="typ">Polygon</span><span class="pln">\FiveSides</span><span class="pun">,</span><span class="pln"> 
    </span><span class="typ">Polygon</span><span class="pln">\SixSides
</span><span class="pun">};</span><span class="pln">
$rectangle </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pun">();</span></pre>

<p>
	قد يكون لديك صنفين بنفس الاسم وهذه ليست مشكلة إذا كان كل منهما في فضاء اسم مختلف، لكن هذا قد يسبب مشكلة عند محاولة استيرادهما باستخدام تعليمة <code>use</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_25" style="">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes\Oval</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Languages\Oval</span><span class="pun">;</span><span class="pln">
</span><span class="com">// Error!</span></pre>

<p>
	يمكنك حل هذه المشكلة بتعريف كنية باستخدام الكلمة المفتاحية <code>as</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_27" style="">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes\Oval </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">OvalShape</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Languages\Oval </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">OvalLanguage</span><span class="pun">;</span></pre>

<p>
	يجب الهروب بالمحرف <code>\</code> للإشارة إلى صنف خارج فضاء الاسم الحالي وإلا سيُفترَض فضاء الاسم النسبي من فضاء الاسم الحالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_29" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes</span><span class="pun">;</span><span class="pln">

</span><span class="com">// (1)</span><span class="pln">
$a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rectangle</span><span class="pun">();</span><span class="pln">

</span><span class="com">// (2)</span><span class="pln">
$a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \MyProject\Shapes\Rectangle</span><span class="pun">();</span><span class="pln">

</span><span class="com">// (3)</span><span class="pln">
$a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Shapes\Rectangle</span><span class="pun">();</span><span class="pln">

</span><span class="com">// (4)</span><span class="pln">
$a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \StdClass</span><span class="pun">();</span><span class="pln">

</span><span class="com">// (5)</span><span class="pln">
$a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StdClass</span><span class="pun">();</span></pre>

<p>
	في الموضع (1) أُشير إلى <code>MyProject\Shapes\Rectangle</code> بشكلٍ صحيح.
</p>

<p>
	في الموضع (2) أُشير إلى <code>MyProject\Shapes\Rectangle</code> بشكلٍ صحيح لكن لا يوجد ضرورة لذكر المسار الكامل.
</p>

<p>
	في الموضع (3) أُشير إلى <code>MyProject\Shapes\MyProject\Shapes\Rectangle</code> بشكلٍ خاطئ.
</p>

<p>
	في الموضع (4) تتطلب الإشارة إلى الصنف <code>StdClass</code> من ضمن فضاء الاسم استخدام البادئة <code>\</code> لأنّ هذا الصنف غير معرّف في فضاء اسم أي أنّه عام وهذه الطريقة الصحيحة للإشارة إليه.
</p>

<p>
	في الموضع (5) أُشير إلى <code>MyProject\Shapes\StdClass</code> بشكلٍ خاطئ.
</p>

<h2>
	التصريح عن فضاء اسم فرعي
</h2>

<p>
	يمكننا التصريح عن فضاء اسم ضمن هرمية بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_31" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Sub\Level</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> CONNECT_OK </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Connection</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* ... */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> connect</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* ... */</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	يُنشئ المثال السابق ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_618_33" style="">
<span class="pln">constant </span><span class="typ">MyProject</span><span class="pln">\Sub\Level\CONNECT_OK
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Sub\Level\Connection </span><span class="kwd">and</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> </span><span class="typ">MyProject</span><span class="pln">\Sub\Level\connect</span></pre>

<h2>
	ما هي فضاءات الأسماء؟
</h2>

<p>
	يوجد في مجتمع PHP الكثير من المطورين يكتبون الكثير من الشيفرات فمن الممكن أن يوجد نفس اسم الصنف في مكتبتين مختلفتين وقد يسبب هذا مشكلة عند استخدامهما في فضاء اسم واحد، لذا فإن فضاءات الأسماء تحلّ هذه المشكلة. كما هو موضح في دليل PHP المرجعي يمكن موازنة فضاءات الأسماء بمجلدات نظام التشغيل، فإذا كان لدينا ملفين بنفس الاسم موجودين في مجلدين مختلفين يشبه ذلك صنفي PHP لهما نفس الاسم وموجودين في فضاءي اسمين مختلفين.
</p>

<p>
	من الضروري بالنسبة لك أن يُستخدم فضاء اسم شيفرتك من قِبل المطورين الآخرين دون الخوف من التصادم مع مكتبات أخرى.
</p>

<p>
	ترجمة -وبتصرف- للفصل [Namespaces] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%A4%D9%82%D8%AA-%D9%84%D9%84%D8%AE%D8%B1%D8%AC-%D9%81%D9%8A-php-r1083/" rel="">التخزين المؤقت للخرج في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AC%D9%84%D8%B3%D8%A7%D8%AA-%D9%88%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-curl-%D9%81%D9%8A-php-r1081/" rel="">الجلسات وملفات تعريف الارتباط ومكتبة cURL في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1082</guid><pubDate>Sun, 06 Dec 2020 13:02:00 +0000</pubDate></item></channel></rss>
