<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x627;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/page/2/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x627;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; Laravel</description><language>ar</language><item><title>&#x631;&#x641;&#x639; &#x627;&#x644;&#x645;&#x644;&#x641;&#x651;&#x627;&#x62A; &#x648;&#x625;&#x62F;&#x627;&#x631;&#x62A;&#x647;&#x627; &#x641;&#x64A; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D9%91%D8%A7%D8%AA-%D9%88%D8%A5%D8%AF%D8%A7%D8%B1%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r392/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_03/laravel3.png.7e6b4359ac967526034a8de1c6121e22.png" /></p>

<p>
	يتوفّر إطار العمل Laravel على واجهة تطبيقات برمجيّة <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> موّحّدة للتعامل مع الملفات. تأتي واجهة التطبيقات هذه مجهّزة مبدئيا بتعريفات Drivers تمكّن من إدارة الملفات على نظام الملفات المحلّي، خادوم FTP أو على خدمتي <a href="https://academy.hsoub.com/tags/amazon/" rel="">Amazon S3</a> وRackspace السّحابيتين. سنعرض في هذا الدرس لأساسيّات إدارة الملفات: رفعها Upload، تخزينها والعثور عليها في الإصدار 5.3 من إطار العمل Laravel.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="22344" data-unique="iw8zvjnr6" src="https://academy.hsoub.com/uploads/monthly_2017_03/laravel3.png.b70a02189e5c1ad09c5c8ca2811b0592.png" alt="laravel3.png"></p>

<h2 id="أقراص-التخزين-في-laravel">
	أقراص التخزين في Laravel
</h2>

<p>
	تُضبَط إعدادات تخزين الملفات ضمن الملف <code>config/filesystems.php</code> عن طريق ما يُسمّيه Laravel الأقراص Disks. يُمثّل كل قرص تعريفا، مسارا للتخزين وإعدادات خاصّة بالقرص. يعرّف ملفّ الإعداد مبدئيا ثلاثة أقراص <code>public</code>، <code>local</code> و<code>s3</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_649_7">
<span class="str">'disks'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

    </span><span class="str">'local'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'driver'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'local'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'root'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> storage_path</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">],</span><span class="pln">

    </span><span class="str">'public'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'driver'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'local'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'root'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> storage_path</span><span class="pun">(</span><span class="str">'app/public'</span><span class="pun">),</span><span class="pln">
        </span><span class="str">'visibility'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'public'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">],</span><span class="pln">

    </span><span class="str">'s3'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'driver'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'s3'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'key'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'your-key'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'secret'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'your-secret'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'region'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'your-region'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'bucket'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'your-bucket'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">],</span><span class="pln">

</span><span class="pun">],</span></pre>

<p>
	يستخدم القرصُ <code>local</code> في المثال المبدئي أعلاه التعريفَ <code>local</code> (نظام الملفات المحلّي) ومسار التخزين <code>storage/app</code>. بالنسبة للقرص <code>s3</code> فهو يستخدم التعريف <code>s3</code> (خدمة Amazon S3) ويتطلّب قيما ضرورية للولوج إلى الخدمة.<br>
	يشبه القرص <code>public</code> القرصَ <code>local</code>؛ إلا أنّ بينهما فرقًا جوهريًّا: هذا القرص مهيّأ للملفات التي نريد إتاحتها للعموم. تُخزَّن ملفات هذا القرص على المسار <code>storage/app/public</code>. يمكن ملاحظة أن المسار <code>storage/app/public</code> يوجد <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel-5-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D8%B9%D9%84%D9%89-windows-%D9%88ubuntu-r212/#%D8%A8%D9%86%D9%8A%D8%A9-%D9%85%D8%AC%D9%84%D8%AF%D8%A7%D8%AA-laravel" rel="">خارج المجلّد <code>public</code></a> الذي يحوي ملفّات المشروع المتاحة للعموم. نستخدم أمر Artisan التالي لجعل ملفات القرص <code>public</code> متاحة على الوِب:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_7">
<span class="pln">php artisan storage</span><span class="pun">:</span><span class="pln">link</span></pre>

<p>
	ينشئ الأمر <a href="https://academy.hsoub.com/certificates/redhat/rhcsa/%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%AC%D9%84%D8%AF%D8%A7%D8%AA-%D8%B9%D9%84%D9%89-red-hat-enterprise-linux-r41/#%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D9%88%D8%B5%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D9%84%D8%A8%D8%A9-%D9%88%D8%A7%D9%84%D8%B1%D9%85%D8%B2%D9%8A%D8%A9" rel="">وصلة رمزيّة</a> على المسار <code>public/storage</code> ويجعلها تحيل إلى<code>storage/app/public</code> الذي هو مسار تخزين القرص <code>public</code>. سنرى بعد قليل كيف نصل إلى الملفات الموجودة في هذا القرص.
</p>

<p>
	<strong>ملحوظة:</strong> يتطلّب استخدام التعريفيْن <code>s3</code> و<code>rackspace</code> تثبيت الحزمتييْن التاليّتيْن على التوالي (عن طريق <code>composer</code>):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_9">
<span class="pln">league</span><span class="pun">/</span><span class="pln">flysystem</span><span class="pun">-</span><span class="pln">aws</span><span class="pun">-</span><span class="pln">s3</span><span class="pun">-</span><span class="pln">v3 </span><span class="pun">~</span><span class="lit">1.0</span><span class="pln">
league</span><span class="pun">/</span><span class="pln">flysystem</span><span class="pun">-</span><span class="pln">rackspace </span><span class="pun">~</span><span class="lit">1.0</span></pre>

<h2 id="رفع-ملفات-وعرض-روابطها-في-laravel-53">
	رفع ملفات وعرض روابطها في Laravel 5.3
</h2>

<p>
	سنهيّئ في بقيّة الدرس مشروع Laravel 5.3 للعمل عليه. سيكون هدفنا رفع صورة في المتصفّح ثم عرض هذه الصورة في صفحة الوِب.<br>
	نضيف مسارين إلى ملف مسارات الوِب <code>routes/web.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_11">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'image-upload'</span><span class="pun">,</span><span class="str">'ImageController@imageUpload'</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'image-upload'</span><span class="pun">,</span><span class="str">'ImageController@imageUploadPost'</span><span class="pun">);</span></pre>

<p>
	يتلقّى الإجراء <code>get</code> طلبات عرض الصفحة، في ما نستخدم الإجراء <code>post</code> لتخزين الصّورة المحمَّلة في الصفحة التي سننشئها بعد قليل.
</p>

<p>
	الخطوة التاليّة هي إنشاء المتحكّم <code>ImageController</code> وكتابة الدالتين <code>imageUpload</code> و<code>imageUploadPost</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_13">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">ImageController</span></pre>

<p>
	كلّ ما تفعله الدالة <code>imageUpload</code> هو استدعاء العرض <code>image-upload</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_15">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> imageUpload</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"> view</span><span class="pun">(</span><span class="str">'image-upload'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بالنسبة للدالة <code>imageUploadPost</code> فستستقبل الصورة المحمّلة من المتصفّح، تخزّنها ثم ترسلها إلى <code>image-upload</code> الذي يعرضها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_17">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> imageUploadPost</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="com">// TODO:</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'image-upload'</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'message'</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Image uploaded successfully"</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">,</span><span class="pln"> $imagePath</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الدالة غير مكتملة لحد الساعة، فكل ما يظهر منها هو استدعاء القالب وتمرير رسالة إليه تفيد بنجاح رفع الصورة، إضافة إلى متغيّر يمثّل رابط الصورة. استقبال الصورة، تخزينها والحصول على رابط تخزينها سيكون محلّ التعليق <code>TODO</code>.<br>
	ننشئ القالب <code>image-upload</code> قبل العودة إلى الدالة <code>imageUploadPost</code>.
</p>

<p>
	ننشئ الملف <code>image-upload.blade.php</code> على المسار <code>resources/views</code> ونضع فيه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_19">
<span class="dec">&lt;!DOCTYPE html&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">Laravel 5.3 Image Upload example</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;div&gt;</span><span class="pln">
    @if (isset($path))
        </span><span class="tag">&lt;p&gt;</span><span class="pln">{{ $message }}</span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"{{ url($path) }}"</span><span class="tag">&gt;</span><span class="pln">
    @endif

    </span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ url('image-upload') }}"</span><span class="pln"> </span><span class="atn">enctype</span><span class="pun">=</span><span class="atv">"multipart/form-data"</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">
            {{ csrf_field() }}
            </span><span class="tag">&lt;div&gt;</span><span class="pln">
                    </span><span class="tag">&lt;div&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">"file"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"image"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
                    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                    </span><span class="tag">&lt;div&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">Upload</span><span class="tag">&lt;/button&gt;</span><span class="pln">
                    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/form&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	نتحقّق أولا، عن طريق الدالة <code>isset</code>، من وجود متغيّر باسم <code>path</code> في المعطيات الممرّرة إلى القالب. يمثّل المتغيّر <code>path</code> مسار الصورة التي نعرضها في حال وجود المتغيّر <code>path</code>. ثم يأتي دور استمارة الرّفع التي ترسل طلبا بإجراء <code>POST</code> إلى المسار <code>image-upload</code>. نحدّد نوع المُدخَل <code>input</code> الذي نريد استقبال الصورة عن طريقه بالنوع <code>file</code> ونحدّد اسمه بـ<code>image</code>.
</p>

<p>
	نستطيع الآن العودة إلى الدالة <code>imageUploadPost</code> لإكمالها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_21">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> imageUploadPost</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="com">// TODO:</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'image-upload'</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'message'</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Image uploaded successfully"</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">,</span><span class="pln"> $imagePath</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نستقبل الطلب في المعطى <code>request</code>؛ حيث يمكننا تطبيق الدالة <code>file</code> للحصول على الصورة التي حمّلها المتصفّح بتحديد اسم المُدخَل <code>input</code> الذي استقبلها في صفحة الوٍب:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_23">
<span class="pln">$request</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">(</span><span class="str">'image'</span><span class="pun">);</span></pre>

<p>
	نطبّق على الملف الدالة <code>store</code> لتخزينه:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_25">
<span class="pln">$image </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">(</span><span class="str">'image'</span><span class="pun">)-&gt;</span><span class="pln">store</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'public'</span><span class="pun">);</span></pre>

<p>
	تأخذ الدالة <code>store</code> معطَيَيْن، الأول منهما هو اسم المجلّد حيثُ نريد تخزين الملفّ والثاني اسم القرص الذي نريد استخدامه. إن لم نحدّد اسمَ القرص فسيُستخدَم القرص المبدئي المعرّف بالتعليمة <code>default</code> ضمن ملف الإعداد <code>config/filesystems</code> (تأخذ التعليمة مبدئيا القيمة <code>local</code>).
</p>

<p>
	نريد أن تكون الصورة متاحة للعموم ضمن مجلد خاصّ بالصور اسمه <code>images</code>، لذا نمرّر القيمتيْن <code>images</code> و<code>public</code> للمعطييْن الأول والثاني على التوالي.
</p>

<p>
	خزّنا الآن الصورة على القرص المتاح للعموم. الخطوة التاليّة هي الحصول على مسارها من أجل إرساله إلى القالب <code>image-upload</code> لعرضه. نستخدم الدالة <code>url</code> ضمن الصنف <code>Storage</code> والتي يمكن تطبيقها على أقراص تستخدم أحد التعريفيْن <code>local</code> أو <code>s3</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_27">
<span class="pln">$imagePath </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">url</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">);</span></pre>

<p>
	لا ننسى استيراد الصّنف <code>Storage</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_29">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Storage</span><span class="pun">;</span></pre>

<p>
	أصبحت دالة المتحكّم مكتملة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_31">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> imageUploadPost</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  $image </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">(</span><span class="str">'image'</span><span class="pun">)-&gt;</span><span class="pln">store</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="str">'public'</span><span class="pun">);</span><span class="pln">
  $imagePath </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">url</span><span class="pun">(</span><span class="pln">$image</span><span class="pun">);</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'image-upload'</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'message'</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Image uploaded successfully"</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'path'</span><span class="pun">,</span><span class="pln"> $imagePath</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا ننسى إنشاء الوصلة الرمزية:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_33">
<span class="pln">php artisan storage</span><span class="pun">:</span><span class="pln">link</span></pre>

<p>
	نشغّل خادوم التطوير المضمَّن في Laravel:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_35">
<span class="pln">php artisan serve    </span></pre>

<p>
	ثم نفتح المتصفّح لزيارة المسار <code><a href="http://localhost:8000/image-upload" ipsnoembed="false" rel="external nofollow">http://localhost:8000/image-upload</a></code>. نختار صورة لرفعها ثم نضغط على الزّر <code>Upload</code>. يخزّن Laravel الصّورة في المجلّد <code>storage/app/public</code>، ثم يطلُب عرض القالب <code>image-upload</code> مع تمرير رابط الصّورة في المتغيّر <code>path</code>، إضافة إلى رسالة في المتغيّر <code>message</code> تفيد بنجاح الرّفع.
</p>

<p>
	<strong>ملحوظة:</strong> يختار Laravel عند استخدام الدالة <code>store</code> اسما مميّزا للملف بتطبيق <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-encoding%D8%8C-%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9-encryption%D8%8C-%D8%A7%D9%84%D8%AA%D8%AC%D8%B2%D8%A6%D8%A9-hashing-%D9%88%D8%A7%D9%84%D8%AA%D8%B4%D9%88%D9%8A%D8%B4-obfuscation%D8%9F-r308/" rel="">دالة تجزئة Hash</a> عليه. إن أردت اختيار الاسم الذي يُخزَّن به الملف فيمكنك ذلك بالدالة <code>storeAs</code>:
</p>

<ul>
<li>
		<p>
			تخزين الملف في القرص المبدئي:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_37">
<span class="pln">$image </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">(</span><span class="str">'image'</span><span class="pun">)-&gt;</span><span class="pln">storeAs</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="str">'fileName'</span><span class="pun">);</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تخزين الملف مع تحديد القرص:
		</p>

		<pre>
 </pre>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_41">
<span class="pln">$image </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">(</span><span class="str">'image'</span><span class="pun">)-&gt;</span><span class="pln">storeAs</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="str">'fileName'</span><span class="pun">,</span><span class="str">'public'</span><span class="pun">);</span></pre>

<h2 id="العمليات-على-الملفات-المرفوعة">
	العمليّات على الملفات المرفوعة
</h2>

<p>
	يوفّر Laravel الصّنفَ Storage للتعامل مع الملفات والأقراص.
</p>

<h3 id="إضافة-ملفات-إلى-التخزين">
	إضافة ملفات إلى التخزين
</h3>

<p>
	تُستخدَم الدالة <code>put</code> في الصّنف <code>Storage</code> لتخزين ملفات على النحو التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_43">
<span class="typ">Storage</span><span class="pun">::</span><span class="pln">put</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> $fileContents</span><span class="pun">);</span></pre>

<p>
	يُمثّل المعطى الأوّل الممرَّر إلى الدالة اسمَ المجلّد الذي تريد حفظ الملفّ فيه والثاني محتوى الملفّ. تستخدم الدالة أعلاه القرص المبدئي (التعليمة <code>default</code> في ملف الإعداد). إن أردت استخدام قرص مغاير فيمكنك الاستعانة بالدالة <code>disk</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_45">
<span class="typ">Storage</span><span class="pun">::</span><span class="pln">disk</span><span class="pun">(</span><span class="str">'public'</span><span class="pun">)-&gt;</span><span class="pln">put</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> $fileContents</span><span class="pun">);</span></pre>

<p>
	يُحدَّد المجلّد المُمرَّر إلى الدالة <code>put</code> (المعطَى الأول) اعتمادا على المسار الجذر للقرص المستخدَم؛ أي أن المقصود بالمجلّد <code>images</code> في المثال السابق هو المجلد <code>storage/app/public/images</code>؛ نظرا لكون <code>storage/app/public</code> هو المسار الجذر للقرص <code>public</code>. يُعيَّن المسار الجذر بالتعليمة <code>root</code> أثناء إعداد الأقراص في ملف الإعداد <code>config/filesystems</code>.
</p>

<h3 id="استرجاع-ملف-من-التخزين">
	استرجاع ملف من التخزين
</h3>

<p>
	يتيح الصّنف <code>Storage</code> الدالة <code>get</code> لاسترجاع محتوى ملف مخزّن في القرص المبدئي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_47">
<span class="pln">$contents </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'images/file.jpg'</span><span class="pun">);</span></pre>

<p>
	يمكن تحديد القرص المستهدَف باستدعاء الدالة <code>disk</code> قبل تطبيق <code>get</code>.
</p>

<p>
	يتوفّر الصّنف <code>Storage</code> على الدالة <code>exists</code> التي تتيح التأكد من وجود الملفّ:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_49">
<span class="pln">$exists </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">disk</span><span class="pun">(</span><span class="str">'s3'</span><span class="pun">)-&gt;</span><span class="pln">exists</span><span class="pun">(</span><span class="str">'file.jpg'</span><span class="pun">);</span></pre>

<h3 id="الحصول-على-بيانات-ملف">
	الحصول على بيانات ملفّ
</h3>

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

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_51">
<span class="pln">$size </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">size</span><span class="pun">(</span><span class="str">'file1.jpg'</span><span class="pun">);</span></pre>

<p>
	أو بتحديد القرص المستهدَف:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_53">
<span class="pln">$size </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">disk</span><span class="pun">(</span><span class="str">'s3'</span><span class="pun">)-&gt;</span><span class="pln">size</span><span class="pun">(</span><span class="str">'file1.jpg'</span><span class="pun">);</span></pre>

<p>
	يمكن على نفس المنوال معرفة تاريخ آخر تعديل على الملف على صيغة ختم زمني Timestamp:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5049_55">
<span class="pln">$time </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">lastModified</span><span class="pun">(</span><span class="str">'file1.jpg'</span><span class="pun">);</span></pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">392</guid><pubDate>Mon, 27 Mar 2017 10:13:02 +0000</pubDate></item><item><title>&#x645;&#x642;&#x62F;&#x645;&#x629; &#x625;&#x644;&#x649; &#x646;&#x638;&#x627;&#x645; &#x627;&#x644;&#x625;&#x634;&#x639;&#x627;&#x631;&#x627;&#x62A; Notifications &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%A5%D8%B4%D8%B9%D8%A7%D8%B1%D8%A7%D8%AA-notifications-%D9%81%D9%8A-laravel-r390/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_10/1.png.1a7c0a4033ceb736d9961b6dbf8345e6.png" /></p>

<p>
	يضيف الإصدار 5.3 من Laravel نظاما للإشعارات Notifications يمكن من خلاله إخطار المستخدم بحدوث شيء ما. تُستخدَم الإشعارات، التي تكون عادة على هيئة بلاغات قصيرة، لإعلام مستخدم التطبيق بوقوع أمر ما؛ على سبيل المثال “صدور فاتورة”، “تسجيل مستخدم”، “إعادة تعيين كلمة السّر” أو “نشر درس”؛ حسب طبيعة التطبيق الذي تعمل عليه.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="25186" data-unique="6intmifnv" src="https://academy.hsoub.com/uploads/monthly_2017_10/1.png.1f06b3e358a3ff0f0e1d3d5cc2e53200.png" alt="1.png"></p>

<p>
	يتيح نظام الإشعارات في Laravel 5.3 وسائط عدّة (تُسمّى قنوات Channels) لتوصيل الإشعار: البريد الإلكتروني، الرسائل النصية القصيرة SMS (بالاعتماد على خدمة Nexmo) وخدمة Slack. يمكن أيضا تخزين الإشعارات في قاعدة البيانات من أجل عرضها في واجهة الوِب.
</p>

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

<h2 id="تهيئة-المشروع">
	تهيئة المشروع
</h2>

<p>
	نبدأ أولا بتهيئة المشروع الذي سنعمل عليه. أنشئ مشروع Laravel 5.3 جديدا، إن لم يكن لديك واحد جاهز واضبط إعدادات قاعدة البيانات. نستخدم نفس الإعدادات المذكورة في فقرة <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AE%D8%A8%D8%A6%D8%A9-%D9%81%D9%8A-laravel-r389#%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%AA%D8%B7%D9%88%D9%8A%D8%B1" rel="">تهيئة بيئة التطوير</a> من درس أساسيات التخبئة في Laravel؛ مع التعديل عليها قليلا. سنضيف صنفا لبذر المستخدمين:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1539_7">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">UsersTableSeeder</span></pre>

<p>
	ونعدّل صنف البذر على النحو التالي لإضافة مستخدمَيْن إلى قاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1539_9">
<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">
    $user1 </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">'Med Ahmed Eyil'</span><span class="pun">,</span><span class="pln">
      </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'medeyil@laravel.com'</span><span class="pun">,</span><span class="pln">
      </span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="str">'1234'</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
    $user2 </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">'Fatima Benziane'</span><span class="pun">,</span><span class="pln">
      </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'fbenziane@laravel.com'</span><span class="pun">,</span><span class="pln">
      </span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="str">'4567'</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="pln">create</span><span class="pun">(</span><span class="pln">$user1</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">User</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="pln">$user2</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_1539_11">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<p>
	يصبح لدينا الآن نموذجان، واحد للمستخدمين وآخر للمنشورات.
</p>

<p>
	ننتقل إلى ملف المسارات <code>routes/web.php</code> ونضيف المسار التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_7">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/notify/{user_id}/{post_id}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'PostsController@notify'</span><span class="pun">);</span></pre>

<p>
	يعني هذا أنه عند زيارة الرابط <code>notify/user_id/post_id/</code> (حيث <code>user_id</code> و<code>post_id</code> معرّفا المستخدم والمنشور على التوالي) سيطلُب Laravel تنفيذ الدالة <code>notify</code> في المتحكم <code>PostsController</code>. نعدّل المتحكّم <code>PostsController</code> لإضافة هذه الدالة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_9">
<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">$user_id</span><span class="pun">,</span><span class="pln">$post_id</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="typ">User</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$user_id</span><span class="pun">);</span><span class="pln">
    $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$post_id</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// todo</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سنعود لاحقا لإكمال الدالة <code>notify</code> التي تكتفي لحد الساعة بالعثور على المستخدم والمنشور الممررَيْن إليها في المعطيات.
</p>

<h2 id="الإشعارات">
	الإشعارات
</h2>

<p>
	هدفنا هو التالي: يطلُب المتصفح الرابط <code>notify/1/2/</code> (مثلا) فيُرسَل إشعار عبر البريد إلى المستخدم ذي المعرف <code>1</code> يخبره أن المنشور ذا المعرف <code>2</code> قد أُضيف إلى الموقع. سنحتاج لبلوغ هذا الهدف لإشعار “إضافة منشور”. ننفذ الأمر التالي لإنشاء هذا الإشعار:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_11">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">notification </span><span class="typ">NewPost</span></pre>

<p>
	ستلاحظ بعد تنفيذ الأمر أعلاه ظهور مجلد جديد باسم <code>Notifications</code> (إن لم يكن موجودا سلفا) متفرع عن المجلد <code>app</code> وبداخله صنف باسم <code>NewPost.php</code> (نزعنا التعليقات للاختصار):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_13">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Notifications</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Bus\Queueable</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Notifications\Notification</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\Queue\ShouldQueue</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Notifications\Messages\MailMessage</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">NewPost</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Notification</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">Queueable</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="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> via</span><span class="pun">(</span><span class="pln">$notifiable</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="str">'mail'</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"> toMail</span><span class="pun">(</span><span class="pln">$notifiable</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="kwd">new</span><span class="pln"> </span><span class="typ">MailMessage</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">-&gt;</span><span class="pln">line</span><span class="pun">(</span><span class="str">'The introduction to the notification.'</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">-&gt;</span><span class="pln">action</span><span class="pun">(</span><span class="str">'Notification Action'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'https://laravel.com'</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">-&gt;</span><span class="pln">line</span><span class="pun">(</span><span class="str">'Thank you for using our application!'</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"> toArray</span><span class="pun">(</span><span class="pln">$notifiable</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">
        </span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمدّد الصنف <code>NewPost</code> الصنفَ <code>Notification</code> الذي يحوي التعليمات الضرورية للتعامل مع الإشعارات. تظهر الدالة المشيّدة Constructor وثلاث دوال أخرى:
</p>

<ul>
<li>
		<code>via</code>: تعرّف القنوات التي نريد إرسال الإشعارات عبرها. توجد قناة البريد <code>mail</code> مبدئيا. تمكن إضافة قناة أخرى من تلك المتوفرة. يستخدم Laravel جميع القنوات المذكورة في المصفوفة المرجَعة، بمعنى؛ إن حددت مثلا القناتين <code>mail</code> و<code>database</code> في المصفوفة فإن الإشعار سيُرسَل عبر البريد ويُخزَّن أيضا في قاعدة البيانات.
	</li>
	<li>
		<code>toMail</code>: هذه الدالة خاصّة بالتعامل مع قناة البريد الإلكتروني. تنشئ الدالة <code>toMail</code> كائنا من صنف <code>MailMessage</code> لتخصيص بريد إلكتروني. سنعود لهذا الصنف بعد قليل.
	</li>
	<li>
		<code>toArray</code>: إن حدّدت قناة للإشعارات في الدالة <code>via</code> دون أن تنشئ دالة خاصّة للتعامل معها فسيستدعي Laravel الدالة <code>toArray</code>. تجدر الإشارة إلى أن الدوال المخصّصة للتعامل مع قنوات الإشعارات تبدأ بـ<code>to</code> متبوعة باسم القناة. مثلا <code>toMail</code> للبريد الإلكتروني (تأتي مبدئيا) و<code>toDatabase</code> لتخصيص الإشعار عبر قناة قاعدة البيانات.
	</li>
</ul>
<p>
	نعدّل الصنف <code>NewPost</code> قليلا بحيث نمرّر للمشيّد معطى من نوع <code>Post</code> (نزعنا أجزاء الصنف التي لم يطرأ عليها تعديل):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_15">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="com">// استدعاء الأصناف، أضفنا إليه الصنف Post</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Post</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">NewPost</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Notification</span><span class="pln">
</span><span class="pun">{</span><span class="pln">

    </span><span class="com">// أضفنا خاصيّة post إلى الصنف</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $post</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">Post</span><span class="pln"> $post</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">post </span><span class="pun">=</span><span class="pln"> $post</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>
	نعود إلى الدالة <code>notify</code> في المتحكم ونعدّلها لتصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_17">
<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">$user_id</span><span class="pun">,</span><span class="pln">$post_id</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="typ">User</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$user_id</span><span class="pun">);</span><span class="pln">
    $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$post_id</span><span class="pun">);</span><span class="pln">

    $user</span><span class="pun">-&gt;</span><span class="pln">notify</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">NewPost</span><span class="pun">(</span><span class="pln">$post</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استدعاء الصنف <code>NewPost</code> في المتحكم:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_19">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Notifications\NewPost</span><span class="pun">;</span></pre>

<p>
	استدعينا الدالة <code>notify</code> من الكائن <code>user$</code> ومررنا إليها صنفا جديدا من الإشعار <code>NewPost</code>.
</p>

<p>
	سنحتاج قبل تجربة إرسال الإشعار إلى ضبط البريد الإلكتروني في ملف النظام <code>env.</code>. ستجد في الملف عند فتحه الإعدادات التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_21">
<span class="pln">MAIL_DRIVER</span><span class="pun">=</span><span class="pln">smtp
MAIL_HOST</span><span class="pun">=</span><span class="pln">mailtrap</span><span class="pun">.</span><span class="pln">io
MAIL_PORT</span><span class="pun">=</span><span class="lit">2525</span><span class="pln">
MAIL_USERNAME</span><span class="pun">=</span><span class="kwd">null</span><span class="pln">
MAIL_PASSWORD</span><span class="pun">=</span><span class="kwd">null</span><span class="pln">
MAIL_ENCRYPTION</span><span class="pun">=</span><span class="kwd">null</span></pre>

<p>
	يقترح Laravel مبدئيا موقع <a href="mailtrap.io" rel="">https://mailtrap.io</a> الذي يوفر خدمة لمحاكاة إرسال بريد إلكتروني وعرضه. نحصُل بالتسجيل في الموقع على صندوق بريد للاختبار. ندخل إلى صندوق البريد (Demo inbox).
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19785" href="https://academy.hsoub.com/uploads/monthly_2016_11/01_mailtrap_credentials.png.dc0a94e1e2c1962044a0e10af1ef33af.png" rel=""><img alt="01_mailtrap_credentials.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19785" data-unique="mc80ycubx" src="https://academy.hsoub.com/uploads/monthly_2016_11/01_mailtrap_credentials.thumb.png.df68de4dfb2659a5d79863d1eff2d787.png"></a>
</p>

<p>
	ننسخ قيم <code>Username</code> و<code>Password</code> ونضيفها إلى الإعدادات في ملف <code>env.</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_23">
<span class="pln">MAIL_DRIVER</span><span class="pun">=</span><span class="pln">smtp
MAIL_HOST</span><span class="pun">=</span><span class="pln">mailtrap</span><span class="pun">.</span><span class="pln">io
MAIL_PORT</span><span class="pun">=</span><span class="lit">2525</span><span class="pln">
MAIL_USERNAME</span><span class="pun">=</span><span class="str">"be7c7d3972da27"</span><span class="pln">
MAIL_PASSWORD</span><span class="pun">=</span><span class="str">"5f445b7bdca027"</span><span class="pln">
MAIL_ENCRYPTION</span><span class="pun">=</span><span class="kwd">null</span></pre>

<p>
	يمكننا الآن اختبار الإشعار بتشغيل خادوم التطبيق والذهاب إلى المسار <code><a href="http://localhost:8000/notify/1/2" ipsnoembed="false" rel="external nofollow">http://localhost:8000/notify/1/2</a></code>. إن نظرت في صندوق البريد على موقع mailtrap فستجد رسالة جديدة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19786" href="https://academy.hsoub.com/uploads/monthly_2016_11/02_email_notification.png.960d12a11250093d3ff1fdf2e23da499.png" rel=""><img alt="02_email_notification.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19786" data-unique="3o4nyou5q" src="https://academy.hsoub.com/uploads/monthly_2016_11/02_email_notification.thumb.png.740976412e3ed1a0e26d2fbb4ae12887.png"></a>
</p>

<p>
	لاحظ العنوان البريدي الذي يُوجّه إليه الإشعار <code>medeyil@laravel.com</code>. إن عدلت المسار الذي تطلُبه إلى التالي <code><a href="http://localhost:8000/notify/2/2" ipsnoembed="false" rel="external nofollow">http://localhost:8000/notify/2/2</a></code> ونظرت في الإشعار الذي يصل إلى البريد فستجد أن المرسَل إليه <code>To</code> تبدّل إلى <code>fbenziane@laravel.com</code> الذي هو بريد المستخدم ذي المعرف <code>2</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19787" href="https://academy.hsoub.com/uploads/monthly_2016_11/03_email_notification.png.b944b200b099305f6d2243fe43824050.png" rel=""><img alt="03_email_notification.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19787" data-unique="mx2k8rqva" src="https://academy.hsoub.com/uploads/monthly_2016_11/03_email_notification.thumb.png.07d1e58a51307e615e6d449d13a76ae5.png"></a>
</p>

<p>
	هل تساءلت كيف يعرف نظام الإشعارات البريد الإلكتروني الذي يجب إرسال الإشعار إليه، أي البريد الإلكتروني الخاصّ بالمستخدِم؟
</p>

<h2 id="تخصيص-الإشعار-عبر-البريد-الإلكتروني">
	تخصيص الإشعار عبر البريد الإلكتروني
</h2>

<p>
	يمكن تطبيق الإشعارات على أي نموذج Eloquent في النظام، بشرط أن يستخدم النموذجُ السّمةَ Trait المسمّاة <code>Notifiable</code>. إن نظرنا إلى النموذج <code>User</code> الذي يأتي مبدئيا مع المشروع فسنلاحظ التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_25">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Notifications\Notifiable</span><span class="pun">;</span></pre>

<p>
	و
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_27">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Notifiable</span><span class="pun">;</span></pre>

<p>
	يتيح استخدام هذه السمة في النموذج إمكانية استدعاء الدالة <code>notify</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_29">
<span class="pln">$user</span><span class="pun">-&gt;</span><span class="pln">notify</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">NewPost</span><span class="pun">(</span><span class="pln">$post</span><span class="pun">));</span></pre>

<p>
	التي تأخذ معطى عبارة عن كائن من صنف <code>Notification</code>.
</p>

<p>
	بالنسبة لكيفية معرفة نظام الإشعارات ببريد المستخدم فالإجابة هي أن كل قناة إشعار تتطلّب وجود خاصيّات Properties معيّنة في النموذج الذي يستدعي الدالة <code>notify</code>. في حالة قناة البريد الإلكتروني فإن الخاصيّة المنتظرة هي - منطقيا - عنوان البريد <code>email</code>.
</p>

<p>
	بالعودة إلى الصنف <code>NewPost</code> لاحظ دالة التعامل مع البريد الإلكتروني:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_31">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> toMail</span><span class="pun">(</span><span class="pln">$notifiable</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="kwd">new</span><span class="pln"> </span><span class="typ">MailMessage</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">line</span><span class="pun">(</span><span class="str">'The introduction to the notification.'</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">action</span><span class="pun">(</span><span class="str">'Notification Action'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'https://laravel.com'</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">line</span><span class="pun">(</span><span class="str">'Thank you for using our application!'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجع هذه الدالة كائنا من صنف <code>MailMessage</code>. إن تنبهت جيدا فستدرك أن العبارات الواردة في الشفرة أعلاه هي نفسها الموجودة في البريد المرسَل إلى المستخدم:
</p>

<ul>
<li>
		الدالة <code>line</code> تدرج فقرة في بريد الإشعار.
	</li>
	<li>
		الدالة <code>action</code> تدرج زرًّا وتحدّد النص الذي يظهر على الزرّ ورابط الصفحة التي تزورها عند النقر على هذا الزرّ.
	</li>
</ul>
<p>
	توجد دوال أخرى لتخصيص الإشعار أكثر:
</p>

<ul>
<li>
		<code>subject</code> لتخصيص موضوع البريد الإلكتروني.
	</li>
	<li>
		<code>from</code> لتحديد بريد المرسِل.
	</li>
	<li>
		<code>attach</code> لإضافة ملف مرفَق.
	</li>
	<li>
		<code>priority</code> لتحديد الأولوية (<code>1</code> تعني أولوية قصوى).
	</li>
</ul>
<p>
	نخصّص في ما يلي البريد السّابق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_33">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> toMail</span><span class="pun">(</span><span class="pln">$notifiable</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="kwd">new</span><span class="pln"> </span><span class="typ">MailMessage</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">subject</span><span class="pun">(</span><span class="str">'New post: '</span><span class="pun">.</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">post</span><span class="pun">-&gt;</span><span class="pln">title</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">line</span><span class="pun">(</span><span class="str">'Don\'t miss our new post '</span><span class="pln"> </span><span class="pun">.</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">post</span><span class="pun">-&gt;</span><span class="pln">title</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">action</span><span class="pun">(</span><span class="str">'View the post'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'https://laravel.com'</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="pln">line</span><span class="pun">(</span><span class="str">'Thank you for your visit!'</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">-&gt;</span><span class="kwd">from</span><span class="pun">(</span><span class="str">'hsoub@academy.com'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نحصل بزيارة الرابط <code><a href="http://localhost:8000/notify/1/2" ipsnoembed="false" rel="external nofollow">http://localhost:8000/notify/1/2</a></code> على النتيجة أدناه.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19788" href="https://academy.hsoub.com/uploads/monthly_2016_11/04_email_notification.png.a110007a08c41209b369da40154d08bf.png" rel=""><img alt="04_email_notification.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19788" data-unique="252uzxt4e" src="https://academy.hsoub.com/uploads/monthly_2016_11/04_email_notification.thumb.png.2e5fa721eaaecdb03989bdede9cfa575.png"></a>
</p>

<p>
	بالنسبة لاسم التطبيق الذي يظهر في الإشعار فيمكن تعديله عن طريق التعليمة <code>name</code> في ملف الإعداد <code>config/app.php</code>. تأخذ التعليمة مبدئيا القيمة <code>Laravel</code>.
</p>

<p>
	إن أردت تخصيصا أكبر للبريد ومظهره فيمكنك ذلك بنشر <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">قالب Blade</a> الخاص بالبريد الإلكتروني للإشعار ومن ثم تخصيصه. نفذ الأمر التالي لنشر القالب:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8190_35">
<span class="pln">php artisan vendor</span><span class="pun">:</span><span class="pln">publish </span><span class="pun">--</span><span class="pln">tag</span><span class="pun">=</span><span class="pln">laravel</span><span class="pun">-</span><span class="pln">notifications</span></pre>

<p>
	ستجد القالب على المسار <code>resources/views/vendor/notifications/email.blade.php</code>؛ حيث يمكنك التعديل عليه بما تراه مناسبا.
</p>
]]></description><guid isPermaLink="false">390</guid><pubDate>Sun, 12 Mar 2017 11:18:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x645;&#x646;&#x634;&#x626; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x639;&#x644;&#x627;&#x645;&#x627;&#x62A; Query builder &#x644;&#x644;&#x62A;&#x62E;&#x627;&#x637;&#x628; &#x645;&#x639; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D8%B4%D8%A6-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-query-builder-%D9%84%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r398/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_10/2.png.d5c25b8c66b10d8318b4ff50f9063cf8.png" /></p>

<p>
	يأتي Laravel بإطار العمل <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-eloquent-orm-%D9%84%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r227/" rel="">Eloquent</a> مضمّنا مبدئيا؛ وهو ما يتيح بناء نماذج تُعالّج فيها البيانات وتُطبّق عليها القواعد التي تحكُم سير التطبيق. يُيسّر Eloquent كثيرا من الأمور على المطوِّر؛ إلا أنّه يمكن أن يكون أحيانا غير مناسب لتعقيد المشروع الذي تعمل عليه. يوفّر Laravel آلية للتعامل مع قواعد البيانات مباشرة دون الحاجة لربط كائنات التطبيق بجداول قاعدة البيانات. تُسمى هذه الآلية منشئ الاستعلامات Query builder. كانت الاستعلامات المعدّة بمنشئ الاستعلامات ترجع النتائج، في الإصدارات السابقة (قبل الإصدار 5.3) من Laravel، على هيئة مصفوفة Array؛ إلا أن الأمر تغيّر في الإصدار 5.3 وأصبحت أغلب دوالّ بناء الاستعلامات ترجع نتيجة من نوع Collection (مجموعة).
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="25185" data-unique="0iuv0j05z" src="https://academy.hsoub.com/uploads/monthly_2017_10/2.png.67062e12a2bb98998cf63fc203efead9.png" alt="2.png"></p>

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

<h2 id="أيهما-أستخدم-eloquent-أم-منشئ-الاستعلامات">
	أيهما أستخدم.. Eloquent أم منشئ الاستعلامات؟
</h2>

<p>
	يخضع تطوير البرمجيّات لإكراهات كثيرة، وهو ما يعني أن عليك أحيانا كتابة <a href="https://academy.hsoub.com/programming/php/laravel/%d8%a7%d8%b3%d8%aa%d8%ae%d8%af%d8%a7%d9%85-eloquent-orm-%d9%84%d9%84%d8%aa%d8%b9%d8%a7%d9%85%d9%84-%d9%85%d8%b9-%d9%82%d8%a7%d8%b9%d8%af%d8%a9-%d8%a7%d9%84%d8%a8%d9%8a%d8%a7%d9%86%d8%a7%d8%aa-%d9%81%d9%8a-laravel-5-r227/#%D8%AA%D9%86%D9%81%D9%8A%D8%B0-%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-sql-%D9%85%D8%A8%D8%A7%D8%B4%D8%B1%D8%A9" rel="">استعلامات SQL</a> للتخاطب مع قاعدة البيانات مباشرة. يتيح Eloquent آلية أنيقة للتعامل مع قاعدة البيانات بربطها بأصناف التطبيق ممّا يقلّل كثيرا من الحاجة لتدخّل المطوّر في تفاصيل تنفيذ العمليّات. تشمل التسهيلات التي يتيحها Eloquent:
</p>

<ul>
<li>
		التحقق المُستَتِر Dirty check: تحديث الحقول التي تغيّرت قيمتها فقط دون غيرها، عند تنفيذ استعلامات <code>UPDATE</code>.
	</li>
	<li>
		ربط النماذج <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%A3%D8%AD%D8%AF%D8%A7%D8%AB-events-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87%D8%A7-%D9%81%D9%8A-laravel-r305/" rel="">بأحداث Events</a>؛ مثلا ل<a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%A5%D8%B4%D8%B9%D8%A7%D8%B1%D8%A7%D8%AA-notifications-%D9%81%D9%8A-laravel-r390/" rel="">إشعار المستخدمين</a> أو تحديث إحصائيات عند إنشاء مستخدم جديد.
	</li>
	<li>
		إدارة الحذف اللطيف Soft delete: تعليم تسجيلة على أنها محذوفة بدلا من حذفها فعلا.
	</li>
	<li>
		تنفيذ آليات <a href="https://academy.hsoub.com/programming/php/laravel/%D8%B9%D9%84%D8%A7%D9%82%D8%A7%D8%AA-eloquent-%D9%88%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%AD%D8%AB%D9%8A%D8%AB-%D9%81%D9%8A-laravel-5-r193/" rel="">التحميل الحثيث Lazy loading</a> (طلب البيانات عند الحاجة إليها).
	</li>
</ul>
<p>
	يمكن - بالطبع - تطبيق هذه الآليات بنفسك دون الاعتماد على Eloquent؛ إلا أن ذلك سيأخذ وقتا. من الجيد أن يكون لديك سبب مقنع للوقت الذي ستمضيه في هذه المهمة بدلا من التركيز على أمور <strong><em>*قد*</em></strong> تكون أهم. سيكون مثاليّا جدا الحصولُ على كلّ هذه التسجيلات بدون دفع ثمن، إلا أن الأمور في الواقع ليست مثالية. الثمن الذي تدفعه مقابل التسهيلات التي يتضمّنها Eloquent - وأطر عمل ORM الأخرى، بغضّ النظر عن لغة البرمجة - هو سرعة تنفيذ الاستعلامات. على الجهة الأخرى، تمكّن كتابة الاستعلامات من الوصول إلى أقصى سرعة ممكنة في التنفيذ، مقابل التضحية بالجهد والوقت أثناء التطوير.
</p>

<p>
	لا يوجد مانع من مزج جميع الوسائل المتاحة أمامك؛ بل إن الأمر محبّذ. مثلا؛ استخدم Eloquent عندما تتعامل مع كيانات منفردة (استمارة تسجيل على موقع مثلا)، الجأ لمنشئ الاستعلامات في المهامّ التي تتطلب وقتا للتنفيذ (كيانات بالجملة Batch processing أو إعداد تقارير على سبيل المثال) واكتب استعلامات SQL مباشرة عندما تكون أمام استعلام شديد التعقيد.
</p>

<h2 id="الجديد-في-laravel-53">
	الجديد في Laravel 5.3
</h2>

<p>
	نستخدم منشئ الاستعلامات في المثال التالي للحصول على كافة المستخدمين (جدول <code>users</code> في قاعدة البيانات):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1770_7">
<span class="pln">DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span></pre>

<p>
	تكافئ التعليمة السابقة في نتيجتها تنفيذ الاستعلام التالي: 
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_1770_9">
<span class="pln">SELECT </span><span class="pun">*</span><span class="pln"> FROM users</span><span class="pun">;</span></pre>

<p>
	كانت النتيجة، في الإصدارات السابقة من Laravel، من نوع Array (مصفوفة)؛ إلا أن هذا الأمر تغيّر في الإصدار 5.3 لتصبح النتيجة من نوع Collection (مجموعة). يعني هذا أنه للوصول إلى العنصر الأول في مجموعة المستخدمين السابقة فإننا يمكن أن نكتب:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1770_11">
<span class="pln">DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">()-&gt;</span><span class="pln">first</span><span class="pun">();</span></pre>

<p>
	بدلا من:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1770_13">
<span class="pln">DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">()[</span><span class="lit">0</span><span class="pun">];</span></pre>

<p>
	يجعل هذا التغيير من منشئ الاستعلامات متناسقا في نوع النتيجة مع Eloquent الذي يرجع مجموعة كائنات؛ كما أنه يمكّن من استخدام الدوال الموجودة مبدئيا <a href="https://laravel.com/docs/5.3/collections#available-methods" rel="external nofollow">للتعامل مع المجموعات</a>؛ ومن بينها الدالة <code>all</code> التي ترجع مصفوفة مكافئة للمجموعة؛ مثلا ترجع التعليمة التالية مصفوفة بالمستخدمين:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1770_15">
<span class="pln">DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">()-&gt;</span><span class="pln">all</span><span class="pun">();</span></pre>

<p>
	إن كان لديك تطبيق مبني على اعتبار أن منشئ الاستعلامات يُرجع النتائج على هيئة مصفوفات، فأسهل طريقة لتعديل الشفرة المصدرية للتوافق مع تغيير نوع النتيجة إلى مجموعة بدلا من مصفوفة؛ هي استخدام الدالة <code>all.</code>
</p>

<p>
	<strong>ملحوظة 1:</strong> لا ينطبق التغيير المذكور أعلاه (إرجاع مجموعة بدلا من مصفوفة) على دوال الصنف <code>DB</code> التي تتعامل مع استعلامات SQL مباشرة. مثلا؛ ترجع التعليمة التالية مصفوفة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1770_17">
<span class="pln">DB</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="str">'SELECT name FROM users WHERE id = ?'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span></pre>

<p>
	<strong>ملحوظة 2:</strong> انتبه عند استخدام استعلامات SQL مباشرة من ثغرات الحَقن SQL injection. استخدم ربط المتغيّرات Binding (كما في الملحوظة 1) بدلا من تمرير المتغيّر مباشرة كما في الاستعلام التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1770_19">
<span class="pln">DB</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="str">"SELECT name FROM users WHERE id = '$id' "</span><span class="pun">]);</span></pre>

<p>
	قد يمثل الاستعلام الأخير خطرا إن لم يُتحقّق من المتغيّر<code>id$</code> قبل استخدامه في الاستعلام. يتحقّق Laravel تلقائيا من المُدخلات عند ربط المتغيّرات كما في استعلام <strong>الملحوظة 1</strong>.
</p>

<p>
	راجع مقال<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-eloquent-orm-%D9%84%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r227/" rel=""> استخدام Eloquent ORM للتعامل مع قاعدة البيانات في Laravel 5</a>.
</p>
]]></description><guid isPermaLink="false">398</guid><pubDate>Wed, 08 Mar 2017 09:02:00 +0000</pubDate></item><item><title>&#x62A;&#x62E;&#x635;&#x64A;&#x635; &#x627;&#x644;&#x62A;&#x651;&#x635;&#x641;&#x64A;&#x62D; Pagination &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AE%D8%B5%D9%8A%D8%B5-%D8%A7%D9%84%D8%AA%D9%91%D8%B5%D9%81%D9%8A%D8%AD-pagination-%D9%81%D9%8A-laravel-r391/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_10/3.png.d2f4e67eaf60c700b42affe2ecbdaa24.png" /></p>

<p>
	يعدّ التصفيح Pagination (إعداد الصفحات) إحدى المهامّ الشائعة في مواقع الوِب، وهو ما دعا Laravel لتضمين هذه الوظيفة مبدئيا في إطار العمل. كانت تخصيص التصفيح في الإصدارات الأولى من Laravel بسهولة إعداد <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">قالب Blade</a>؛ إلا أن الأمر تغيّر في الإصدار 5.0، إذ عمل إطار العمل على تسهيل نظام التصفيح الذي يستخدمه لتمكن إعادة استخدامه في مشاريع لا تعتمد على إطار العمل Laravel. صاحب هذه العمليّة تعقيد في إمكانيّة تخصيص التصفيح.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="25187" data-unique="0kjtljxbq" src="https://academy.hsoub.com/uploads/monthly_2017_10/3.png.b777211ef6609a8271b1f70af8f97964.png" alt="3.png"></p>

<p>
	يأتي <a href="https://academy.hsoub.com/tags/laravel%205.3/" rel="">الإصدار 5.3</a> لتصحيح هذه الوضعية وإعادة الأمور إلى نصابها.
</p>

<h2 id="تهيئة-المشروع">
	تهيئة المشروع
</h2>

<p>
	سنهيّئ مشروع Laravel 5.3 للعمل عليه. نبدأ بالتثبيت:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_7">
<span class="pln">composer create</span><span class="pun">-</span><span class="pln">project </span><span class="pun">--</span><span class="pln">prefer</span><span class="pun">-</span><span class="pln">dist laravel</span><span class="pun">/</span><span class="pln">laravel laravel53pagination </span><span class="str">"5.3.*"</span></pre>

<p>
	يأتي المشروع مبدئيا بنموذج للمستخدم <code>User</code>، سنعمل من أجل الشرح على هذا النموذج. نبدأ بإعداد مسار للمستخدمين في <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D9%8A%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%8A-%D8%B7%D8%B1%D8%A3%D8%AA-%D8%B9%D9%84%D9%89-%D9%87%D9%8A%D9%83%D9%84%D8%A9-%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-laravel-%D9%81%D9%8A-%D8%A7%D9%84%D8%A5%D8%B5%D8%AF%D8%A7%D8%B1-53-r388#%D9%85%D9%84%D9%81-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%A7%D8%AA-routes" rel="">ملف المسارات الخاصّ بالوِب</a> <code>routes/web.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_9">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'users'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'users.index'</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">User</span><span class="pun">::</span><span class="pln">paginate</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يطلُب المسار <code>users/</code> عند زيارته عرضَ القالب <code>index.blade.php</code> الموجود في المجلّد <code>users</code> ضمن مجلد القوالب <code>resources/views</code>. نمرّر للقالب المتغيّر <code>users</code> الذي يتلقّى نتيجة استدعاء الدالة <code>paginate</code> للحصول على المستخدمين المسجلين في قاعدة البيانات. ما يميّز هذه الدالة عن بقيّة الدوال الأخرى التي يمكن استدعاؤها في النموذج هي أنها توفّر إمكانية تطبيق الدالة <code>links</code> في قالب Blade من أجل إنشاء الصفحات، كما سنرى الآن.
</p>

<p>
	ليس لدينا لحد الساعة المجلد <code>users</code> ولا الملف <code>index.blade.php</code>، ننشئ المجلد والملف بحيث يصبح مسار ملف القالب <code>resources/views/users/index.blade.php</code> ثم نفتحه ونضيف إليه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_11">
<span class="dec">&lt;!DOCTYPE html&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;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="pln">  </span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;title&gt;</span><span class="pln"> Document </span><span class="tag">&lt;/title&gt;</span><span class="pln">
</span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/css/app.css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;style</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/css"</span><span class="tag">&gt;</span><span class="pln"> body </span><span class="pun">{</span><span class="pln"> padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">10em</span><span class="pun">;}</span><span class="tag">&lt;/style&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">
@foreach ($users as $user)
    </span><span class="tag">&lt;li&gt;</span><span class="pln">{{ $user-&gt;name }}</span><span class="tag">&lt;/li&gt;</span><span class="pln">
@endforeach

{{ $users-&gt;links() }}
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	لدينا في أعلى الملف بضعة تعليمات للتنسيق، ثم تأتي في جسم المستند <code>body</code> التعليمة التكرارية <code>foreach</code> التي تمرّ على المستخدمين وتعرض أسماءهم، وفي الأخير الدالة <code>links</code> التي تحدثنا عنها أعلاه. يمكننا استدعاء هذه الدالة على المتغيّر <code>users</code> نظرا لأننا استخدمنا الدالة <code>paginate</code> في ملف المسارات للحصول على المستخدمين. تتكفّل الدالة <code>links</code> بإنشاء الصفحات عبر تقسيم المستخدمين على مجموعة من خمسة عناصر (مرّرنا المعطى <code>5</code> للدالة <code>paginate</code> في ملف المسارات).
</p>

<p>
	بقي لنا بذر جدول المستخدمين حتى يمكننا تجربة ما أنجزناه لحد الآن:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_13">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">UsersTableSeeder</span></pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_15">
<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">
  </span><span class="typ">User</span><span class="pun">::</span><span class="pln">unguard</span><span class="pun">();</span><span class="pln">

  </span><span class="com">// نستخدم Faker لتوليد البيانات</span><span class="pln">
  $faker </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Faker</span><span class="pln">\Factory</span><span class="pun">::</span><span class="pln">create</span><span class="pun">();</span><span class="pln">

  </span><span class="com">// إنشاء 20 مستخدما</span><span class="pln">
  </span><span class="kwd">foreach</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">20</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $index</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="pln">create</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"> $faker</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">,</span><span class="pln">
          </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">safeEmail</span><span class="pun">,</span><span class="pln">
          </span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">password</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="typ">User</span><span class="pun">::</span><span class="pln">reguard</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استيراد النموذج:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_17">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\User</span><span class="pun">;</span></pre>

<p>
	ثم نعدّل <code>DatabaseSeeder</code> لإضافة ملف البذر الذي أنشأناه للتو:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_19">
<span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">UsersTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span></pre>

<p>
	يمكننا الآن تنفيذ التهجيرات (تهجير المستخدم يأتي مبدئيا مع المشروع):
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_21">
<span class="pln">php artisan migrate</span></pre>

<p>
	ثم بذر قاعدة البيانات:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_23">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<p>
	ثم تشغيل خادوم التطوير:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_25">
<span class="pln">php artisan serve</span></pre>

<p>
	تظهر عند زيارة الرابط <code><a href="http://localhost:8000/users" ipsnoembed="false" rel="external nofollow">http://localhost:8000/users</a></code> قائمة بالمستخدمين مقسّمة على صفحات من خمسة مستخدمين.
</p>

<p>
	<img alt="01_pagination.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19856" data-unique="haoitunbj" src="https://academy.hsoub.com/uploads/monthly_2016_11/01_pagination.png.a395429781b2febbd2a36835ae1189f0.png"></p>

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

<h2 id="تخصيص-التصفيح-في-laravel">
	تخصيص التصفيح في Laravel
</h2>

<p>
	يوجد القالب المبدئي لروابط الصفحات على المسار <code>vendor/laravel/framework/src/Illuminate/Pagination/resources/views</code> إن أردت تخصيصه فسيتوجّب عليك نشره بالأمر التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_27">
<span class="pln">php artisan vendor</span><span class="pun">:</span><span class="pln">publish </span><span class="pun">--</span><span class="pln">tag</span><span class="pun">=</span><span class="pln">laravel</span><span class="pun">-</span><span class="pln">pagination</span></pre>

<p>
	وستجد بضعة قوالب على المسار <code>ressources/views/vendor/pagination</code>.<br>
	يستخدم اثنان من هذه القوالب (<code>bootstrap-4.blade.php</code> و<code>simple-boostrap-4.blade.php</code>) الإصدار 4 من Bootstrap والذي ما زال قيد التطوير؛ أما الآخران فأحدهما هو القالب المبدئي <code>default.blade.php</code> والآخر (<code>simple-default.blade.php</code>) نسخة مبسّطة منه لا تحوي سوى أزرار سابق ولاحق للتنقل بين الصفحات.
</p>

<p>
	أدناه الشفرة الخاصّة بالقالب المبدئي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_29">
<span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$paginator</span><span class="pun">-&gt;</span><span class="pln">hasPages</span><span class="pun">())</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">"pagination"</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Previous</span><span class="pln"> </span><span class="typ">Page</span><span class="pln"> </span><span class="typ">Link</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
        </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$paginator</span><span class="pun">-&gt;</span><span class="pln">onFirstPage</span><span class="pun">())</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">"disabled"</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;«&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="lit">@else</span><span class="pln">
            </span><span class="str">&lt;li&gt;</span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ $paginator-&gt;previousPageUrl() }}"</span><span class="pln"> rel</span><span class="pun">=</span><span class="str">"prev"</span><span class="pun">&gt;«&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="lit">@endif</span><span class="pln">

        </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Pagination</span><span class="pln"> </span><span class="typ">Elements</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
        </span><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$elements </span><span class="kwd">as</span><span class="pln"> $element</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{{--</span><span class="pln"> </span><span class="str">"Three Dots"</span><span class="pln"> </span><span class="typ">Separator</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
            </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_string</span><span class="pun">(</span><span class="pln">$element</span><span class="pun">))</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">"disabled"</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;{{</span><span class="pln"> $element </span><span class="pun">}}&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="lit">@endif</span><span class="pln">

            </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Array</span><span class="pln"> </span><span class="typ">Of</span><span class="pln"> </span><span class="typ">Links</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
            </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_array</span><span class="pun">(</span><span class="pln">$element</span><span class="pun">))</span><span class="pln">
                </span><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$element </span><span class="kwd">as</span><span class="pln"> $page </span><span class="pun">=&gt;</span><span class="pln"> $url</span><span class="pun">)</span><span class="pln">
                    </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$page </span><span class="pun">==</span><span class="pln"> $paginator</span><span class="pun">-&gt;</span><span class="pln">currentPage</span><span class="pun">())</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">"active"</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;{{</span><span class="pln"> $page </span><span class="pun">}}&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="lit">@else</span><span class="pln">
                        </span><span class="str">&lt;li&gt;</span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ $url }}"</span><span class="pun">&gt;{{</span><span class="pln"> $page </span><span class="pun">}}&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="lit">@endif</span><span class="pln">
                </span><span class="lit">@endforeach</span><span class="pln">
            </span><span class="lit">@endif</span><span class="pln">
        </span><span class="lit">@endforeach</span><span class="pln">

        </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Next</span><span class="pln"> </span><span class="typ">Page</span><span class="pln"> </span><span class="typ">Link</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
        </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$paginator</span><span class="pun">-&gt;</span><span class="pln">hasMorePages</span><span class="pun">())</span><span class="pln">
            </span><span class="str">&lt;li&gt;</span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ $paginator-&gt;nextPageUrl() }}"</span><span class="pln"> rel</span><span class="pun">=</span><span class="str">"next"</span><span class="pun">&gt;»&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="lit">@else</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">"disabled"</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;»&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="lit">@endif</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="lit">@endif</span></pre>

<ul>
<li>
		تتيح الدالة <code>hasPages</code> التحقق من وجود صفحات لعرضها.
	</li>
	<li>
		نتحقّق بالدالة <code>onFirstPage</code> من أننا على الصفحة الأولى.
	</li>
	<li>
		يمكن بالدالة <code>hasMorePages</code> معرفة ما إذا كان لدينا مزيد من الصفحات لعرضها.
	</li>
	<li>
		تطبع الدالتان <code>previousPageUrl</code> و<code>nextPageUrl</code>على التوالي رابطي الصفحة السابقة واللاحقة للصفحة الحالية التي نحصل عليها بالدالة <code>currentPage</code>.
	</li>
</ul>
<p>
	سنعدّل الآن القالب بحيث نضع كلمة <code>Previous</code> (السابق) مكان الرمز <code>»</code>، على ألا تظهر عندما نكون على الصفحة الأولى.
</p>

<p>
	<img alt="02_pagination.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19857" data-unique="xbv6r3fvm" src="https://academy.hsoub.com/uploads/monthly_2016_11/02_pagination.png.c59e1355e721c584bfc643470732aad4.png"></p>

<p>
	نضع بنفس الطريقة كلمة <code>Next</code> (التالي) مكان <code>«</code>، على ألا تظهر عندما نكون على الصفحة الأخيرة.
</p>

<p>
	<img alt="03_pagination.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19858" data-unique="nqmayutfu" src="https://academy.hsoub.com/uploads/monthly_2016_11/03_pagination.png.784b73c9c682dcba5502eb6172455c16.png"></p>

<p>
	نحصُل على الشفرة التاليّة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4082_31">
<span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$paginator</span><span class="pun">-&gt;</span><span class="pln">hasPages</span><span class="pun">())</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">"pagination"</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Previous</span><span class="pln"> </span><span class="typ">Page</span><span class="pln"> </span><span class="typ">Link</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
        </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">$paginator</span><span class="pun">-&gt;</span><span class="pln">onFirstPage</span><span class="pun">())</span><span class="pln">
            </span><span class="str">&lt;li&gt;</span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ $paginator-&gt;previousPageUrl() }}"</span><span class="pln"> rel</span><span class="pun">=</span><span class="str">"prev"</span><span class="pun">&gt;</span><span class="typ">Previous</span><span class="pun">&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="lit">@endif</span><span class="pln">

        </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Pagination</span><span class="pln"> </span><span class="typ">Elements</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
        </span><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$elements </span><span class="kwd">as</span><span class="pln"> $element</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{{--</span><span class="pln"> </span><span class="str">"Three Dots"</span><span class="pln"> </span><span class="typ">Separator</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
            </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_string</span><span class="pun">(</span><span class="pln">$element</span><span class="pun">))</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">"disabled"</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;{{</span><span class="pln"> $element </span><span class="pun">}}&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="lit">@endif</span><span class="pln">

            </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Array</span><span class="pln"> </span><span class="typ">Of</span><span class="pln"> </span><span class="typ">Links</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
            </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_array</span><span class="pun">(</span><span class="pln">$element</span><span class="pun">))</span><span class="pln">
                </span><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$element </span><span class="kwd">as</span><span class="pln"> $page </span><span class="pun">=&gt;</span><span class="pln"> $url</span><span class="pun">)</span><span class="pln">
                    </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$page </span><span class="pun">==</span><span class="pln"> $paginator</span><span class="pun">-&gt;</span><span class="pln">currentPage</span><span class="pun">())</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">"active"</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;{{</span><span class="pln"> $page </span><span class="pun">}}&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="lit">@else</span><span class="pln">
                        </span><span class="str">&lt;li&gt;</span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ $url }}"</span><span class="pun">&gt;{{</span><span class="pln"> $page </span><span class="pun">}}&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="lit">@endif</span><span class="pln">
                </span><span class="lit">@endforeach</span><span class="pln">
            </span><span class="lit">@endif</span><span class="pln">
        </span><span class="lit">@endforeach</span><span class="pln">

        </span><span class="pun">{{--</span><span class="pln"> </span><span class="typ">Next</span><span class="pln"> </span><span class="typ">Page</span><span class="pln"> </span><span class="typ">Link</span><span class="pln"> </span><span class="pun">--}}</span><span class="pln">
        </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$paginator</span><span class="pun">-&gt;</span><span class="pln">hasMorePages</span><span class="pun">())</span><span class="pln">
            </span><span class="str">&lt;li&gt;</span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ $paginator-&gt;nextPageUrl() }}"</span><span class="pln"> rel</span><span class="pun">=</span><span class="str">"next"</span><span class="pun">&gt;</span><span class="typ">Next</span><span class="pun">&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="lit">@endif</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="lit">@endif</span></pre>

<p>
	احفظ التعديلات ثم أعد تنزيل الصفحة للحصول على نتيجة مشابهة لتلك الظاهرة في الصورتين أعلاه.
</p>
]]></description><guid isPermaLink="false">391</guid><pubDate>Thu, 02 Mar 2017 11:42:00 +0000</pubDate></item><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x62E;&#x628;&#x626;&#x629; Cache &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AE%D8%A8%D8%A6%D8%A9-cache-%D9%81%D9%8A-laravel-r389/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/laravel-cache.png.4ea070914f28933126bfd62014fd979e.png" /></p>

<p>
	يوفّر Laravel واجهة تطبيقات برمجية موّحدة للتعامل مع أنظمة تخبئة Cache مختلفة مثل <a href="https://academy.hsoub.com/tags/memcached/" rel="">Memcached</a> و<a href="https://academy.hsoub.com/tags/redis" rel="">Redis</a>.
</p>

<p>
	سنعرض في هذا المقال لكيفية إعداد التخبئة في Laravel ومبدأ عملها ثم نتطرق للدالة المساعدة <code>cache</code> التي أضيفت إلى إطار العمل بداية من الإصدار 5.3.
</p>

<p style="text-align: center;">
	<img alt="laravel-cache.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22004" data-unique="l3mg0kkwv" src="https://academy.hsoub.com/uploads/monthly_2017_02/laravel-cache.png.7190b6ca86f8303dc723d867b3ffbc0c.png" style=""></p>

<h2 id="تهيئة-بيئة-التطوير">
	تهيئة بيئة التطوير
</h2>

<p>
	يُحدَّد اسم النظام المستخدَم في التعليمة <code>CACHE_DRIVER</code> ضمن ملف <code>env.</code>. تأخذ التعليمة <code>CACHE_DRIVER</code> مبدئيا القيمة <code>file</code> التي تعني أن الكائنات Objects المخبَّأة ستخزن ضمن ملف ضمن نظام التشغيل. تُضبَط إعدادات نظام التخبئة المستخدَم في الملف <code>config/cache.php</code>، بعد تعيينه بالتعليمة السابقة.
</p>

<p>
	نفترض أنك لديك مشروع Laravel بالإصدار 5.3 للتطبيق عليه. ننفذ الخطوات التالية لتهيئة مثال نعتمد عليه في ما بعد للشرح.
</p>

<h3 id="إنشاء-نموذج-والتهجير-المصاحب-له-وبذره">
	إنشاء نموذج والتهجير المصاحب له وبذره
</h3>

<p>
	نستخدم <code>artisan</code> لإنشاء نموذج Eloquent مع التهجير المصاحب له على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6060_7">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">model </span><span class="typ">Post</span><span class="pln"> </span><span class="pun">-</span><span class="pln">m</span></pre>

<p>
	نفتح ملف التهجير لضبط الحقول في جدول البيانات بإضافة حقل جديد يُسمّى<code>title</code> (العنوان):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6060_9">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">"title"</span><span class="pun">);</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</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_3723_7">
<span class="pln">php artisan migrate</span></pre>

<p>
	الخطوة التالية هي بذر الجدول الحصول على بيانات للتطبيق عليها. ننشئ ملف البذر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_9">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">PostsTableSeeder</span></pre>

<p>
	ثم نعدل عليه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_11">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">PostsTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</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">
    </span><span class="typ">Model</span><span class="pun">::</span><span class="pln">unguard</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// نستورد faker لبذر الجدول</span><span class="pln">
    $faker </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Faker</span><span class="pln">\Factory</span><span class="pun">::</span><span class="pln">create</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// ننشئ 10 تسجيلات في الجدول</span><span class="pln">
    </span><span class="kwd">foreach</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"> $index</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">create</span><span class="pun">([</span><span class="pln">
            </span><span class="str">'title'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">sentence</span><span class="pun">(</span><span class="lit">5</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="typ">Model</span><span class="pun">::</span><span class="pln">reguard</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نعدّل ملف بذر قاعدة البيانات لإضافة ملف بذر الجدول <code>posts</code> إليه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_13">
<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">call</span><span class="pun">(</span><span class="typ">PostsTableSeeder</span><span class="pun">::</span><span class="kwd">class</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_3723_15">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed </span><span class="pun">--</span><span class="kwd">class</span><span class="pun">=</span><span class="typ">PostsTableSeeder</span></pre>

<p>
	لدينا الآن جدول بيانات بـ10 تسجيلات. أكملنا إعداد النموذج الذي نريد العمل عليه، الخطوة الموالية هي إعداد المتحكم والمسارات.
</p>

<h3 id="المتحكم-والمسارات">
	المتحكم والمسارات
</h3>

<p>
	نستعين بأداة <code>artisan</code> لإنشاء متحكم على النحو التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_17">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">PostsController</span></pre>

<p>
	ننشئ في المتحكم <code>PostsController</code> دالة باسم <code>index</code> نستخدمها للحصول على جميع المنشورات الموجودة في جدول البيانات <code>posts</code> بصيغة JSON:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_19">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$posts</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استيراد النموذج <code>Post</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_21">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Post</span><span class="pun">;</span></pre>

<p>
	ثم ننتقل إلى إعداد المسارات. سنضيف مسارا باسم <code>posts/</code> إلى ملف مسارات واجهةالوب <code>routes/web.php</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_23">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/posts'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'PostsController@index'</span><span class="pun">);</span></pre>

<p>
	يمكننا الآن تنفيذ الأمر <code>php artisan serve</code> من مجلد المشروع لتشغيل الخادوم الخاص ببيئة التطوير ثم الذهاب إلى الرابط <code><a href="http://localhost:8000/posts" ipsnoembed="false" rel="external nofollow">http://localhost:8000/posts</a></code> لرؤية جميع المنشورات المحفوظة في الجدول.
</p>

<h2 id="إعداد-التخبئة-واستخدامها">
	إعداد التخبئة واستخدامها
</h2>

<p>
	تُضبَط التخبئة - كما أسلفنا - في الملفين <code>env.</code> و<code>config/cache.php</code>. يحوي الصنف <code>Illuminate\Support\Facades\Cache</code> الكثير من الدوال الثابتة Static التي تتعامل مع التخبئة.
</p>

<h3 id="إضافة-قيمة-إلى-التخبئة">
	إضافة قيمة إلى التخبئة
</h3>

<p>
	تُستخدَم الدالة <code>Cache::put</code> لإضافة قيمة إلى التخبئة. تأخذ الدالة ثلاثة معطيات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_25">
<span class="typ">Cache</span><span class="pun">::</span><span class="pln">put</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'value'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span></pre>

<ul>
<li>
		مفتاح <code>key</code> يمثل اسم المتغير. لا يمكن أن تحمل قيمتان في النظام نفس المفتاح.
	</li>
	<li>
		قيمة المفتاح <code>value</code>.
	</li>
	<li>
		مدة زمنية معبَّر عنها بالدقائق (<code>10</code> في المثال أعلاه)، وتمثل المدة التي سيحتفظ النظام فيها بقيمة المفتاح ضمن التخبئة.
	</li>
</ul>
<p>
	تمكن أتمتة إضافة المفاتيح إلى التخبئة بالدالة <code>remember</code>. تبحث هذه الدالة أولا عن قيمة المفتاح في التخبئة، وترجعها إن وجدته؛ فإن لم تجده تنشئ المفتاح وتعطيه القيمة التي ترجعها دالة الإغلاق Closure الممررة في المعطى الثالث.<br>
	سنستخدم الدالة <code>remember</code> في دالة <code>index</code> التي أضفناها سابقا إلى المتحكم. نعدّل الدالة <code>index</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_27">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Cache</span><span class="pun">::</span><span class="pln">remember</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</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">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</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"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$posts</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا ننسى استدعاء الصنف <code>Cache</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_29">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Cache</span><span class="pun">;</span></pre>

<p>
	تعني الشفرة أعلاه أننا عند طلب الدالة <code>index</code> فإنها ستبحث عن المنشورات الموجودة في التخبئة، فإن وجدتها ترجعها وإلا فإنها تنشئها باستدعاء الدالة <code>all</code> من النموذج <code>Post</code>؛ وتحتفظ بها في التخبئة لمدة خمس دقائق؛ ثم ترجع النتيجة.
</p>

<p>
	بهذا تكون جميع الطلبات التي ترد إلى المسار <code>posts/</code> تمر عبر التخبئة؛ سنضيف لأغراض التوضيح مسارا جديدا (ضمن <code>routes/web.php</code>) لنعدل عن طريقه على إحدى التسجيلات الموجودة في جدول المنشورات:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_31">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/edit/post/{id}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'PostsController@edit'</span><span class="pun">);</span></pre>

<p>
	ونعدّل المتحكم بإضافة الدالة <code>edit</code> التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_33">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> edit</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
    $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">=</span><span class="pln"> </span><span class="str">"New title for "</span><span class="pun">.</span><span class="pln">$id</span><span class="pun">;</span><span class="pln">
    $post</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">
    $posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$posts</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ما يحدث هو التالي: تظهر عند زيارة الرابط <code>posts/</code> المنشورات مع المرور على نظام التخبئة؛ أما عند زيارة المسار <code>edit/post/id/</code> فسنعدّل على المنشور ذي المعرف <code>id</code>، ثم نعرض المنشورات المخزنة في الجدول مباشرة، دون البحث عنها في التخبئة.
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19784" href="https://academy.hsoub.com/uploads/monthly_2016_11/01_laravel_cache.gif.fff946c56676227108fbca2acbbdbf8c.gif" rel=""><img alt="01_laravel_cache.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="19784" data-unique="43ka80uu2" src="https://academy.hsoub.com/uploads/monthly_2016_11/01_laravel_cache.thumb.gif.bd1685778c8425ed3ed71dbbe5962e99.gif"></a>
</p>

<ul>
<li>
		تكون التخبئة فارغة عند زيارة المسار <code>posts/</code> لأول مرة. في هذه الحالة يطلب Laravel المنشورات مباشرة من جدول البيانات، يعرضها ثم يضيفها إلى التخبئة.
	</li>
	<li>
		نطلب الرابط <code>edit/post/1/</code> الذي يغيّر عنوان المنشور ذي المعرف <code>1</code> ليصبح <code>New title for 1</code>؛ ثم يعرض المنشورات بطلبها مباشرة من جدول قاعدة البيانات. لاحظ تغير عنوان المنشور.
	</li>
	<li>
		نعود للرابط <code>posts/</code> قبل انقضاء المدة المحددة في دالة التخبئة (5 دقائق)، نلاحظ أن التعديل الذي أجريناه لا يظهر في المنشورات المعروضة.
	</li>
</ul>
<p>
	<strong>ملحوظة:</strong> يجب التأكد في التطبيقات الموجهة لبيئة الإنتاج من تناسق عمليات التعديل على قاعدة البيانات والتخبئة. بمعنى أنه يجب أن ينعكس التعديل على قيمة في جدول البيانات مباشرة على القيمة المحفوظة في التخبئة.
</p>

<h3 id="العمليات-على-التخبئة">
	العمليات على التخبئة
</h3>

<ul>
<li>
		<p>
			الحصول على قيمة من التخبئة:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_35">
<span class="typ">Cache</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

		<p>
			يمكن إرجاع قيمة مبدئية في حال عدم وجود المفتاح في التخبئة:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_37">
<span class="typ">Cache</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'default'</span><span class="pun">);</span></pre>

		<p>
			تبحث الدالة أعلاه عن قيمة المفتاح <code>key</code> في التخبئة، فإن لم تجدها ترجع القيمة المبدئية <code>default</code>.
		</p>
	</li>
	<li>
		<p>
			التحقق من وجود مفتاح في التخبئة:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_39">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Cache</span><span class="pun">::</span><span class="pln">has</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">)){</span><span class="pln">
    </span><span class="typ">Cache</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'key'</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">Cache</span><span class="pun">::</span><span class="pln">put</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">,</span><span class="pln"> $values</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></pre>

		<p>
			نتحقق في الشفرة أعلاه من وجود قيمة للمفتاح <code>key</code> ونرجعها إن وجدت؛ وإلا نضيف قيمة جديدة للمفتاح في التخبئة.
		</p>
	</li>
	<li>
		<p>
			نزع مفتاح من التخبئة:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_41">
<span class="typ">Cache</span><span class="pun">::</span><span class="pln">forget</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

		<p>
			كما يمكن استخدام الدالة <code>pull</code> التي تبحث عن قيمة في التخبئة، ثم تحذفها بعد الحصول عليها:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_43">
<span class="typ">Cache</span><span class="pun">::</span><span class="pln">pull</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

		<p>
			يشبه الأمر تنفيذ الدالتين <code>get</code> و<code>forget</code> بالتتالي.
		</p>

		<p>
			توجد طريقة أخرى لحذف محتوى التخبئة قبل انتهاء المدة المحددة له بتنفيذ أمر <code>artisan</code> التالي:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_45">
<span class="pln">php artisan cache</span><span class="pun">:</span><span class="pln">clear</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2 id="الدالة-المساعدة-cache">
	الدالة المساعدة cache
</h2>

<p>
	يحتوي إطار العمل Laravel على الكثير من دوال PHP المساعدة؛ بعضها مستخدَم في وظائف إطار العمل نفسه. تعمل <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D9%85%D8%AE%D8%B5%D8%B5%D8%A9-custom-helpers-%D9%81%D9%8A-laravel-5-r236/" rel="">الدوال المساعدة</a> Helper functions على الرفع من الإنتاجية والابتعاد عن تكرار الشفرات البرمجية بتجميع وظائف اعتيادية وإتاحة الوصول إليها حيث دعت الحاجة.<br>
	يضيف الإصدار 5.3 دالة مساعدة جديدة باسم <code>cache</code> يمكن استخدامها في أي جزء من المشروع من أجل تسهيل التخاطب مع نظام التخبئة، بدلا من الصّنف <code>Illuminate\Support\Facades\Cache</code>.
</p>

<p>
	نحصل على قيمة المتغير <code>key</code> (المفتاح) باستخدام الدالة المساعدة <code>cache</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_47">
<span class="pln">cache</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

<p>
	تكافئ التعليمة أعلاه استخدام الصنف <code>Cache</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_49">
<span class="typ">Cache</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

<p>
	يمكن أيضا تمرير مصفوفة بالمفاتيح وقيمها إلى الدالة <code>cache</code>؛ ونحدّد المدة الزمنية التي نريد أن تستغرقها التخبئة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_51">
<span class="pln">cache</span><span class="pun">([</span><span class="str">'title'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Hsoub Academy'</span><span class="pun">],</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span></pre>

<p>
	إن طلبنا في الخمس دقائق القادمة قيمة المفتاح <code>title</code> في الدالة <code>cache</code> فسنجد القيمة <code>Hsoub Academy</code>.
</p>

<p>
	نستخدم الدوال الموجودة في الصنف <code>Cache</code> في الدالة المساعدة <code>cache</code> بنفس الطريقة:
</p>

<ul>
<li>
		<p>
			إضافة مفتاح إلى التخبئة:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_53">
<span class="pln">cache</span><span class="pun">()-&gt;</span><span class="pln">put</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'value'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span></pre>

		<p>
			أو
		</p>

		<pre>
 </pre>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_55">
<span class="pln">cache</span><span class="pun">([</span><span class="str">'key'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'value'</span><span class="pun">],</span><span class="lit">10</span><span class="pun">);</span></pre>

		<p>
			البحث عن قيمة المفتاح في التخبئة، وإضافته إليها إن لم يوجد بها:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_59">
<span class="pln">cache</span><span class="pun">()-&gt;</span><span class="pln">remember</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</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">
    </span><span class="com">//</span><span class="pln">
</span><span class="pun">});</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			الحصول على قيمة مفتاح من التخبئة ثم حذفه منها بعد ذلك:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_61">
<span class="pln">cache</span><span class="pun">()-&gt;</span><span class="pln">pull</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			حذف مفتاح من التخبئة:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_63">
<span class="pln">cache</span><span class="pun">()-&gt;</span><span class="pln">forget</span><span class="pun">(</span><span class="str">'key'</span><span class="pun">);</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<p>
	نعيد كتابة الدالة <code>index</code> في المتحكم <code>PostsController</code> بالدالة المساعدة <code>cache</code> بدلا من الصنف <code>Cache</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3723_67">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    $posts </span><span class="pun">=</span><span class="pln"> cache</span><span class="pun">()-&gt;</span><span class="pln">remember</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</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">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</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"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$posts</span><span class="pun">);</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	يمكن ملاحظة أنك لا تحتاج لاستيرد صنف جديد؛ فالدالة المساعدة متوفرة في جميع المشروع.
</p>
]]></description><guid isPermaLink="false">389</guid><pubDate>Tue, 28 Feb 2017 06:00:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x62A;&#x62C;&#x646;&#x628; &#x645;&#x634;&#x643;&#x644; N+1 &#x641;&#x64A; Laravel &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x62A;&#x62D;&#x645;&#x64A;&#x644; &#x627;&#x644;&#x646;&#x651;&#x634;&#x637; Eager Loading</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%AA%D8%AC%D9%86%D8%A8-%D9%85%D8%B4%D9%83%D9%84-n1-%D9%81%D9%8A-laravel-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D9%86%D9%91%D8%B4%D8%B7-eager-loading-r433/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_04/laravel3.png.539753e973fb61a1426d40d00cb53b2b.png" /></p>

<h3>
	مقدمة
</h3>

<p>
	قبل أن ندخل في صلب الموضوع، دعني أطلعك على بعض مشاكل تصميم البرمجيات التي قد تواجهك. قبل بضعة أيام اشتكى أحد العملاء من بطء كبير جدًا في تحميل بعض صفحات موقعه. لذلك قرّرت أن أتفحّص تلك الصفحة وقد صدمني ما وجدته. فقد أظهر قسم الاستعلامات(query section) بأنّه تمّ تنفيذ أكثر من 16500 استعلام على تلك الصفحة لوحدها!<br>
	وجدت الشيفرة البرمجية المسبّبة لتلك المشكلة.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="22624" data-unique="alovfhhyx" src="https://academy.hsoub.com/uploads/monthly_2017_04/laravel3.png.9e0cb2e93c54133fc609fad9249a0d94.png" alt="laravel3.png"></p>

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

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs php"><span class="hljs-variable"><span class="pln">$main_object</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MainObject</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">foreach</span></span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$main_object</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">as</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$object</span></span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="hljs-keyword"><span class="pln">echo</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$object</span></span><span class="pun">-&gt;</span><span class="pln">some_property</span><span class="pun">;</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">foreach</span></span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$object</span></span><span class="pun">-&gt;</span><span class="pln">related_object </span><span class="hljs-keyword"><span class="kwd">as</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$related</span></span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="hljs-keyword"><span class="pln">echo</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$related</span></span><span class="pun">-&gt;</span><span class="pln">some_property</span><span class="pun">;</span><span class="pln">
        </span><span class="hljs-keyword"><span class="pln">echo</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$related</span></span><span class="pun">-&gt;</span><span class="pln">another_property</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">foreach</span></span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$object</span></span><span class="pun">-&gt;</span><span class="pln">another_related </span><span class="hljs-keyword"><span class="kwd">as</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$another</span></span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="hljs-keyword"><span class="pln">echo</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$another</span></span><span class="pun">-&gt;</span><span class="pln">some_property</span><span class="pun">;</span><span class="pln">
        </span><span class="hljs-keyword"><span class="pln">echo</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$another</span></span><span class="pun">-&gt;</span><span class="pln">another_property</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	إذا كانت $main_object = MainObject::all(); تقوم بإرجاع 5500 نتيجة، فإنّ أوّل حلقة foreach سوف تُنفَّذ 5500 مرة وكذلك الحال بالنّسبة للحلقتين الثانية والثالثة. عند استعمال ما يُسمى بمخطّط الكائن العلائقيّة ORM ، يقوم أغلب المطورين بكتابة استعلامات قواعد بيانات غير فعّالة، ويُصعّب استخدام الـORM مُهمّة اكتشاف هذه الأخطاء. تُسمّى هذه المشكلة بمشكلة N+1 وأعتقد بأنّ المُطوّر السّابق لم ينتبه لذلك. ولنتفادى هذه المشكلة سنقوم باستعمال التحميل النّشط(eager loading).
</p>

<h3>
	ما هو التحميل النّشط(eager loading)؟
</h3>

<p>
	يمكنك القول بأنّ التّحميل النّشط هو طريقة لفعل كلّ شيء عند الطّلب. وهو أيضًا عكس <a href="https://en.wikipedia.org/wiki/Lazy_loading" rel="external nofollow">التحميل الخامل(lazy loading)</a> بحيث يتمّ تنفيذ المهام عند الحاجة إليها. يساعد التحميل النّشط على تفادي الوقوع في مشاكل الأداء. حتى تتضح الصورة بشكل أفضل تخيّل معي الحالة التّالية:
</p>

<p style="text-align: center;">
	<img alt="Figure1_stores_model.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22143" data-unique="smgtnvo2c" src="https://academy.hsoub.com/uploads/monthly_2017_03/Figure1_stores_model.png.8ffab2383783de607a39c6545267415f.png"></p>

<p>
	يوجد لدينا نموذج علاقة كائنيّة مُعزّزة enhanced entity-relationship model يحتوي على ثلاث وحدات/كائنات مترابطة. يمكننا قراءة هذا النموذج كالتالي: كل عضو(member) يمكنه أن يملك أكثر من متجر(store) ولكن المتجر الواحد ينتمي إلى عضو واحد فقط. كل متجر يمكن أن يحتوي على أكثر من مُنتَج(product) ولكن المنتَج الواحد ينتمي إلى متجر واحد فقط.<br>
	الخطوة التّالية هي إنشاء نماذج eloquent لهذه الوحدات/الكائنات.<br>
	عضو(member):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs xml"><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">namespace</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Illuminate</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Database</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Eloquent</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Model</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Member</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Model</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">

    </span><span class="hljs-comment"><span class="com">/**
     * The attributes that are mass assignable.
     *
     *</span><span class="hljs-phpdoc"><span class="com"> @var</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$fillable</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'username'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'email'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'first_name'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'last_name'</span></span><span class="pun">];</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">stores</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">hasMany</span><span class="pun">(</span><span class="hljs-string"><span class="str">'App\\Store'</span></span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></span></code></pre>

<p>
	متجر(store):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs xml"><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">namespace</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Illuminate</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Database</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Eloquent</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Model</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Store</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Model</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">

    </span><span class="hljs-comment"><span class="com">/**
     * The attributes that are mass assignable.
     *
     *</span><span class="hljs-phpdoc"><span class="com"> @var</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$fillable</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'name'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'slug'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'site'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'member_id'</span></span><span class="pun">];</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln">  </span><span class="hljs-title"><span class="pln">member</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="hljs-string"><span class="str">'App\\Member'</span></span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">products</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">hasMany</span><span class="pun">(</span><span class="hljs-string"><span class="str">'App\\Product'</span></span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></span></code></pre>

<p>
	مُنتَج(product):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs xml"><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">namespace</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Illuminate</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Database</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Eloquent</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Model</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Product</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Model</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">

    </span><span class="hljs-comment"><span class="com">/**
     * The attributes that are mass assignable.
     *
     *</span><span class="hljs-phpdoc"><span class="com"> @var</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$fillable</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'name'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'short_desc'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'long_desc'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'price'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'store_id'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'member_id'</span></span><span class="pun">];</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln">  </span><span class="hljs-title"><span class="pln">store</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="hljs-string"><span class="str">'App\\Store'</span></span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></span></code></pre>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="22144" href="https://academy.hsoub.com/uploads/monthly_2017_03/Figure2_storelist_mockup.png.99b0ac9b9edfbe06afb9fc5c92aa54ae.png" rel=""><img alt="Figure2_storelist_mockup.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22144" data-unique="jbgkgupg0" src="https://academy.hsoub.com/uploads/monthly_2017_03/Figure2_storelist_mockup.thumb.png.2d1c4ccff4728a610aca7c29810da1a9.png"></a>
</p>

<p>
	قد ينتهي بك المطاف بشيء كهذا في المتحكم(controller) الخاص بك:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs xml"><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">namespace</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Http</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Controllers</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Repositories</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">StoreRepository</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">StoresController</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Controller</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">;</span><span class="pln">

    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">__construct</span></span><span class="hljs-params"><span class="pun">(</span><span class="typ">StoreRepository</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">stores </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">


    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">index</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">stores</span><span class="pun">-&gt;</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> \View</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-string"><span class="str">'stores.index'</span></span><span class="pun">)-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="hljs-string"><span class="str">'stores'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></span></code></pre>

<p>
	في الـView تريد أن تظهر تلك البيانات:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs handlebars"><span class="xml"><span class="lit">@foreach</span><span class="pun">(</span><span class="pln">$stores </span><span class="kwd">as</span><span class="pln"> $store</span><span class="pun">)</span><span class="pln">
    </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">h1</span></span><span class="str">&gt;</span></span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln"> $</span><span class="hljs-variable"><span class="pln">store</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pln"> </span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">h1</span></span><span class="pun">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span><span class="typ">Owner</span><span class="pun">:</span><span class="pln"> </span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln"> $</span><span class="hljs-variable"><span class="pln">store</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">member</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">first</span></span><span class="pln">_</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pun">.</span></span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="hljs-variable"><span class="pun">.</span></span><span class="pln"> $</span><span class="hljs-variable"><span class="pln">store</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">member</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">last</span></span><span class="pln">_</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pln"> </span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">span</span></span><span class="pun">&gt;</span></span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">&gt;</span></span><span class="pln">

    </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">h2</span></span><span class="str">&gt;</span></span><span class="typ">Products</span><span class="pun">:</span><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">h2</span></span><span class="pun">&gt;</span></span><span class="pln">
    </span><span class="lit">@foreach</span><span class="pun">(</span><span class="pln">$store</span><span class="pun">-&gt;</span><span class="pln">products </span><span class="kwd">as</span><span class="pln"> $product</span><span class="pun">)</span><span class="pln">
        </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">h3</span></span><span class="str">&gt;</span></span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln">$</span><span class="hljs-variable"><span class="pln">product</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">h3</span></span><span class="pun">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln">$</span><span class="hljs-variable"><span class="pln">product</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">short</span></span><span class="pln">_</span><span class="hljs-variable"><span class="pln">desc</span></span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;</span><span class="str">/</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">br</span></span><span class="str">/</span><span class="pun">&gt;</span></span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span><span class="typ">Price</span><span class="pun">:</span><span class="pln"> </span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln">$</span><span class="hljs-variable"><span class="pln">product</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">price</span></span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">span</span></span><span class="pun">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
        </span><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="typ">Debugbar</span><span class="pun">::</span><span class="pln">info</span><span class="pun">(</span><span class="hljs-string"><span class="str">'Product displayed'</span></span><span class="pun">);</span><span class="pln"> </span><span class="hljs-preprocessor"><span class="pun">?&gt;</span></span></span><span class="pln">
    </span><span class="lit">@endforeach</span><span class="pln">
    </span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
    </span><span class="pun">========================</span><span class="pln">
    </span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
</span><span class="lit">@endforeach</span></span></code></pre>

<p>
	وتكون النتيجة كالتالي:
</p>

<p style="text-align: center;">
	<img alt="Figure3_n_plus_one_problem.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22145" data-unique="r9h8uoxze" src="https://academy.hsoub.com/uploads/monthly_2017_03/Figure3_n_plus_one_problem.png.3899dc504af638143fa009a544c7ad8f.png"></p>

<p>
	في هذا المثال، قُمت بإعطاء قاعدة البيانات 5 أعضاء و3 متاجر و4 منتجات. الاستعلام الأول هو لجلب جميع المتاجر من قاعدة البيانات وهذا هو الجزء “+1” من <a href="https://secure.phabricator.com/book/phabcontrib/article/n_plus_one/" rel="external nofollow">المشكلة N+1</a>. وفي هذا المثال تحديدًا، فإنّ الحرف “N” يُمثّل عدد المتاجر التي سيقوم الاستعلام الأول بإرجاعها، وسيتم تنفيذ استعلام select *from بنفس العدد على جداول المنتجات والأعضاء. ولأنّ هناك 3 متاجر، فهذا يعني بأنّنا سنقوم بإجراء 3 استعلامات على جدول الأعضاء و3 استعلامات أخرى على جدول المنتجات، وبالتالي يصبح عدد الاستعلامات التي تمّ تنفيذها بالكامل هو 3+3+1.<br>
	تخيّل معي الآن ماذا كان سيحصل لو كان هناك 5 آلاف أو 10 آلاف متجر؟ سيكون هناك من 10 آلاف إلى 20 ألف استعلام في كلّ مرّة يزور أحدهم تلك الصفحة. وماذا لو كان هناك 10 آلاف أو 100 ألف زائر خلال 24 ساعة فقط؟ سيكون ذلك بمثابة كابوسٍ مرعبٍ بلا شك. يظهر الآن وبكلّ وضوح بأنّ هذه الطّريقة غير مجدية وقاتلة للأداء(performance killer). لن يهم أي قاعدة بيانات تستخدم أو قوّة الخادوم فستكون هناك دائمًا نقطة ما لن يستطيع العتاد القوي التعامل معها. يمكنك تحسين الأداء عن طريق التخزين المؤقت(caching) للاستعلامات؛ باستخدام Redis على سبيل المثال. سيعمل ذلك جيّدًا ولكن بشكل مؤقّت. ستقوم بتلك الطّريقة فقط بتأخير النّهاية الحتميّة التي ستكلّفك الكثير من المال والوقت وقد تخسر أيضًا الكثير من المستخدمين.<br>
	وهنا يأتي دور التّحميل النّشط. فاستعمال <a href="http://laravel.com/docs/4.2/eloquent#eager-loading" rel="external nofollow">التحميل النّشط</a> في Laravel يُعدّ أمرًا في غاية السهولة. فعن طريق استخدام تابع with تقوم بتحديد العلاقات التي تريد أن يتمّ تحميلها تحميلاً نشطًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs coffeescript"><span class="pln">$stores </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-attribute"><span class="typ">Store</span></span><span class="pun">::</span><span class="hljs-reserved"><span class="kwd">with</span></span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-string"><span class="str">'member'</span></span><span class="pun">,</span><span class="hljs-string"><span class="str">'products'</span></span><span class="pun">)</span></span><span class="pun">-&gt;</span></span><span class="kwd">get</span><span class="pun">();</span></code></pre>

<p>
	باستعمال التحميل النّشط، قمنا بتقليص عدد الاستعلامات من 7 إلى 3 فقط، كما توضح الصورة التالية:
</p>

<p style="text-align: center;">
	<img alt="Figure4_n_plus_one_problem_eager.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22146" data-unique="qwechme7n" src="https://academy.hsoub.com/uploads/monthly_2017_03/Figure4_n_plus_one_problem_eager.png.527a53bb10480b06074e8538da27239e.png"></p>

<p>
	وحتى لو كان هناك 10 آلاف مُدخل للمتجر، فإنّ عدد الاستعلامات لن يتغير وسيبقى 3 فقط. وكما ترى، فإنّ استخدام التّحميل النّشط بالشّكل المناسب قد يُحسّن من الأداء بصورة كبيرة. وحتى نرى تحسّنًا فعليًا، فإنّه يجب أيضًا أن يكون هناك مؤشّر/فهرس(index) على حقول المُعرّفات(id fields) في جداول الأعضاء والمنتجات. فمع وجود الكثير من السجلات(records) فإنّ تنفيذ in( ‘1’, ‘2’, … ) على حقول غير مفهرسة(non-indexed) قد يأخذ بعض الوقت.
</p>

<p>
	بعد هذه المقدمة السّريعة عن التحميل النّشط، لنرى كيف يمكننا استعمال العلاقات(relations) مع المستودعات(repositories).
</p>

<h3>
	تمديد فئة المستودع
</h3>

<p>
	سأريك الآن طريقة واحدة لكيفية استعمال العلاقات (relations) في فئات المستودع. هذا مثال لنتيجة نهائية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs lasso"><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="typ">StoreRepository</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">stores </span><span class="hljs-subst"><span class="pun">=</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">


</span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pun">=</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">stores</span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="hljs-keyword"><span class="kwd">with</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">'member'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'products'</span></span><span class="pun">)</span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="hljs-literal"><span class="pln">all</span></span><span class="pun">();</span><span class="pln">

    </span><span class="hljs-attribute"><span class="pun">...</span></span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	فكما ترى في الأعلى، هناك تابع with ليمكننا من سلسلة نموذج العلاقات. هذا التابع سيكون شبيها بالتّابع with الخاصة <a href="https://github.com/laravel/framework/blob/5.0/src/Illuminate/Database/Eloquent/Builder.php#L734" rel="external nofollow">بمُنشئ الاستعلامات في Laravel(Laravel’s Query Builder)</a>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs php"><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="kwd">with</span></span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$relations</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_string</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$relations</span></span><span class="pun">))</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$relations</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> func_get_args</span><span class="pun">();</span><span class="pln">

    </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$relations</span></span><span class="pun">;</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	نحتاج الآن لربط كل علاقة(relation) إلى النموذج:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs lasso"><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> eagerLoadRelations</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pun">(</span><span class="hljs-subst"><span class="pun">!</span></span><span class="pln">is_null</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="hljs-keyword"><span class="kwd">with</span></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="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="hljs-keyword"><span class="kwd">with</span></span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$relation</span></span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">model</span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="hljs-keyword"><span class="kwd">with</span></span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$relation</span></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="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	ما تبّقى علينا الآن هو تحديث تابع المستودع all() (وأي توابع أخرى تريدها) لتستخدم التحميل النّشط:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs lasso"><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="hljs-literal"><span class="pln">all</span></span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$columns</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pun">=</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">array</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">'*'</span></span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">applyCriteria</span><span class="pun">();</span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">newQuery</span><span class="pun">()</span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">eagerLoadRelations</span><span class="pun">();</span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">model</span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="kwd">get</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$columns</span></span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	وكما ذكرت مسبقًا، يمكنك إضافة علاقات متعدّدة داخل وسيلة with(). وهذا مثال على StoresController:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs xml"><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">namespace</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Http</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Controllers</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Repositories</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">StoreRepository</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">StoresController</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Controller</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">;</span><span class="pln">

    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">__construct</span></span><span class="hljs-params"><span class="pun">(</span><span class="typ">StoreRepository</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">stores </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">index</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">stores</span><span class="pun">-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="hljs-string"><span class="str">'member'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'products'</span></span><span class="pun">)-&gt;</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> \View</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-string"><span class="str">'stores.index'</span></span><span class="pun">)-&gt;</span><span class="kwd">with</span><span class="pun">(</span><span class="hljs-string"><span class="str">'stores'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$stores</span></span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></span></code></pre>

<p>
	يمكنك في الـView أن تعرض أيّ بيانات بالطريقة التي تريدها. لأغراض التّجريب سيكون التالي كافيًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6413_9">
<code class="hljs handlebars"><span class="xml"><span class="lit">@foreach</span><span class="pun">(</span><span class="pln">$stores </span><span class="kwd">as</span><span class="pln"> $store</span><span class="pun">)</span><span class="pln">
    </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">h1</span></span><span class="str">&gt;</span></span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln"> $</span><span class="hljs-variable"><span class="pln">store</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pln"> </span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">h1</span></span><span class="pun">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span><span class="typ">Owner</span><span class="pun">:</span><span class="pln"> </span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln"> $</span><span class="hljs-variable"><span class="pln">store</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">member</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">first</span></span><span class="pln">_</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pun">.</span></span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="hljs-variable"><span class="pun">.</span></span><span class="pln"> $</span><span class="hljs-variable"><span class="pln">store</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">member</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">last</span></span><span class="pln">_</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pln"> </span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">span</span></span><span class="pun">&gt;</span></span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">&gt;</span></span><span class="pln">

    </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">h2</span></span><span class="str">&gt;</span></span><span class="typ">Products</span><span class="pun">:</span><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">h2</span></span><span class="pun">&gt;</span></span><span class="pln">
    </span><span class="lit">@foreach</span><span class="pun">(</span><span class="pln">$store</span><span class="pun">-&gt;</span><span class="pln">products </span><span class="kwd">as</span><span class="pln"> $product</span><span class="pun">)</span><span class="pln">
        </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">h3</span></span><span class="str">&gt;</span></span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln">$</span><span class="hljs-variable"><span class="pln">product</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">name</span></span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">h3</span></span><span class="pun">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln">$</span><span class="hljs-variable"><span class="pln">product</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">short</span></span><span class="pln">_</span><span class="hljs-variable"><span class="pln">desc</span></span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;</span><span class="str">/</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">br</span></span><span class="str">/</span><span class="pun">&gt;</span></span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="str">&lt;</span><span class="hljs-title"><span class="str">span</span></span><span class="str">&gt;</span></span><span class="typ">Price</span><span class="pun">:</span><span class="pln"> </span></span><span class="hljs-expression"><span class="pun">{{</span><span class="pln">$</span><span class="hljs-variable"><span class="pln">product</span><span class="pun">-</span></span><span class="pun">&gt;</span><span class="hljs-variable"><span class="pln">price</span></span><span class="pun">}}</span></span><span class="xml"><span class="hljs-tag"><span class="pun">&lt;/</span><span class="hljs-title"><span class="pln">span</span></span><span class="pun">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
        </span><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="typ">Debugbar</span><span class="pun">::</span><span class="pln">info</span><span class="pun">(</span><span class="hljs-string"><span class="str">'Product displayed'</span></span><span class="pun">);</span><span class="pln"> </span><span class="hljs-preprocessor"><span class="pun">?&gt;</span></span></span><span class="pln">
    </span><span class="lit">@endforeach</span><span class="pln">
    </span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
    </span><span class="pun">========================</span><span class="pln">
    </span><span class="hljs-tag"><span class="pun">&lt;</span><span class="hljs-title"><span class="pln">br</span></span><span class="pun">/&gt;</span></span><span class="pln">
</span><span class="lit">@endforeach</span></span></code></pre>

<p>
	يوجد الآن 3 استعلامات فقط كما هو متوقع:
</p>

<p style="text-align: center;">
	<img alt="Figure5_eager_loading.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22147" data-unique="z7zhm7fvh" src="https://academy.hsoub.com/uploads/monthly_2017_03/Figure5_eager_loading.png.f5e88e3935fb849e89406b1778f66dda.png"></p>

<h3 id="خاتمة">
	خاتمة
</h3>

<p>
	كما رأيت، يمكنك باستعمال التحميل النّشط أن تُحسّن من أداء التطبيق الخاص بك. ولكن ضع في الحسبان بأنّه عندما يكبر تطبيقك، فإنّ التحميل النّشط لوحده لن يكون كافيًا للحصول على أفضل النتائج.
</p>

<p>
	ترجمة -وبتصرّف- للمقال<a href="https://bosnadev.com/2015/03/26/using-repository-pattern-in-laravel-5-eloquent-relations-and-eager-loading/" rel="external nofollow"> Using Repository Pattern In Laravel 5 – Eloquent Relations And Eager Loading</a> لصاحبه Mirza Pasic
</p>
]]></description><guid isPermaLink="false">433</guid><pubDate>Tue, 20 Dec 2016 21:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x62F;&#x64A;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x64A; &#x637;&#x631;&#x623;&#x62A; &#x639;&#x644;&#x649; &#x647;&#x64A;&#x643;&#x644;&#x629; &#x645;&#x634;&#x627;&#x631;&#x64A;&#x639; Laravel &#x628;&#x62F;&#x621;&#x627; &#x645;&#x646; &#x627;&#x644;&#x625;&#x635;&#x62F;&#x627;&#x631; 5.3</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D9%8A%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%8A-%D8%B7%D8%B1%D8%A3%D8%AA-%D8%B9%D9%84%D9%89-%D9%87%D9%8A%D9%83%D9%84%D8%A9-%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-laravel-%D8%A8%D8%AF%D8%A1%D8%A7-%D9%85%D9%86-%D8%A7%D9%84%D8%A5%D8%B5%D8%AF%D8%A7%D8%B1-53-r388/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/larave-53.png.1d3031e2509b24abea0f49669ec5d587.png" /></p>

<p>
	يتغيّر إطار العمل Laravel باستمرار بإدراج تحديثات جديدة على كلّ إصدار من أجل تحسين تجربة التطوير وإضافة ميزات جديدة تسهّل عمل المطوّر. سنتناول في هذا الدرس، الأول من سلسلة مكونة من ستة أجزاء، التغييرات الحاصلة في هيكلة مشاريع في الإصدار 5.3 من إطار العمل Laravel.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="21681" data-unique="7xuxk7p0f" src="https://academy.hsoub.com/uploads/monthly_2017_02/larave-53.png.025d0c773ae01ccedb97eea95f978c62.png" style="" alt="larave-53.png"></p>

<p>
	سنستخدم لأغراض الشرح مشروعي Laravel؛ الأول يعمل بالإصدار 5.2 والثاني بالإصدار 5.3 (الأخير أثناء كتابة هذا المقال). ننشئ المشروعين بمدير الاعتمادات <code>composer</code> على النحو التالي:
</p>

<ul>
<li>
		<p>
			بالنسبة للإصدار 5.2:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9979_7">
<span class="pln">composer create</span><span class="pun">-</span><span class="pln">project </span><span class="pun">--</span><span class="pln">prefer</span><span class="pun">-</span><span class="pln">dist laravel</span><span class="pun">/</span><span class="pln">laravel laravel52 </span><span class="str">"5.2.*"</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			بالنسبة للإصدار 5.3:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9979_9">
<span class="pln">composer create</span><span class="pun">-</span><span class="pln">project </span><span class="pun">--</span><span class="pln">prefer</span><span class="pun">-</span><span class="pln">dist laravel</span><span class="pun">/</span><span class="pln">laravel laravel53 </span><span class="str">"5.3.*"</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<p>
	يظهر الإصدار المستهدَف في كل من الأمرين أعلاه (5.2 و5.3 على التوالي).
</p>

<h2 id="ملف-المسارات-routes">
	ملف المسارات Routes
</h2>

<p>
	تعدّ <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-laravel-5-r216/#%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%8A%D9%87-%D9%81%D9%8A-laravel" rel="">المسارات</a> الخطوة الأولى في معالجة الطلبات التي يتلقاها التطبيق. في الإصدارات السابقة من Laravel (قبل 5.3) كانت المسارات تُضبَط في الملف <code>app/Http/routes.php</code> بغضّ النظر عن طبيعة الطلبات التي تتعامل معها. إن بحثت عن هذا الملف في الإصدار الجديد فلن تجده؛ إذ أنه اختفى مع إنشاء مجلّد جديد باسم <code>routes</code> يوجد في جذر المشروع ويحوي ملفّين:
</p>

<ul>
<li>
		ملف <code>web.php</code>: يحوي هذا الملف المسارات الخاصّة بواجهة الوِب. تعتمد المسارات الموجودة في هذا الملفّ على وسيط برمجي Middleware يحمل نفس الاسم <code>(web</code>) ويوفّر خاصيّات مثل حالة الجلسة Session state (الاحتفاظ ببيانات العميل لاستخدامها في الطلبات الواردة منه أثناء صلاحية الجلسة) والحماية من هجمات تزوير الطلب عبر الموقع Cross-site request forgery, CSRF.
	</li>
	<li>
		ملف <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code>: يتوجّه هذا الملف للتطبيقات التي توفّر واجهة تطبيقات برمجية Application programming interface. تعتمد المسارات الموجودة في الملف <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code> على وسيط برمجي أخف من السابق (يُسمّى هذا الوسيط <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code>)؛ إذ لا يحتوي على الخاصيّات الموجودة في الوسيط <code>web</code> والتي لا تحتاجها واجهات التطبيقات البرمجية.
	</li>
</ul>
<p>
	يمكن القول إن الملف <code>web.php</code> معدّ للتعامل مع الطلبات ذات الحالة Stateful، بينما الملف <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code> معدّ للطلبات عديمة الحالة Stateless.
</p>

<p>
	من الجيد الانتباه إلى أن جميع المسارات المذكورة في الملف <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code> تُطبَّق عليها لاحقة <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code>. لو نظرنا إلى الملف <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code> المبدئي فسنجد أن محتواه على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6084_11">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">


</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/user'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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"> $request</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">();</span><span class="pln">
</span><span class="pun">})-&gt;</span><span class="pln">middleware</span><span class="pun">(</span><span class="str">'auth:<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>'</span><span class="pun">);</span></pre>

<p>
	وبالنسبة للملف <code>web.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6084_13">
<span class="pun">&lt;?</span><span class="pln">php


</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'welcome'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إن نفذنا أمر سرد مسارات المشروع فستكون على النحو التالي:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19671" href="https://academy.hsoub.com/uploads/monthly_2016_11/01_route_list.png.d01991c85bcea8a6a1898b4f13a9ae46.png" rel=""><img alt="01_route_list.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19671" data-unique="75mbp5qih" src="https://academy.hsoub.com/uploads/monthly_2016_11/01_route_list.thumb.png.af792a849e14f1c50cf3467fb356721a.png"></a>
</p>

<p>
	لاحظ كيف أن Laravel أضاف تلقائيا اللاحقة <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code> إلى المسار <code>user/</code> مع تحديد الوسيط البرمجي المستخدم بـ <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>, auth:<abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code>.
</p>

<p>
	فلنضف مسارا باسم <code>user/</code> إلى الملف <code>web.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6084_15">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/user'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"1,2,3,4"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ثم نسرُد المسارات المتوفرة:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19672" href="https://academy.hsoub.com/uploads/monthly_2016_11/02_route_list.png.7687cd504d322d16707c47efc054b276.png" rel=""><img alt="02_route_list.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19672" data-unique="g91vqn0to" src="https://academy.hsoub.com/uploads/monthly_2016_11/02_route_list.thumb.png.80aba1771e1170accc9a350012c7ce33.png"></a>
</p>

<p>
	يظهر المسار الجديد في القائمة، ولكن بدون اللاحقة <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code>، ومع تحديد الوسيط بـ<code>web</code>.
</p>

<h2 id="تغيير-الهيكلة-المبدئية-للمجلدات">
	تغيير الهيكلة المبدئية للمجلدات
</h2>

<p>
	تخَلّص الإصدار 5.3 من Laravel من مجلدات كانت تأتي مبدئيا مع إطار العمل. يمكن ملاحظة هذا الأمرحيث تظهر، في الصورة أدناه، المجلدات الفرعية من المجلد <code>app</code> لكل من الإصدارين 5.2 (في اليسار) و5.3 (في اليمين).
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19673" href="https://academy.hsoub.com/uploads/monthly_2016_11/03_folders_structure.png.661bff50aded181c6d0bc2c9b98fc18e.png" rel=""><img alt="03_folders_structure.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19673" data-unique="qxf5buyta" src="https://academy.hsoub.com/uploads/monthly_2016_11/03_folders_structure.thumb.png.c264664429b9a12766701f7574294781.png"></a>
</p>

<p>
	نلاحظ إخفاء المجلدات <code>Listeners</code>، <code>Jobs</code>، <code>Events</code> و <code>Policies</code>. لا يعني الإخفاء المبدئي لهذه الملفات أن الوظائف المرتبطة بها لم تعد موجودة؛ بل يتعلّق الأمر بالتخفيف من المجلدات الموجودة مبدئيا وإنشائها فقط عند الحاجة لذلك. مثلا؛ إن أردنا إنشاء <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%A3%D8%AD%D8%AF%D8%A7%D8%AB-events-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87%D8%A7-%D9%81%D9%8A-laravel-r305/" rel="">حدث Event</a> باسم <code>ContactHandlerAction</code> فسنفّذ الأمر التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6084_17">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="kwd">event</span><span class="pln"> </span><span class="typ">ContactHandlerAction</span></pre>

<p>
	إن نفذت الأمر أعلاه فستجد أن Laravel أنشأ مجلدا فرعيا في <code>app</code> باسم <code>Events</code> وأنشأ داخله الملف <code>ContactHandlerAction.php</code>.
</p>

<p>
	<img alt="04_events_folder.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19674" data-unique="wj4c53ppe" src="https://academy.hsoub.com/uploads/monthly_2016_11/04_events_folder.png.7ece0bebd6c41a6af25e935e101e5472.png"></p>

<p>
	نفس الشيء بالنسبة للمستمعات Listeners:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6084_19">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">listener </span><span class="typ">EmailContactListener</span><span class="pln"> </span><span class="pun">--</span><span class="kwd">event</span><span class="pun">=</span><span class="str">"ContactHandlerAction"</span></pre>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19675" href="https://academy.hsoub.com/uploads/monthly_2016_11/05_listeners_folder.png.786e91b84b044d4b63af5081a443144d.png" rel=""><img alt="05_listeners_folder.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19675" data-unique="74abu00xj" src="https://academy.hsoub.com/uploads/monthly_2016_11/05_listeners_folder.thumb.png.3ae740cab6720adb261751e2cfbb4572.png"></a>
</p>

<p>
	يظهر جليا أن Laravel 5.3 تخفّف من مجلداتٍ مبدئيا؛ إلا أنه ينشئها إن احتاج إليها.
</p>
]]></description><guid isPermaLink="false">388</guid><pubDate>Tue, 22 Nov 2016 11:11:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x633;&#x62A;&#x631;&#x62C;&#x639;&#x627;&#x62A; Accessors &#x648;&#x627;&#x644;&#x645;&#x639;&#x62F;&#x644;&#x627;&#x62A; Mutators &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%B1%D8%AC%D8%B9%D8%A7%D8%AA-accessors-%D9%88%D8%A7%D9%84%D9%85%D8%B9%D8%AF%D9%84%D8%A7%D8%AA-mutators-%D9%81%D9%8A-laravel-r365/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_11/laravel-accessors-Mutators.png.66fe39344430314c58403485c88f06cb.png" /></p>

<p>
	المسترجِعات Accessors والمعدِّلات Mutators في Laravel هي مجموعة دوالّ مخصّصة يعرّفها المستخدم لتهيئة خواص النماذج Models. تُستخدم المسترجعات لتهيئة خواصّ النموذج عند طلب الحصول عليها من قاعدة البيانات، بينما تُستخدَم المعدّلات لتهيئة الخواصّ قبل حفظ النموذج في القاعدة.
</p>

<h2 id="تعريف-مسترجع">
	تعريف مسترجع
</h2>

<p>
	تُسمى الدوال المسترجعة بالصيغة <code>()getFooAttribute</code> حيث <code>Foo</code> هو اسم الخاصيّة التي نريد تهيئتها في الدالة، مع الانتباه إلى حالة الحرف الأول من الخاصية (حرف كبير Uppercase). سيستدعي Laravel تلقائيا هذه الدالة في كلّ مرة تبحث فيها عن قيمة الخاصيّة <code>foo</code>. لا يقتصر استخدام المسترجعات على سلاسل المحارف، بل يمكنك استخدامها لتهيئة أي نوع من البيانات تواريخ، أثمان، …إلخ.
</p>

<p>
	سنفترض أن لدينا نموذجا باسم <code>Member</code> (عضو) يحوي الخاصيّات التاليّة:
</p>

<pre class="ipsCode" id="ips_uid_7986_7">
first_name
last_name
email
password
last_visit
settings
created_at
updated_at</pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_9">
<span class="pln">$user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Member</span><span class="pun">::</span><span class="pln">create</span><span class="pun">([</span><span class="pln">
    </span><span class="str">'first_name'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'mirza'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'last_name'</span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'pasic'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'email'</span><span class="pln">       </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'mirza.pasic@bosnadev.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'password'</span><span class="pln">    </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'!supersecretpassword!'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'last_login'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Carbon</span><span class="pln">\Carbon</span><span class="pun">::</span><span class="pln">now</span><span class="pun">(),</span><span class="pln">
    </span><span class="str">'settings'</span><span class="pln">    </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'two_factor_aut'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="str">'session_time'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1200</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"> </span><span class="typ">Carbon</span><span class="pln">\Carbon</span><span class="pun">::</span><span class="pln">now</span><span class="pun">(),</span><span class="pln">
    </span><span class="str">'updated_at'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Carbon</span><span class="pln">\Carbon</span><span class="pun">::</span><span class="pln">now</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_7986_11">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="com">/**
* Class Member
* @package App
*/</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Member</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * التأكد من تهيئة الاسم الشخصي بعد الحصول على النموذج من قاعدة البيانات
    * 
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getFirstNameAttribute</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">return</span><span class="pln"> ucfirst</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="com">/**
    * التأكد من تهيئة الاسم العائلي بعد الحصول على النموذج من قاعدة البيانات
    * 
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getLastNameAttribute</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">return</span><span class="pln"> ucfirst</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="pun">}</span></pre>

<p>
	سيعمل المسترجعان <code>getFirstNameAttribute</code> و <code>getLastNameAttribute</code> على تهيئة الحقلين <code>first_name</code> (الاسم الشخصي) و<code>last_name</code> (الاسم العائلي) على التوالي لجعل الحرف الأول في كلّ واحد منهما يُكتب كبيرا (Uppercase)، بغضّ النظر عن الطريقة التي أدخلهما بها المستخدم.
</p>

<p>
	يمكن أيضا استخدام المسترجعات لدمج خاصيّتين في النموذج لتكوّنا واحدة جديدة. يمكن مثلا تعريف الاسم الكامل <code>full_name</code> بناء على الاسم الشخصي والاسم العائلي:<code> </code>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_14">
<span class="com">/**
* Get members full name
* 
* @return string
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getFullNameAttribute</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"> ucfirst</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">first_name</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"> ucfirst</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">last_name</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم يمكننا استخدامه كما لو كان فعلا يوجد حقل باسم <code>full_name</code> في النموذج:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_16">
<span class="pln">$member </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Member</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">

echo $member</span><span class="pun">-&gt;</span><span class="pln">full_name</span><span class="pun">;</span></pre>

<p>
	يمكنك إن أردت استخدام المسترجعات على أنواع بيانات أخرى. مثلا، لتهيئة التاريخ. نستخدم في المثال التالي الدالة <code>getLastLoginAttribute</code> لتهيئة تاريخ آخر دخول (الحقل <code>last_login</code>) بحيث يظهر بالصيغة <code>d.m.Y</code> (يمثّل الحرف <code>d</code> اليوم، الحرف<code>m</code> الشهر و<code>Y</code> السنة مكتوبة بأربعة أرقام):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_22">
<span class="com">/**
 * Custom format for the last login date
 * 
 * @param $value
 * @return string
 */</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getLastLoginAttribute</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">return</span><span class="pln"> \Carbon\Carbon</span><span class="pun">::</span><span class="pln">parse</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">)-&gt;</span><span class="pln">format</span><span class="pun">(</span><span class="str">'d.m.Y.'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم نستخدم الحقل <code>last_login</code> كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_24">
<span class="pln">$member </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Member</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
echo $member</span><span class="pun">-&gt;</span><span class="pln">last_login</span><span class="pun">;</span></pre>

<p>
	يظهر الحقل كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_26">
<span class="lit">11.07</span><span class="pun">.</span><span class="lit">2016.</span></pre>

<h2 id="تعريف-معدل">
	تعريف معدل
</h2>

<p>
	تشبه آلية تسميّة المعدِّل تعريفَ المسترجع، مع فرق إحلال <code>set</code> مكان <code>get</code>. إذا أردنا تعريف معدِّل للخاصيّة <code>foo</code> فسيكون اسمُه <code>setFooAttribute</code>. نعود لمثال النموذج <code>Member</code> السابق. نريد الآن أن نتأكد من تهيئة اسم العضو <strong>قبل</strong> حفظ النموذج في قاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_28">
<span class="com">/**
* التأكد من تهيئة الاسم الشخصي **قبل** حفظ النموذج
* 
* @param $value
* @return string
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setFirstNameAttribute</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">attributes</span><span class="pun">[</span><span class="str">'first_name'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> ucfirst</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="com">/**
* التأكد من تهيئة الاسم العائلي **قبل** حفظ النموذج
* 
* @param $value
* @return string
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setLastNameAttribute</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">attributes</span><span class="pun">[</span><span class="str">'last_name'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> ucfirst</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ربما لاحظت أن الدالة لا ترجِع أية قيمة. ما يحدُث هو أننا نضبُط الخاصيّة بالقيمة التي نريد مباشرة. نتأكد بهذه الطريقة أن الاسمين الشّخصي والعائلي سيكونان مهيأيْن دائما بالصيغة التي نريد.
</p>

<h2 id="أمثلة-على-المسترجعات-والمعدلات">
	أمثلة على المسترجعات والمعدلات
</h2>

<p>
	رأينا في الفقرات السابقة أمثلة لاستخدامات سهلة للمسترجعات والمعدّلات؛ إلا أن هذه الدوال يمكن أن تُستخدَم لأمور أكثر تخصيصا كما سنرى في الأمثلة التالية.
</p>

<h3 id="حماية-كلمات-السر">
	حماية كلمات السّر
</h3>

<p>
	يمكن استخدام المعدِّلات ل<a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-encoding%D8%8C-%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9-encryption%D8%8C-%D8%A7%D9%84%D8%AA%D8%AC%D8%B2%D8%A6%D8%A9-hashing-%D9%88%D8%A7%D9%84%D8%AA%D8%B4%D9%88%D9%8A%D8%B4-obfuscation%D8%9F-r308/" rel="">تجزئة</a> كلمة السّر Password hashing قبل حفظها في قاعدة البيانات؛ مثلا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_34">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setPasswordAttribute</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">attributes</span><span class="pun">[</span><span class="str">'password'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تتأكد بهذه الطريقة أن كلمة السّر لن تُحفَظ أبدا بصيغتها المقروءة في قاعدة البيانات، وهو ما يعدّ إجراء أمنيًّا أساسيا. استخدمنا في المثال السابق صنف <code>Hash</code> الذي يوفّره Laravel مبدئيا، ولكن يمكنك استخدام دوال تعميّة إن أردت، مثل <code>()bcrypt</code>.
</p>

<h3 id="الترميز-بصيغة-json">
	الترميز بصيغة Json
</h3>

<p>
	إن نظرت إلى نموذج <code>Member</code> السابق فستجد أنه يحوي خاصيّة باسم <code>settings</code> تُستخدَم لحفظ تفضيلات العضو الشخصيّة وخيارات أخرى يتيحها التطبيق. يمكن استخدام مصفوفة لإدارة هذه الخيارات وحفظها في قاعدة البيانات بصيغة Json. تتيح قواعد بيانات مثل <a href="https://academy.hsoub.com/tags/PostgreSQL/" rel="">PostgreSQL</a> نوع البيانات Json في حقول الجدول منذ زمن، كما أن <a href="https://academy.hsoub.com/tags/MySQL/" rel="">MySQL</a> أتاحت نوع البيانات هذا في الإصدار 5.7.8.
</p>

<p>
	<strong>ملحوظة:</strong> دعم نوع البيانات Json في MySQL لا زال في بداياته، وقد تواجه مشاكل عند استخدامه.
</p>

<p>
	بالنسبة لخاصيّة <code>settings</code> فسنحتاج لمعدِّل يخزّن البيانات بصيغة Json في القاعدة ومسترجِع لتحويل Json إلى مصفوفة من سلسلة محارف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_36">
<span class="com">/**
* Make sure that we get an array from JSON string 
*
* @param $value
* @return array
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getSettingsAttribute</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">return</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">$value</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">/**
* Encode an array to a JSON string
* 
* @param $value
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setSettingsAttribute</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">attributes</span><span class="pun">[</span><span class="str">'settings'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> json_encode</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3 id="المثال-كاملا">
	المثال كاملا
</h3>

<p>
	في ما يلي الخطوات اللازمة لإنشاء مثال عملي يعتمد على النموذج المقدّم في هذا الدرس. نفترض وجود Laravel مثبّت بقاعدة بيانات <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%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-%D9%81%D9%8A-laravel-5-r224/#%D9%85%D8%AA%D8%B7%D9%84%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1" rel="">مضبوطة</a>.
</p>

<h4 id="إنشاء-التهجير-والنموذج">
	إنشاء التهجير والنموذج
</h4>

<pre class="ipsCode" id="ips_uid_7986_38">
php artisan make:model Member -m
Model created successfully.
Created Migration: 2016_07_04_020531_create_members_table</pre>

<h4 id="التعديل-على-التهجير">
	التعديل على التهجير
</h4>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_40">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'members'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'first_name'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'last_name'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'email'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'password'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">date</span><span class="pun">(</span><span class="str">'last_login'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'settings'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h4 id="التعديل-على-النموذج">
	التعديل على النموذج
</h4>

<p>
	في ما يلي الشفرة الكاملة للنموذج <code>Member</code> مع المسترجعات والمعدِّلات.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7986_42">
<span class="pun">&lt;?</span><span class="pln">php  </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Hash</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="com">/**
* Class Member
* @package App
*/</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Member</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * @var array
    */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'first_name'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'last_name'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'email'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'last_login'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'settings'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'created_at'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'updated_at'</span><span class="pun">];</span><span class="pln">

    </span><span class="com">/**
    * التأكد من تهيئة الاسم الشخصي بعد الحصول على النموذج من قاعدة البيانات
    *
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getFirstNameAttribute</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">return</span><span class="pln"> ucfirst</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="com">/**
    * التأكد من تهيئة الاسم العائلي بعد الحصول على النموذج من قاعدة البيانات
    *
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getLastNameAttribute</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">return</span><span class="pln"> ucfirst</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="com">/**
    * الاسم الكامل للعضو
    *
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getFullNameAttribute</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"> ucfirst</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">first_name</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"> ucfirst</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">last_name</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
    * تهيئة تاريخ آخر زيارة
    *
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getLastLoginAttribute</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">return</span><span class="pln"> \Carbon\Carbon</span><span class="pun">::</span><span class="pln">parse</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">)-&gt;</span><span class="pln">format</span><span class="pun">(</span><span class="str">'d.m.Y.'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
    *  التأكد من تهيئة الاسم الشخصي **قبل** حفظ النموذج
    *
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setFirstNameAttribute</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">attributes</span><span class="pun">[</span><span class="str">'first_name'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> ucfirst</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="com">/**
    * التأكد من تهيئة الاسم العائلي **قبل** حفظ النموذج
    *
    * @param $value
    * @return string
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setLastNameAttribute</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">attributes</span><span class="pun">[</span><span class="str">'last_name'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> ucfirst</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="com">/**
    * تهيئة كلمة السّر **قبل** حفظها
    *
    * @param $value
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setPasswordAttribute</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">attributes</span><span class="pun">[</span><span class="str">'password'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</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="com">/**
    * الحصول على مصفوفة من حقل بصيغة 
    * Json
	*
    * @param $value
    * @return array
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getSettingsAttribute</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">return</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">$value</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">/**
    * الترميز بصيغة 
    * Json
	* قبل حفظ الحقل
    * @param $value
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> setSettingsAttribute</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">attributes</span><span class="pun">[</span><span class="str">'settings'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> json_encode</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="pun">}</span></pre>

<h4 id="استخدام-النموذج">
	استخدام النموذج
</h4>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7986_46">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'members'</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">
    $user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Member</span><span class="pun">::</span><span class="pln">create</span><span class="pun">([</span><span class="pln">
        </span><span class="str">'first_name'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'mirza'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'last_name'</span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'pasic'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'email'</span><span class="pln">       </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'mirza.pasic@bosnadev.com'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'password'</span><span class="pln">    </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'!supersecretpassword!'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'last_login'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Carbon</span><span class="pln">\Carbon</span><span class="pun">::</span><span class="pln">now</span><span class="pun">(),</span><span class="pln">
        </span><span class="str">'settings'</span><span class="pln">    </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'two_factor_aut'</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">'session_time'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1200</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"> </span><span class="typ">Carbon</span><span class="pln">\Carbon</span><span class="pun">::</span><span class="pln">now</span><span class="pun">(),</span><span class="pln">
        </span><span class="str">'updated_at'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Carbon</span><span class="pln">\Carbon</span><span class="pun">::</span><span class="pln">now</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">]);</span><span class="pln">

    $member </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Member</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    echo $member</span><span class="pun">-&gt;</span><span class="pln">last_login </span><span class="pun">.</span><span class="pln"> </span><span class="str">'&lt;br&gt;'</span><span class="pun">;</span><span class="pln">
    echo $member</span><span class="pun">-&gt;</span><span class="pln">full_name </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>
	ترجمة -وبتصرّف- للمقال <a href="https://bosnadev.com/2015/12/17/laravel-accessors-mutators/" rel="external nofollow"> Laravel Accessors and Mutators</a> لصاحبه Mirza Pasic.
</p>
]]></description><guid isPermaLink="false">365</guid><pubDate>Mon, 24 Oct 2016 03:04:00 +0000</pubDate></item><item><title>&#x646;&#x634;&#x631; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; Laravel &#x639;&#x644;&#x649; &#x645;&#x646;&#x635;&#x629; Heroku</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%86%D8%B4%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-%D8%B9%D9%84%D9%89-%D9%85%D9%86%D8%B5%D8%A9-heroku-r357/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_10/deploy-laravel-to-heroku.png.76221125ff38466a6abb6ea54cf4f555.png" /></p>

<p>
	اشتهر استخدام منصة Heroku السحابية ضمن مجتمع مطوري Ruby on Rails ونالت فيه شعبية واسعة؛ إلا أن الخدمة لم تقتصر على مطوري Ruby وما يدور حولها بل تجاوزتهم إلى تقديم الدعم للغات برمجة مثل Node.js ،Java و PHP؛ من بين أخرى.
</p>

<p>
	توفّر Heroku خطّة اشتراك مجانية يمكن استخدامها لإدارة مشاريع صغيرة جدا أو لأغراض الاختبار. سنشرح في هذا الدرس كيفية الاستفادة من Heroku عبر هذه الخطة لنشر Deploying تطبيقات Laravel.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="19256" data-unique="a1q0sg74i" src="https://academy.hsoub.com/uploads/monthly_2016_10/deploy-laravel-to-heroku.png.42429f232d4845f66742ff625986e369.png" alt="deploy-laravel-to-heroku.png"></p>

<h2 id="إنشاء-حساب-على-heroku">
	إنشاء حساب على Heroku
</h2>

<p>
	يجب أولا أن ننشئ حسابا على <a href="https://signup.heroku.com" rel="external nofollow">موقع الخدمة</a> حتى يمكننا الاستفادة منها. التسجيل مجاني ولا يستغرق سوى دقائق. ستُعرَض عليك خلال عملية التسجيل خيارات للغة البرمجة التي تريد استخدامها، اختر PHP؛ مع العلم أن هذا الخيار لا يؤثّر على إمكانية استعمالك للغات برمجة أخرى مستقبلا.
</p>

<h2 id="تثبيت-heroku-toolbelt">
	تثبيت Heroku Toolbelt
</h2>

<p>
	الخطوة الثانية بعد إنشاء الحساب هي تثبيت أداة <a href="https://toolbelt.heroku.com" rel="external nofollow">Heroku Toolbelt</a>. تُستخدَم هذه الأداة، التي تعمل عبر سطر الأوامر، لإدارة جوانب عدّة من المشاريع المضافة إلى Heroku؛ ومن ضمنها إدارة عمليّة النشر، <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%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-%D9%81%D9%8A-laravel-5-r224/" rel="">تهجير Migrating قاعدة البيانات</a> والتخاطب مع خادوم Heroku. تتوفّر الأداة على وندوز، ماك وتوزيعة أوبونتو لينكس.
</p>

<p>
	نفّذ بعد تثبيت الأداة الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_11">
$ heroku login
heroku-cli: Installing CLI... 21.83MB/21.83MB
Enter your Heroku credentials.
Email: mail@example.com
Password (typing will be hidden): 
Logged in as mail@example.com</pre>

<p>
	انتظر قليلا حتى يكتمل تنزيل عميل Heroku ثمّ أدخل معلومات الاستيثاق الخاصّة بك (عنوان البريد وكلمة السر).
</p>

<h2 id="نشر-تطبيق-laravel-على-heroku">
	نشر تطبيق Laravel على Heroku
</h2>

<p>
	يمكننا الآن بعد التسجيل في Heroku وتثبيت الأداة Heroku Toolbelt نشرُ مشروع Laravel. نبدأ بإنشاء مشروع Laravel جديد (على الحاسوب الشخصي):
</p>

<pre class="ipsCode" id="ips_uid_4211_16">
$ composer create-project laravel/laravel dev.herokutest.com dev-develop
Installing laravel/laravel (dev-develop 083db95...dac46617)
- Installing laravel/laravel (dev-develop develop)
Cloning develop
...
Compiling views
Do you want to remove the existing <abbr title="Version Control Systems | أنظمة التحكم بالنُّسخ"><abbr title="Version Control Systems | أنظمة التحكم بالنُّسخ"><abbr title="Version Control Systems | أنظمة التحكم بالنُّسخ"><abbr title="Version Control Systems | أنظمة التحكم بالنُّسخ">VCS</abbr></abbr></abbr></abbr> (.git, .svn..) history? [Y,n]? Y
Application key [9UCBk7IDjvAGrkLOUBXw43yYKlymlqE3Y] set successfully.</pre>

<p>
	ثم ننشئ ملفا باسم <code>Procfile</code> ونضعه في المجلد الجذر لمشروع Laravel. طريقة كتابة اسم الملفّ مهمة جدا (الحرف الأول كبير، ولا وجود لامتداد للملف). يقرأ Heroku هذا الملفّ لتحديد نوع العمليات التي سيجريها بعد نشر التطبيق. في حالة تطبيق Laravel فإن نوع العمليات المطلوب هو وِب <code>web</code>. نحدّد نوع خادوم الوِب المستخدم لتقديم التطبيق (Apache) والمجلّد الذي توجد به ملفات التطبيق المخصّصة للعرض، وهو في حالة Laravel المجلد <code>public</code>. يصبح ملفّ <code>Procfile</code> على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_18">
web: vendor/bin/heroku-php-apache2 public
</pre>

<p>
	هذا فقط مثال على الخيارات المتاحة، يمكنك تغيير هذه الخيارات (خادوم الوِب مثلا) إن أردت ذلك.
</p>

<p>
	الخطوة الموالية لإنشاء ملفّ <code>Procfile</code> هي وضع المشروع تحت تصرّف نظام إدارة الإصدارات Git بإنشاء مستودع للمشروع:
</p>

<pre class="ipsCode" id="ips_uid_4211_20">
$ git init
Initialized empty Git repository in /home/zeine77/dev.herokutest.com/.git/
$ git add .
$ git commit -m "First commit"</pre>

<p>
	يسهّل استخدامُ Git كثيرا عمليةَ النشر، فإطار العمل Laravel يأتي مبدئيا بميزات خاصّة بنظام إدارة الإصدارات Git (مثل ملفات <code>gitignore.</code>)؛ كما أن Heroku أيضا يتفاعل مع مستودع Git المحلي لتسهيل النشر. راجع <a href="http://academy.hsoub.com/programming/workflow/git/" rel="">هذه المقالات</a> لمعرفة المزيد عن Git.
</p>

<p>
	نحن الآن جاهزون لنشر التطبيق على Heroku. نستخدم Heroku Toolbelt لهذه المهمة: 
</p>

<pre class="ipsCode" id="ips_uid_4211_22">
$ heroku create
Heroku CLI submits usage information back to Heroku. If you would like to disable this, set `skip_analytics: true` in /home/zeine77/.heroku/config.json
Creating app... done, ⬢ nameless-chamber-90421
https://nameless-chamber-90421.herokuapp.com/ | https://git.heroku.com/nameless-chamber-90421.git
</pre>

<p>
	ينشئ الأمر <code>heroku create</code> اسما جديدا لمشروعك (أعطاني الاسم <code>nameless-chamber-90421</code>) ويعرّف رابطا يمكن عبره الوصول إلى التطبيق. لا يوجد على الرابط - لحد السّاعة - سوى صفحة مبدئية من Heroku. زيادة على الرابط والاسم، أنشأ الأمر السابق <a href="https://academy.hsoub.com/programming/workflow/git/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%AA%D9%81%D8%B1%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B9%D9%8A%D8%AF%D8%A9-remote-branches-%D9%81%D9%8A-git-r288/" rel="">مستودع Git بعيدا</a>. مستودع Git بعيد هو مستودع يضم ملفات مشروعك ولكنه يوجد في مكان آخر غير جهازك؛ يمكن دفع التغييرات إلى المشروع البعيد أو جلبها منه. سنكتفي في حالة Heroku بدفع التعديلات إلى المستودع البعيد، كما سنرى بعد قليل.
</p>

<p>
	يستخدم Heroku ملفات تسمى <code>buildpacks</code> (حزم بناء) لمعرفة البرامج التي يجب عليه إعدادها على الخادوم بعد تثبيت التطبيق؛ لذا يجب أن نحدّد واحدا. اخترنا ملفّ <code>buildpack</code> الرسمي من Heroku الخاص بتطبيقات PHP؛ نستخدم الأمر <code>config:add</code> في Heroku Toolbelt لتحديد هذا الملف:
</p>

<pre class="ipsCode" id="ips_uid_4211_24">
$ heroku config:add BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-php
Setting BUILDPACK_URL and restarting ⬢ nameless-chamber-90421... done, v3
BUILDPACK_URL: https://github.com/heroku/heroku-buildpack-php</pre>

<p>
	تستخدم تطبيقات Laravel مفتاح تعميّة Encryption key لتعمية معلومات جلسة المستخدم ومعلومات أخرى؛ توجد قيمة هذا المفتاح في <a href="https://academy.hsoub.com/questions/123-%D9%85%D8%A7%D8%B0%D8%A7-%D9%8A%D8%B9%D9%86%D9%8A-%D9%85%D8%AA%D8%BA%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D8%B8%D8%A7%D9%85-path%D8%9F/" rel="">متغيّر البيئة</a> <code>APP_KEY</code>. يوجد المتغيّر <code>APP_KEY</code> في الملفّ <code>env.</code>، إلا أن الملف <code>env.</code> لا يدخل في إطار الملفات التي يتعامل معها Git، نظرا لوجوده في الملفات المحدّدة في <code>gitignore.</code>. سنحتاج إذن لتوليد مفتاح تعميّة لاستخدامه على خادوم Heroku.
</p>

<p>
	تُستخدم أداة <code>artisan</code> لتوليد مفتاح تعمية على النحو التالي: 
</p>

<pre class="ipsCode" id="ips_uid_4211_26">
php artisan key:generate --show
</pre>

<p>
	يولّد الأمر أعلاه مفتاح تعميّة ويعرضه على سطر الأوامر؛ إلا أننا نريد أن نخزّن المفتاح على الخادوم؛ نستخدم Toolbelt لهذا الغرض على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_28">
heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)
Setting APP_KEY and restarting ⬢ nameless-chamber-90421... done, v7
APP_KEY: base64:jp40IC7SV5eJ5IhjQYwqk/KXJG0uS+ZhCqSGwkwgELs=</pre>

<p>
	يضبط الأمر السابق قيمة المتغيّر <code>APP_KEY</code> على الخادوم لتساوي نتيجة تنفيذ الأمر <code>php artisan --no-ansi key:generate --show</code>.
</p>

<p>
	حان الآن وقت النشر فعليا؛ ندفع التغييرات في المستودع المحلي إلى المستودع البعيد باستخدام Git على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_30">
$ git push heroku master
Counting objects: 103, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (84/84), done.
Writing objects: 100% (103/103), 43.87 KiB | 0 bytes/s, done.
Total 103 (delta 5), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----&gt; Fetching set buildpack https://github.com/heroku/heroku-buildpack-php... done
remote: -----&gt; PHP app detected
remote: 
remote:  !     WARNING: Your 'composer.json' contains a non-'stable' setting
remote:        for 'minimum-stability'. This may cause the installation of
remote:        unstable versions of runtimes and extensions during this deploy.
remote:        It is recommended that you always use stability flags instead,
remote:        even if you have 'prefer-stable' enabled. For more information,
remote:        see https://getcomposer.org/doc/01-basic-usage.md#stability
remote: 
remote: -----&gt; Bootstrapping...
remote: -----&gt; Installing platform packages...
remote:        - php (7.0.7)
remote:        - ext-mbstring (bundled with php)
remote:        - apache (2.4.20)
remote:        - nginx (1.8.1)
remote: -----&gt; Installing dependencies.
(...)
remote: -----&gt; Compressing...
remote:        Done: 15.5M
remote: -----&gt; Launching...
remote:        Released v4
remote:        https://nameless-chamber-90421.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/nameless-chamber-90421.git
* [new branch]      master -&gt; master</pre>

<p>
	إن نظرت إلى لوحة التحكّم في Heroku ستجد سجلا بالإجراءات السابقة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="18069" href="https://academy.hsoub.com/uploads/monthly_2016_06/01_Laravel_Heroku.png.b3774ff3bceb8579b492976eefb2c88c.png" rel="external"><img alt="01_Laravel_Heroku.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18069" data-unique="73m6hnehw" src="https://academy.hsoub.com/uploads/monthly_2016_06/01_Laravel_Heroku.thumb.png.efa70b296aef91ed546f1fae8c22bb9f.png"></a>
</p>

<p>
	هذا كلّ ما في الأمر؛ اكتمل نشرُ تطبيقك الآن ويمكنك الوصول إليه على الرابط المذكور أعلاه. يجب أن تظهر صفحة Laravel المبدئية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="18070" href="https://academy.hsoub.com/uploads/monthly_2016_06/02_Laravel_Heroku.png.c210afbb6f48613c0ef1a9d35786c89f.png" rel="external"><img alt="02_Laravel_Heroku.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18070" data-unique="geyqu8ujt" src="https://academy.hsoub.com/uploads/monthly_2016_06/02_Laravel_Heroku.thumb.png.f880691e2cffea10476633ee4c65fae6.png"></a>
</p>

<p>
	تذكّر أن الرابط المنشَأ سابقا موجود فقط لأغراض الاختبار والتجربة، عندما يكون تطبيقك جاهزا لتلقي الجماهير يمكنك استخدام نطاقك الخاص وربطه بالتطبيق.
</p>

<h2 id="تهجير-قاعدة-البيانات">
	تهجير قاعدة البيانات
</h2>

<p>
	نشرنا في الخطوات السابقة تطبيق Laravel جديدا؛ إلا أن هذه الخطوات لن تكون كافية إن كان التطبيق يعتمد على قاعدة بيانات. ستحتاج في هذه الحالة إلى التأكد من تنفيذ جميع التهجيرات العالقة بعد كلّ عملية نشر. بما أن التطبيق جديد على Heroku فسنحتاج لتموين Provision قاعدة البيانات؛ نستخدم Toolbelt لهذا الغرض:
</p>

<pre class="ipsCode" id="ips_uid_4211_32">
$ heroku addons:create heroku-postgresql:hobby-dev
Creating postgresql-rigid-59415... done, (free)
Adding postgresql-rigid-59415 to nameless-chamber-90421... done
Setting DATABASE_URL and restarting nameless-chamber-90421... done, v10
Database has been created and is available
 ! This database is empty. If upgrading, you can transfer
 ! data from another database with pg:copy
Use `heroku addons:docs heroku-postgresql` to view documentation.</pre>

<p>
	ينشئ الأمر السابق قاعدة بيانات PostgreSQL معرّفة بالخطة المجانيّة <code>hobby-dev</code> التي تمكننا من إنشاء قاعدة بيانات مجانية على Heroku، على ألا يتجاوز عدد أسطرها العشرة آلاف. توجد خطط أخرى يمكن النظر فيها لإيجاد ما يناسبك إن كنت تريد استخدام Heroku بيئةً للإنتاج. يعود السبب في اختيارنا لقاعدة بيانات PostgreSQL بدلا من MySQL إلى أن دعم الأخيرة على Heroku محدود، ستجد لهذا السبب أن الكثير من التوثيق حول خدمة Heroku يعتمد على <a href="https://academy.hsoub.com/devops/servers/databases/postgresql/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-postgresql-%D9%88%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%87-%D8%B9%D9%84%D9%89-ubuntu-1404-r147/" rel="">قاعدة البيانات PostgreSQL</a>.
</p>

<p>
	ثم نفذ الأمر التالي للحصول على المزيد من التفاصيل عن قاعدة البيانات ومن ضمنها الاستيثاق (تأكد من اسم التطبيق):
</p>

<pre class="ipsCode" id="ips_uid_4211_34">
$ heroku config --app nameless-chamber-90421 | grep DATABASE_URL
DATABASE_URL: postgres://USERNAME:PASSWORD@HOSTNAME:PORT/DATABASE</pre>

<p>
	يظهر في نتيجة الأمر اسمُ المستخدم <code>USERNAME</code>، كلمة السّر <code>PASSWORD</code>، اسم المضيف <code>HOSTNAME</code>، المنفذ <code>PORT</code> واسم قاعدة البيانات <code>DATABASE</code>. لن يكون ضروريا حفظ هذه الإعدادات فالمتغير <code>DATABASE_URL</code> الذي يخزّنها محفوظ تلقائيا في إعدادات الخادوم.
</p>

<p>
	يمكنك تسهيل إدارة قاعدتي البيانات على طرفيْ العمل (بيئة التطوير وبيئة الإنتاج) بضبط متغيّر بيئة باسم <code>DATABASE_URL</code> على جهازك المحلي وتخزين إعدادات قاعدة البيانات فيه ثم استخدامه لإعداد اتصال Laravel بقاعدة البيانات. ستحتاج لتثبيت PostgreSQL على جهازك إن لم يكن مثبتا مسبقا.
</p>

<p>
	يستعمل Laravel مبدئيا قاعدة بيانات MySQL، لذا يجب أن نعدّه لاستخدام PostgreSQL. نفتح ملفّ إعداد الاتصال بقاعدة البيانات <code>config/database.php</code> ونبحث عن السطر التالي: 
</p>

<pre class="ipsCode" id="ips_uid_4211_36">
'default' =&gt; env('DB_CONNECTION', 'mysql'),
</pre>

<p>
	ثم نعدّله على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_38">
'default' =&gt; env('DB_CONNECTION', 'pgsql'),
</pre>

<p>
	ثم ننتقل إلى المقطع الخاصّ بإعداد PostgreSQL ضمن ملفّ إعداد الاتصال ونعدّله ليصبح كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_40">
'pgsql' =&gt; [
    'driver'   =&gt; 'pgsql',
    'host'     =&gt; parse_url(getenv("DATABASE_URL"))["host"],
    'database' =&gt; substr(parse_url(getenv("DATABASE_URL"))["path"], 1),
    'username' =&gt; parse_url(getenv("DATABASE_URL"))["user"],
    'password' =&gt; parse_url(getenv("DATABASE_URL"))["pass"],
    'charset'  =&gt; 'utf8',
    'prefix'   =&gt; '',
    'schema'   =&gt; 'public',
],</pre>

<p>
	احفظ التعديلات ثم تأكد من أن اتصال التطبيق بقاعدة البيانات (محليّا)؛ يمكنك إنشاء <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%86%D9%85%D9%88%D8%B0%D8%AC%D8%A7-model-%D9%81%D9%8A-laravel-r297/" rel="">نموذج في Laravel</a> وتهجير مرافق له لغرض اختبار الاتصال بقاعدة البيانات.
</p>

<p>
	نفذ بعد التأكد من إعداد قاعدة البيانات التعديلات التي أضفتها إلى منطقة الإدارج في Git ثم أودعها في المستودع وأرسلها إلى المستودع البعيد على الخادوم:
</p>

<pre class="ipsCode" id="ips_uid_4211_42">
$ git add .
$ git commit -m "Updated database configuration"
$ git push heroku master</pre>

<p>
	يمكنك الآن تنفيذ التهجير على قاعدة البيانات على الخادوم عن طريق <span style="font-family:courier new,courier,monospace;">Toolbelt</span> كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_4211_44">
$ heroku run php artisan migrate --app nameless-chamber-90421
Running `php artisan migrate` attached to terminal... up, run.6981
**************************************
*     Application In Production!     *
**************************************

Do you really wish to run this command? [y/N] y
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_01_30_032004_create_todolists_table.php</pre>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://www.easylaravelbook.com/blog/2015/01/31/deploying-a-laravel-application-to-heroku/" rel="external">Deploying a Laravel Application to Heroku</a> لصاحبه W. Jason Gilmore.
</p>
]]></description><guid isPermaLink="false">357</guid><pubDate>Sat, 08 Oct 2016 17:20:00 +0000</pubDate></item><item><title>&#x62A;&#x62B;&#x628;&#x64A;&#x62A; Homestead &#x648;&#x625;&#x639;&#x62F;&#x627;&#x62F;&#x647; &#x644;&#x62A;&#x634;&#x63A;&#x64A;&#x644; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-homestead-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r361/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_11/laravel-homestead.png.fdd0f10481701fee1434fe3441b2960e.png" /></p>

<p>
	إن كنت تخطّط لتطوير مشروع على Laravel فإطار العمل - ولغة البرمجة PHP - لن يكونا كلّ ما تحتاجه للبدء في العمل؛ بل ستكون بحاجة إلى برنامج لإدارة قاعدة البيانات (مثلا MySQL أو PostgreSQL)، خادوم وِب (Nginx أو Apache) وربما تقنيات أخرى حسب الحاجة. قد يمثّل إعداد بيئة عمل بكلّ هذه التقنيات الكثير من العمل المرهق بالنسبة لك؛ خصوصا إن كنت ممّن يفضّل كتابة الشفرة البرمجية بدلا من التعامل مع مشاكل الإعدادات.
</p>

<p>
	مثّل ظهور الآلات الافتراضية Virtual machines, VM وانتشارها في السنوات الأخيرة فرصة للتغلب على الكثير من مشاكل الإعدادات. الآلات (الأجهزة) الافتراضية هي مجموعة برمجيات تعمل على نظام تشغيل لمحاكاة عمل جهاز فعلي. يمكن بهذه الطريقة مثلا، تشغيل أوبونتو لينكس داخل وندوز أو العكس. كما تمكن تجربة نظام مخصّص للخواديم داخل حاسوب شخصي؛ زيادة على أمور أخرى كثيرة. تتيح الآلات الافتراضية إعداد نظام تشغيل مخصّص، تثبيت برامج عليه، إعدادها؛ ثم توزيع النظام بعد ذلك للمهتمين للبدء في استعماله كما هو. استفاد مطورو Laravel من تقنية الآلات الافتراضية وأنشؤوا نظاما مخصّصا معدّا بجميع ما تحتاجه للبدء في التطوير على Laravel؛ أعطى فريق Laravel لهذه الآلات الافتراضية اسم Homestead. تستخدم Homestead برنامج إدارة الإعدادات Vagrant لتشغيلها.
</p>

<p>
	تأتي آلة Homestead معدّة بنظام تشغيل أوبونتو 14.04، لغة البرمجة PHP 7، خادوم وِب Nginx، نظامي إدارة قواعد بيانات MySQL وPostgreSQL وأدوات متفرقة أخرى. لا يتطلّب إعداد Vagrant لتشغيل Homestead الكثير من الوقت، كما أنه يعمل على OSX، لينكس ووندوز.
</p>

<h2 id="تثبيت-homestead">
	تثبيت Homestead
</h2>

<p>
	الخطوة الأولى لتثبيت Homestead هي تثبيت <a href="https://www.virtualbox.org/wiki/Downloads" rel="external nofollow">VirtualBox</a> و<a href="https://www.vagrantup.com/downloads.html" rel="external nofollow">Vagrant</a> على التوالي. يمكن من موقعي البرنامجيْن الحصولُ على مثبّتات Installers سهلة لأنظمة التشغيل المختلفة. افتح بعد تثبيت VirtualBox وVagrant سطر الأوامر ونفّذ الأمر التالي (قد  يستغرق تنزيل الآلة الافتراضية وقتا، حسب سرعة اتصالك بالإنترنت):
</p>

<pre class="ipsCode" id="ips_uid_9257_7">
$ vagrant box add laravel/homestead
==&gt; box: Loading metadata for box 'laravel/homestead'
    box: URL: https://atlas.hashicorp.com/laravel/homestead
This box can work with multiple providers! The providers that it
can work with are listed below. Please review the list and choose
the provider you will be working with.

1) virtualbox
2) vmware_desktop

Enter your choice: 1
==&gt; box: Adding box 'laravel/homestead' (v0.4.4) for provider: virtualbox
    box: Downloading: https://vagrantcloud.com/laravel/boxes/homestead/versions/0.4.4/providers/virtualbox.box
==&gt; box: Successfully added box 'laravel/homestead' (v0.4.4) for 'virtualbox'!</pre>

<p>
	يثبت الأمر أعلاه صندوق Homestead. يُستخدَم المصطلح صندوق Box للإشارة إلى حزمة في Vagrant. يعدّ مجتمع Vagrant آلات افتراضية بأنظمة تشغيل ثُبتت عليها برامج مختلفة - حسب الغرض - لتكون الآلة جاهزة للعمل فورا. يمكنك الحصول على لائحة بالآلات الافتراضية الشائعة الاستخدام التي يشرف مجتمع Vagrant على صيانتها عبر<a href="https://vagrantcloud.com/discover/popular" rel="external nofollow">هذا الرابط</a>.
</p>

<p>
	ثم ننتقل لتثبيت Homestead باستنساخ مستودع Github في <strong>المجلّد الشخصي</strong> للمستخدم كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_9257_9">
cd ~
git clone https://github.com/laravel/homestead.git Homestead</pre>

<p>
	ثم ننفذ، بعد نسخ المستودع، الأمر التالي الذي ينشئ ملفّ الإعداد <code>Homestead.yaml</code> ضمن مجلّد مخفي باسم <code>homestead.</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_11">
bash init.sh
</pre>

<p>
	<strong>ملحوظة:</strong> يجب تنفيذ الأمر من داخل المجلد <code>Homestead</code>.
</p>

<h2 id="إعداد-homestead">
	إعداد Homestead
</h2>

<p>
	تحدّد التعليمة <code>provider</code> في ملفّ الإعداد <code>homestead/Homestead.yaml.</code> المزوّد الذي سيستخدمه Vagrant؛ إما <code>virtualbox</code> أو <code>vmware_desktop</code>. في حالتنا اخترنا <code>virtualbox</code>.
</p>

<p>
	الخطوة التالية هي إعداد مجلّد المشروع الذي ستتشاركه مع الآلة الافتراضية. تتطلّب مشاركةُ مجلد المشروع تحديد مكان مفتاح <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr> العمومي الخاص بك. تُستخدَم التعمية Encryption المعتمدة على المفاتيح العموميّة والخصوصيّة لتأمين تشارك المجلّد مع الآلة الافتراضية.
</p>

<p>
	افتح ملفّ <code>Homestead.yaml</code> الموجود في مجلّد <code>homestead.</code> وحدّد مكان السّطر التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_13">
authorize: ~/.<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>/id_rsa.pub
</pre>

<p>
	إن كنت تعمل على لينكس أو OS X فلن تحتاج - على الأرجح - للتعديل على هذا السطر، نظرا لكون الملفات الخاصة بمفاتيح <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr> تُخزَّن عادة في مجلّد باسم <code><abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>.</code> ضمن مجلّد المستخدم. إن استخدمتَ مجلدا مخصّصا لمفاتيح <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr> فسيتوجّب عليك تحديث المسار بمقتضى ذلك. أما إذا كنت تستخدم وندوز فستحتاج إلى تحديث السطر ليوافق صيغة المسارات في وندوز، مثلا كالتالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_15">
authorize: c:/Users/wjgilmore/.<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>/id_rsa.pub
</pre>

<p>
	<strong>ملحوظة:</strong> استخدم برنامج PuTTY على وندوز لتوليد مفاتيح التعميّة.
</p>

<p>
	نحتاج الآن لتعديل قائمة المجلدات في ملفّ إعداد Homestead لتعيين مسار التطبيق. توجد فقرتان في ملفّ الإعدادات تتوليان التعامل مع مجلدات التطبيق وهما <code>folders</code> و<code>sites</code>. تبدو الفقرتان مبدئيا على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_9257_17">
folders:
    - map: ~/Code
    to: /home/vagrant/Code

sites:
    - map: homestead.app
    to: /home/vagrant/Code/Laravel/public</pre>

<p>
	تعرفّ الخاصيّة <code>map</code> في الفقرة <code>folders</code> المسار الذي توجد عليه ملفات مشروع Laravel الذي تعمل عليه. القيمة المبدئية لهذه الخاصيّة هي <code>Code/~</code>؛ بمعني أن Homestead يتوقّع وجود ملفات مشروعك ضمن مجلّد باسم <code>Code</code> متفرّع من المجلّد الشخصي للمستخدم. يمكنك تغيير قيمة هذه الخاصيّة حسب رغبتك؛ لكن تذكر أن المسار يجب أن يحيل إلى المجلد الجذر لمشروع Laravel. بالنسبة للخاصية <code>to</code> في الفقرة <code>folders</code> فتعرّف مسار المجلّد الذي ستُزامن معه محتويات المجلّد المعرَّف في الخاصيّة <code>map</code> السابقة. يمكن للآلة الافتراضية قراءة محتويات المجلد المعرَّف على المسار <code>to</code> عكس محتويات المجلّد المعرَّف في <code>map</code>. نتيجة لهذا الإعداد يُزامن محتوى المجلد الأخير (المعرَّف في <code>to</code>) تلقائيا مع محتوي المجلّد الأول (المعرَّف في <code>map</code>)؛ لتتمكن الآلة الافتراضية من قراءته.
</p>

<p>
	<strong>ملحوظة:</strong> من الأفضل ألا تحتوي أسماء المجلدات على مسافات.
</p>

<p>
	توجد في الفقرة <code>sites</code> خاصيتان تحملان نفس الاسميْن السابقيْن، <code>map</code> و<code>to</code>. تعرّف الخاصيّة <code>map</code> في الفقرة <code>sites</code> اسم النطاق الذي ستستخدمه للوصول إلى التطبيق؛ في المثال أعلاه تصل إلى التطبيق بكتابة <code>homestead.app</code> في شريط عنوان المتصفح. أما الخاصيّة <code>to</code> فتعرّف مجلّد الوِب الجذر في مشروع Laravel، وهو مبدئيا المجلّد <code>public</code> الموجود في المجلّد الجذر للمشروع.
</p>

<p>
	<strong>ملحوظة:</strong> المسارات المحدّدة في خاصيّة <code>to</code> في كلتا الحالتين هي بالنسبة لمجلدات موجودة <strong>داخل الآلة الافتراضية</strong>.
</p>

<p>
	سننشئ مجلّدا باسم <code>app.homestead</code> نخصّصه للمشروع الذي سنعمل عليه؛ نضيف مسار هذا المجلّد إلى الخاصية <code>map</code> في الفقرة <code>folders</code> التي تصبح كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_9257_19">
folders:
    - map: /home/zeine77/Documents/projects/app.homestead
    to: /home/vagrant/Code</pre>

<p>
	ثم ننشئ داخل المجلد <code>app.homestead</code> مجلدا باسم <code>Laravel</code> وداخل هذا الأخير مجلدا باسم <code>public</code> حتى نوافق مسار المجلد <code>home/vagrant/Code/Laravel/public/</code> الذي يشير إليه اسم النطاق (الخاصيّة <code>to</code> في الفقرة <code>sites</code>).
</p>

<p>
	<strong>ملحوظة:</strong> تذكّر أن المجلّد <code>home/vagrant/Code/</code> هو نسخة طبق الأصل من المجلّد <code>home/zeine77/Documents/projects/app.homestead/</code>، ولكنه موجود داخل الآلة الافتراضية. يعني هذا أن المجلّد <code>/Laravel/public</code> المستخدَم في الخاصيّة <code>to</code> من الفقرة <code>sites</code> (القيمة <code>/home/vagrant/Code/Laravel/public/</code>) يجب أن يكون موجودا في الأصل (أي في المجلّد <code>home/zeine77/Documents/projects/app.homestead/</code>). هذا هو السبب الذي جعلنا ننشئ المجلد <code>Laravel/public</code> بالطريقة المذكورة أعلاه.
</p>

<p>
	سننشئ الآن داخل المجلّد <code>public</code> ملفا باسم <code>index.php</code> ونضع فيه الشفرة التالية:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9257_21">
<span class="pun">&lt;?</span><span class="pln">php echo </span><span class="str">"Hello from Homestead!"</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;</span></pre>

<p>
	احفظ الملفّ ثم أغلقه. يعني هذا أننا عند تشغيل الآلة الافتراضية والدخول إلى العنوان <code>homestead.app</code> ستظهر لدينا العبارة <code>!Hello from Homestead</code>.
</p>

<p>
	الخطوة الأخيرة قبل الانتقال لتشغيل الآلة الافتراضية هي تعديل ملف المضيفات ليتعرّف النظام على العنوان <code>homestead.app</code>. يوجد ملف المضيفات على المسار <code>etc/hosts/</code> بالنسبة للينكس و <code>C:\Windows\System32\drivers\etc\hosts</code> بالنسبة لوندوز. أضف السّطر التالي إلى الملفّ:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_23">
192.168.10.10       homestead.app
</pre>

<p>
	<strong>ملحوظة:</strong> تأكّد من موافقة العنوان (<code>192.168.10.10</code> في السطر أعلاه) لعنوان IP الموجود في بداية الملفّ <code>Homestead.yaml</code>.
</p>

<p>
	حان الوقت - بعد إكمال الخطوات المشروحة أعلاه - لتشغيل الآلة الافتراضية وتجربة عمل الإعدادات. ننتقل إلى المجلد <code>Homestead</code> (حيثُ نسخنا المشروع من Github) ثم ننفّذ الأم التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_25">
$ vagrant up
</pre>

<p>
	يستغرق تشغيل الآلة الافتراضية بعض الوقت وتظهر مخرجات الأمر:
</p>

<pre class="ipsCode" id="ips_uid_9257_27">
Bringing machine 'default' up with 'virtualbox' provider...
==&gt; default: Importing base box 'laravel/homestead'...
==&gt; default: Matching MAC address for NAT networking...
==&gt; default: Checking if box 'laravel/homestead' is up to date...
(...)
==&gt; default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==&gt; default: Forwarding ports...
    default: 80 (guest) =&gt; 8000 (host) (adapter 1)
    default: 443 (guest) =&gt; 44300 (host) (adapter 1)
    default: 3306 (guest) =&gt; 33060 (host) (adapter 1)
    default: 5432 (guest) =&gt; 54320 (host) (adapter 1)
    default: 22 (guest) =&gt; 2222 (host) (adapter 1)
(...)
==&gt; default: nginx stop/waiting
==&gt; default: nginx start/running, process 1940
==&gt; default: php7.0-fpm stop/waiting
==&gt; default: php7.0-fpm start/running, process 1959
(...)
==&gt; default: Running provisioner: shell...
default: Running: /tmp/vagrant-shell20160628-13381-s5ikfi.sh</pre>

<p>
	يمكنك الآن فتح المتصفّح وتجربة عمل الإعدادت بزيارة الرابط <code>http:homestead.app</code>. إن جرت الأمور على ما يُرام فستظهر العبارة التالية في المتصفّح:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_29">
Hello from Homestead !
</pre>

<p>
	إن تعذّر تشغيل الآلة الافتراضية (خطأ في مخرجات الأمر <code>vagrant up</code>) فتأكد من ملف الإعداد <code>Homestead.yaml</code>. إن اشتغلت الآلة ولم تستطع إظهار محتوى الصفحة فتأكد من إعدادات المضيف، وخصوصا عنوان IP وموافقته للعنوان الموجود في ملفّ الإعداد <code>Homestead.yaml</code>؛ ينبغي التأكد كذلك من المسارات ومن حالة كتابة الأحرف (كبيرة أو صغيرة).
</p>

<p>
	أنشأنا المجلّد <code>Laravel/public</code> وأضفنا إليه الملفّ <code>index.php</code> للتأكد من أن Homestead يعمل من دون مشاكل؛ لكن هدفنا هو استخدام Homestead لعرض مشاريع بـLaravel؛ وهو ما سنعدّه بعد قليل. يمكننا الآن توقيف عمل الآلة الافتراضية بتنفيذ الأمر (من داخل المجلد <code>Homestead</code>):
</p>

<pre class="ipsCode" id="ips_uid_9257_31">
$ vagrant destroy --force
==&gt; default: Forcing shutdown of VM...
==&gt; default: Destroying VM and associated drives...</pre>

<p>
	ثم حذف المجلّد <code>Laravel</code> (وبالتالي المجلد <code>public</code> المتفرع منه).
</p>

<h2 id="الولوج-إلى-الآلة-الافتراضية-عن-طريق-ssh">
	الولوج إلى الآلة الافتراضية عن طريق <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr>
</h2>

<p>
	نظرا لكون Homestead مبني على توزيعة أوبونتو فيمكن الولوج إليه عن طريق <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr>، تماما كما هي الحال بالنسبة لأي خادوم آخر. قد تودّ الدخول إلى الآلة الافتراضية لأسباب منها على سبيل المثال تغيير إعدادات قاعدة البيانات أو خادوم الوِب، إضافة برامج جديدة أو لإجراء تعديلات أخرى. استخدم الأمر التالي، <strong>بعد تشغيل الآلة الافتراضية</strong> ، للدخول عن طريق <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr>:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_33">
$ vagrant <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>
</pre>

<p>
	تظهر بعد تنفيذ الأمر رسالة ترحيبية ومحثّ Prompt أوامر:
</p>

<pre class="ipsCode" id="ips_uid_9257_35">
Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.19.0-25-generic x86_64)

* Documentation:  https://help.ubuntu.com/
vagrant@homestead:~$ </pre>

<p>
	سيُسجَّل دخولك باسم المستخدم <code>vagrant</code>؛ يمكنك بعدها تنفيذ أوامر لينكس حسب الحاجة. ستجد أنه يوجد مجلّد باسم <code>Code</code> داخل المجلّد الشخصي للمستخدم <code>vagrant</code>.<br>
	نفّذ الأمر <code>exit</code> إن أردت الخروج من الآلة الافتراضية.
</p>

<h2 id="إنشاء-تطبيق-laravel">
	إنشاء تطبيق Laravel
</h2>

<p>
	تأكدنا في الخطوات السابقة من إعداد Homestead وأنه جاهز للعمل. يمكننا الآن إنشاء مشروع Laravel على Homestead. لذا سنستخدم <code>composer</code> لإنشاء مشروع Laravel جديد داخل المجلّد <code>app.homestead</code>. اختر اسما مناسبا للمشروع؛ مثلا <code>demo</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_37">
$ composer create-project laravel/laravel demo
</pre>

<p>
	لدينا الآن مشروع Laravel على المسار <code>home/zeine77/Documents/projects/app.homestead/demo/</code>؛ ينبغي أن نعدّل ملفّ الإعداد <code>Homestead.yaml</code> ليشير إلى هذا المجلد. نفتح الملفّ لتحريره؛ ونغيّر قيمة الخاصيّة <code>to</code> ضمن الفقرة <code>sites</code>. القيمة القديمة هي التالية (أعددناها في خطوة سابقة):
</p>

<pre class="ipsCode" id="ips_uid_9257_39">
sites:
    - map: homestead.app
    to: /home/vagrant/Code/Laravel/public</pre>

<p>
	لتصبح كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_9257_41">
sites:
    - map: homestead.app
    to: /home/vagrant/Code/demo/public</pre>

<p>
	احفظ الملفّ ثم أغلقه. نعود لمجلّد <code>Homestead</code> وننفذ الأمر التالي لاعتماد التعديلات (إن كانت الآلة الافتراضية تعمل):
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_43">
$ vagrant provision
</pre>

<p>
	أما إن لم تكن الآلة الافتراضية تعمل فيجب تشغيلها:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_45">
$ vagrant up
</pre>

<p>
	انتظر اعتماد التعديلات أو تشغيل الآلة الافتراضية؛ ثم توجّه إلى المتصفّح وأدخل العنوان <code><a href="http://homestead.app" ipsnoembed="false" rel="external nofollow">http://homestead.app</a></code>، وستظهر الصفحة المبدئية لمشروع Laravel.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="18227" href="https://academy.hsoub.com/uploads/monthly_2016_06/01_homestead_laravel.png.d33107c492b9129161a21fc9f4e78b33.png" rel=""><img alt="01_homestead_laravel.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18227" data-unique="l7nnnbgik" src="https://academy.hsoub.com/uploads/monthly_2016_06/01_homestead_laravel.thumb.png.d25f425f17c8d8f6be6fb795555e49ab.png"></a>
</p>

<h3 id="خاتمة">
	خاتمة
</h3>

<p>
	لست ملزما بمشروع Laravel واحد على آلة Homestead؛ بل يمكنك إنشاء العدد الذي تريد. كل ما يجب عليك فعله هو تحديث قيم <code>map</code> و<code>to</code> في فقرتي <code>folders</code> و<code>sites</code> من ملف الإعداد <code>Homestead.yaml</code> بالمسارات المناسبة.
</p>

<p>
	يمكن مثلا اتخاذ مجلد لمشاريع Laravel تستخدمه لإنشاء المشاريع الجديدة داخله ثم تعدّ الخاصيّة <code>map</code> في <code>folders</code> للإشارة إلى المجلد المشترك؛ وعند إضافة مشروع جديد تضيف نطاقا جديدا له في <code>sites</code>؛ مع تحديث قيمة <code>to</code> لتشير إلى المجلد الموافق له في المجلد المشترك كما في المثال التالي:
</p>

<pre class="ipsCode" id="ips_uid_9257_47">
folders:
    - map: /home/zeine77/Documents/projects/app.homestead
    to: /home/vagrant/Code

sites:
    - map: homestead.app
    to: /home/vagrant/Code/demo/public

    - map: anotherhomestead.app
    to: /home/vagrant/Code/anotherdemo/public</pre>

<p>
	لا تنس تحديث ملف المضيفات (<code>hosts</code>) بإضافة اسم النطاق الجديد (<code>anotherhomestead.app</code>) في المثال أعلاه:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9257_49">
192.168.10.10   anotherhomestead.app
</pre>

<p>
	ترجمة - بتصرّف - لمقال <a href="http://www.easylaravelbook.com/blog/2015/01/08/installing-and-configuring-homestead-2-dot-0-for-laravel-5/" rel="external">Installing and Configuring Homestead 2.0 for Laravel 5</a>. حقوق المقال محفوظة لصاحبه W. Jason Gilmore.
</p>
]]></description><guid isPermaLink="false">361</guid><pubDate>Wed, 28 Sep 2016 11:19:00 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644; &#x645;&#x637;&#x648;&#x651;&#x631;&#x64A; PHP &#x644;&#x644;&#x628;&#x62F;&#x621; &#x641;&#x64A; &#x628;&#x646;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; Laravel - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x646;&#x64A;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AF%D9%84%D9%8A%D9%84-%D9%85%D8%B7%D9%88%D9%91%D8%B1%D9%8A-php-%D9%84%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r364/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2018_04/5acf1d6bad1ed_--PHP-----Laravel----.png.59c793bd746639cfcef92dba47d4c7a7.png" /></p>

<p>
	هيأنا في <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%82%D8%A7%D8%A6%D9%85%D8%A9-%D9%85%D9%87%D8%A7%D9%85-todo-list-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%91%D9%84-r363/" rel="">الجزأ الأوّل من هذا الدرس </a>قاعدة البيانات والتهجيرات، وأعددنا أساس التوجيه والمخطّط العام للقوالب والعروض. نكمل في هذا الجزأ الثاني إعداد بقية العناصر اللّازمة لبناء تطبيق إدارة مهام قاعدي.
</p>

<h2 id="إضافة-المهام">
	إضافة المهامّ
</h2>

<h3 id="التحقق">
	التحقّق
</h3>

<p>
	لدينا الاآن استمارة في العرض <code>resources/views/tasks/index.blade.php</code>؛ سنحتاج لإضافة شفرة إلى الدالة <code>TaskController@store</code> من أجل التحقّق من المُدخلات القادمة من الاستمارة ثم إنشاء مهمة جديدة. نبدأ ب<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AD%D9%82%D9%82-%D9%85%D9%86-%D8%A7%D9%84%D9%85%D8%AF%D8%AE%D9%84%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r352/" rel="">التحقّق من المدخلات</a>.
</p>

<p>
	سنضع شرطا على حقل الاسم في استمارة إضافة مهمّة جديدة؛ يتمثّل الشرط في وجوب إدخال اسم للمهمة، على ألا يتجاوز طوله 255 محرفا Characters. إن لم يتحقّق الشرط نعيد المستخدم إلى الرابط <code>tasks/</code> مع إضاءة المُدخلات القديمة وإظهار أخطاء:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_7">
<span class="com">/**
* Create a new task.
*
* @param  Request  $request
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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">validate</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">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'required|max:255'</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>
	تتضمّن المتحكّمات في Laravel مبدئيا السمة <code>ValidatesRequests</code> التي يمكن عن طريقها التحقّق من موافقة المُدخلات لشروط تُحدَّد في مصفوفة من القواعد. تأخذ دالة التحقّق <code>validate</code> الطّلب <code>request$</code> الذي نريد التحقّق منه ومصفوفة القواعد التي نريد تطبيقها. تشير الشفرة أعلاه إلى أن الحقل <code>name</code> مطلوب <code>required</code> ويجب ألا يتجاوز طوله <code>255</code> (الشّرط <code>max</code>).
</p>

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

<h4 id="المتغير-errors">
	المتغيّر errors$
</h4>

<p>
	تذكّر أننا استخدمنا التعليمة <code>('include('common.errors@</code> داخل العرض <code>tasks.index</code> لتقديم أخطاء التحقّق عبر العرض <code>common.errors</code>. يمكّننا العرض <code>common.errors</code> من إظهار أخطاء التحقّق بسهولة وحسب نفس التنسيق في كامل التطبيق. نعرّف في ما يلي العرض <code>resources/views/common/errors.blade.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_9">
<span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count</span><span class="pun">(</span><span class="pln">$errors</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">&lt;!--</span><span class="pln"> </span><span class="typ">Form</span><span class="pln"> </span><span class="typ">Error</span><span class="pln"> </span><span class="typ">List</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"alert alert-danger"</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="str">&lt;strong&gt;</span><span class="typ">Whoops</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Something</span><span class="pln"> went wrong</span><span class="pun">!&lt;/</span><span class="pln">strong</span><span class="pun">&gt;</span><span class="pln">

        </span><span class="str">&lt;br&gt;&lt;br&gt;</span><span class="pln">

        </span><span class="str">&lt;ul&gt;</span><span class="pln">
            </span><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$errors</span><span class="pun">-&gt;</span><span class="pln">all</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $error</span><span class="pun">)</span><span class="pln">
                </span><span class="str">&lt;li&gt;</span><span class="pun">{{</span><span class="pln"> $error </span><span class="pun">}}&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="lit">@endforeach</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">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endif</span></pre>

<p>
	<strong>ملحوظة:</strong> يتوفّر المتغيّر <code>errors$</code> في كلّ عرض في Laravel. يحوي المتغيّر كائنا فارغا من الصّنف <code>ViewErrorBag</code> إن لم توجد أخطاء.
</p>

<h3 id="إنشاء-المهمة">
	إنشاء المهمّة
</h3>

<p>
	ضبطنا في الفقرة السابقة آلية التحقّق؛ يمكننا الآن إكمال الدالة <code>store</code> في المتحكم <code>TaskController</code> من أجل إنشاء مهمّة جديدة. نوجِّه المستخدم بعد إنشاء المهمّة إلى الرابط <code>tasks/</code>. سنلجأ إلى الإمكانيّات التي توفّرها علاقات Eloquent لإنشاء المهمّة.
</p>

<p>
	تتوفّر أغلب علاقات Eloquent على دالة باسم <code>create</code> تأخذ مصفوفة من الخاصيّات وتضبط تلقائيا قيمة المفتاح الخارجي Foreign key بالاعتماد على النماذج التي تربط بينها العلاقة، ثم تنشئ سطرا جديدا في جدول البيانات لتخزين خاصيّات الكائن.
</p>

<p>
	تستخدم الشفرة التالية متغيّرالطلب <code>request$</code> للحصول على المستخدم الذي طلب إنشاء المهمة <code>()request-&gt;user$</code> ثم باستخدام الدالة <code>create</code> في العلاقة <code>tasks</code> (عرّفناها سابقا في النموذج <code>User</code>) نعطي القيمة <code>request-&gt;name$</code> (أي الاسم الّذي أدخله المستخدم في الاستمارة) للخاصيّة <code>name</code> في النموذج <code>Task</code>. ستتولّى العلاقة <code>()tasks</code> تحديد قيمة معرّف المستخدم صاحب المهمة بالاعتماد على المعلومات الواردة في الطلب عن المستخدم.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_11">
<span class="com">/**
* Create a new task.
*
* @param  Request  $request
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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">validate</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">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'required|max:255'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">]);</span><span class="pln">

    $request</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">()-&gt;</span><span class="pln">tasks</span><span class="pun">()-&gt;</span><span class="pln">create</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"> $request</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">

    </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'/tasks'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ كيف أن تعريف العلاقات أتاح لنا إمكانيّة فعل الكثير من الأمور بسطر برمجي واحد تقريبا.
</p>

<h3 id="عرض-المهام-المخزنة">
	عرض المهامّ المخزّنة
</h3>

<p>
	سنحتاج للتعديل على الدالة <code>index</code> في المتحكّم <code>TaskController</code> من أجل تمرير المهامّ المخزّنة إلى العرض. تقبل الدالة <code>view</code> إضافة إلى اسم العرض، معطى ثانيا يحوي مصفوفة من البيانات المتوفّرة للعرض. يمكن معالجة كلّ عنصر من المصفوفة بعد تمريرها إلى العرض باستخدام متغيّر بنفس الاسم، مثلا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_13">
<span class="com">/**
* Display a list of all of the user's task.
*
* @param  Request  $request
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $tasks </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">()-&gt;</span><span class="pln">tasks</span><span class="pun">()-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'tasks.index'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'tasks'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tasks</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لكننا سنختار طريق حقن الاعتمادات التي يوفرها Laravel.
</p>

<h4 id="حقن-الاعتمادات">
	حقن الاعتمادات
</h4>

<p>
	يستخدم Laravel ، كما أشرنا لذلك في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%85%D8%B2%D9%88%D8%AF-%D8%AE%D8%AF%D9%85%D8%A9-service-provider-%D9%81%D9%8A-laravel-r326/" rel="">إنشاء مزود خدمة في Laravel</a> حاويةَ خدمة Service container لإدارة الاعتمادات بين الأصناف: ماهي الأصناف التي يعتمد عليها الصّنف الجديد للعمل؟ كيف يمكنه الحصول على كائن من هذه الأصناف؟ أين يوجد الصّنف وهل سبق لإطار العمل تحميلُه إلى الذاكرة؟
</p>

<h4 id="إنشاء-مستودع-في-laravel">
	إنشاء مستودع في Laravel
</h4>

<p>
	تمكّن المستودعات Repositories من تخليص المتحكّم من ضرورة معرفة مصدر البيانات؛ إذ تجرّد المصدر الذي تأتي منه (قاعدة بيانات، ملفّ، واجهة تطبيقات <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>). تساعد المستودعات - بهذه الحيلة - في زيادة قابليّة التطبيق للصيانة و<a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-phpunit-%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r296/" rel="">الاختبار</a>.
</p>

<p>
	نودّ أن نعرّف مستودعا باسم <code>TaskRepository</code> للوصول إلى بيانات نموذج المهمة <code>Task</code>. تفيد هذه الطريقة كثيرا عند تزايد حجم المشروع والحاجة لتشارك استعلامات Eloquent عبر التطبيق. سننشئ مجلدا باسم <code>Repositories</code> في المجلّد <code>app</code>. تذكّر أن Laravel يحمّل تلقائيا جميع مجلدات التطبيق؛ لذا يمكنك إنشاء المجلدات حسب الحاجة.ننشئ داخل مجلد المستودعات الصنف <code>TaskRepository</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_15">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Repositories</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\User</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TaskRepository</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * Get all of the tasks for a given user.
    *
    * @param  User  $user
    * @return Collection
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> forUser</span><span class="pun">(</span><span class="typ">User</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">return</span><span class="pln"> $user</span><span class="pun">-&gt;</span><span class="pln">tasks</span><span class="pun">()</span><span class="pln">
                    </span><span class="pun">-&gt;</span><span class="pln">orderBy</span><span class="pun">(</span><span class="str">'created_at'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'asc'</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4 id="حقن-المستودع">
	حقن المستودع
</h4>

<p>
	يمكننا الآن تمرير المستودع، بعد استدعائه، إلى مشيّد المتحكم <code>TaskController</code> ثم استخدامه في الدالة <code>index</code>. تصبح شفرة المتحكّم <code>TaskController</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_17">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Task</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Requests</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">


</span><span class="com">// استدعاء المستودع</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Repositories\TaskRepository</span><span class="pun">;</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TaskController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * The task repository instance.
    *
    * @var TaskRepository
    */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $tasks</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/**
    * Create a new controller instance.
    *
    * @param  TaskRepository  $tasks
    * @return void
    */</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"> __construct</span><span class="pun">(</span><span class="typ">TaskRepository</span><span class="pln"> $tasks</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">middleware</span><span class="pun">(</span><span class="str">'auth'</span><span class="pun">);</span><span class="pln">

        $this</span><span class="pun">-&gt;</span><span class="pln">tasks </span><span class="pun">=</span><span class="pln"> $tasks</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
    * Display a list of all of the user's task.
    *
    * @param  Request  $request
    * @return Response
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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"> view</span><span class="pun">(</span><span class="str">'tasks.index'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            </span><span class="str">'tasks'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">tasks</span><span class="pun">-&gt;</span><span class="pln">forUser</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">-&gt;</span><span class="pln">user</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">/**
    * Create a new task.
    *
    * @param  Request  $request
    * @return Response
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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">validate</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">
            </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'required|max:255'</span><span class="pun">,</span><span class="pln">
        </span><span class="pun">]);</span><span class="pln">

        $request</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">()-&gt;</span><span class="pln">tasks</span><span class="pun">()-&gt;</span><span class="pln">create</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"> $request</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">

        </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'/tasks'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4 id="إظهار-المهام">
	إظهار المهامّ
</h4>

<p>
	يمكننا، بعد تمرير البيانات إلى العرض <code>tasks/index.blade.php</code> من المتحكّم، إظهار المهامّ في جدول. تُستخدَم التعليمة <code>foreach@</code> في قوالب Blade لكتابة حلقات تكرارية يُحوّلها Laravel شفرة PHP.
</p>

<p>
	<strong>ملحوظة:</strong> سبق لنا <a href="https://academy.hsoub.com/programming/php/laravel/%d8%a8%d9%86%d8%a7%d8%a1-%d8%aa%d8%b7%d8%a8%d9%8a%d9%82-%d9%82%d8%a7%d8%a6%d9%85%d8%a9-%d9%85%d9%87%d8%a7%d9%85-todo-list-%d8%a8%d8%a7%d8%b3%d8%aa%d8%ae%d8%af%d8%a7%d9%85-laravel-%d8%a7%d9%84%d8%ac%d8%b2%d8%a1-%d8%a7%d9%84%d8%a3%d9%88%d9%91%d9%84-r363/#%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%B9%D8%B1%D8%B6-%D8%A7%D9%84%D9%85%D9%85%D8%AF%D8%AF-%D9%84%D9%84%D9%85%D8%AE%D8%B7%D8%B7" rel="">في الجزأ الأول من الدرس</a> تعريف استمارة إنشاء مهمة جديدة. توضع الشفرة أدناه مكان التعليق الأخير في قالب <code>tasks/index.blade.php</code> الذي أنشأناه سابقا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7837_20">
<span class="pln">    @if (count($tasks) &gt; 0)
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"panel panel-default"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"panel-heading"</span><span class="tag">&gt;</span><span class="pln">
                Current Tasks
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">

            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"panel-body"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;table</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"table table-striped task-table"</span><span class="tag">&gt;</span><span class="pln">

                    </span><span class="com">&lt;!-- عناوين الجدول --&gt;</span><span class="pln">
                    </span><span class="tag">&lt;thead&gt;</span><span class="pln">
                        </span><span class="tag">&lt;th&gt;</span><span class="pln">Task</span><span class="tag">&lt;/th&gt;</span><span class="pln">
                        </span><span class="tag">&lt;th&gt;</span><span class="pln"> </span><span class="tag">&lt;/th&gt;</span><span class="pln">
                    </span><span class="tag">&lt;/thead&gt;</span><span class="pln">

                    </span><span class="com">&lt;!-- المهام الموجودة --&gt;</span><span class="pln">
                    </span><span class="tag">&lt;tbody&gt;</span><span class="pln">
                        @foreach ($tasks as $task)
                            </span><span class="tag">&lt;tr&gt;</span><span class="pln">
                                </span><span class="com">&lt;!-- اسم المهمة --&gt;</span><span class="pln">
                                </span><span class="tag">&lt;td</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"table-text"</span><span class="tag">&gt;</span><span class="pln">
                                    </span><span class="tag">&lt;div&gt;</span><span class="pln">{{ $task-&gt;name }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
                                </span><span class="tag">&lt;/td&gt;</span><span class="pln">

                                </span><span class="tag">&lt;td&gt;</span><span class="pln">
                                    </span><span class="com">&lt;!-- سنضع هنا الشفرة الخاصة بحذف مهمة --&gt;</span><span class="pln">
                                </span><span class="tag">&lt;/td&gt;</span><span class="pln">
                            </span><span class="tag">&lt;/tr&gt;</span><span class="pln">
                        @endforeach
                    </span><span class="tag">&lt;/tbody&gt;</span><span class="pln">
                </span><span class="tag">&lt;/table&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    @endif
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	شارف التطبيق على النهاية؛ ولكن تنقصنا طريقة تمكّن المستخدم من حذف مهام أضافها سابقا.
</p>

<h2 id="حذف-المهام">
	حذف المهام
</h2>

<h3 id="زر-حذف-مهمة">
	زرّ حذف مهمة
</h3>

<p>
	تركنا في العرض <code>tasks/index.blade.php</code> تعليقا للدلالة على المكان المفترض لزرّ حذف مهمة. سنضيف الآن، لكلّ سطر في جدول المهامّ، زرّا يمكّن من حذف المهمة الموجودة في السطر. يُرسَل، عند النقر على زرّ الحذف، طلب بإجراء <code>DELETE</code> إلى المسار <code>task/</code>، يستقبل المسار الطلب ويحيله إلى الدالة <code>destroy</code> في المتحكّم <code>TaskController</code>. نعدّل العرض <code>tasks/index.blade.php</code> بتعديل شفرة أسطُر الجدول لتصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7837_22">
<span class="tag">&lt;tr&gt;</span><span class="pln">
    </span><span class="com">&lt;!-- اسم المهمة --&gt;</span><span class="pln">
    </span><span class="tag">&lt;td</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"table-text"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div&gt;</span><span class="pln">{{ $task-&gt;name }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/td&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- زرّ حذف المهمة --&gt;</span><span class="pln">
    </span><span class="tag">&lt;td&gt;</span><span class="pln">
        </span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ url('task/'.$task-&gt;</span><span class="pln">id) }}" method="POST"&gt;
            {{ csrf_field() }}
            {{ method_field('DELETE') }}

            </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="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"delete-task-{{ $task-&gt;</span><span class="pln">id }}" class="btn btn-danger"&gt;
                </span><span class="tag">&lt;i</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"fa fa-btn fa-trash"</span><span class="tag">&gt;&lt;/i&gt;</span><span class="pln">Delete
            </span><span class="tag">&lt;/button&gt;</span><span class="pln">
        </span><span class="tag">&lt;/form&gt;</span><span class="pln">
    </span><span class="tag">&lt;/td&gt;</span><span class="pln">
</span><span class="tag">&lt;/tr&gt;</span></pre>

<p>
	لاحظ أن الاستمارة في خلية الجدول حيث يوجد زرّ الحذف تستخدم الإجراء <code>POST</code> بينما نجيب على الطلب بمسار يستخدم الإجراء <code>DELETE</code>. لا تسمح الاستمارات في HTML باستخدام سوى الإجراءيْن <code>POST</code> و<code>GET</code>، أي أننا يجب أن نجد طريقة لإرسال طلب بإجراء <code>DELETE</code>. يكمُن الحل في تنفيذ الدالة <code>('method_field('DELETE</code> داخل الاستمارة. تولّد هذه الدالة حقل إدخال <code>input</code> مخفيّا يتعرّف عليه Laravel ويستخدمه في إلغاء الإجراء المستخدَم في طلب HTTP. يبدو الحقل المولَّد كالتالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7837_24">
<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">"_method"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"DELETE"</span><span class="tag">&gt;</span></pre>

<h3 id="ربط-النموذج-والمسار">
	ربط النموذج والمسار
</h3>

<p>
	نحن الآن جاهزون لتعريف الدالة <code>destroy</code> في المتحكّم <code>TaskController</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_26">
<span class="com">/**
* Destroy the given task.
*
* @param  Request  $request
* @param  Task  $task
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> $task</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>
	سنلقي، قبل أن نكمل تعريف الدالة <code>destroy</code>، نظرة على المسار الخاصّ بحذف مهمة:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_28">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">delete</span><span class="pun">(</span><span class="str">'/task/{task}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'TaskController@destroy'</span><span class="pun">);</span></pre>

<p>
	نظرا لكون المتغيّر <code>{task}</code> في المسار يوافق المتغيّر <code>task$</code> في دالة المتحكم فإن Laravel سيربط تلقائيا بين الاثنين ويحقن كائنا مناسبا من النموذج <code>Task</code> في المسار؛ أي أن الكائن سيكون متاحا للمتحكّم لتنفيذ العمليات عليه.
</p>

<h3 id="التصريح">
	التصريح
</h3>

<p>
	لدى المتحكّم الآن نسخة من نموذج المهمة <code>Task</code> لاستخدامه في الدالة <code>destroy</code>، إلا أننا لسنا متأكدين من أن المستخدم هو فعلا صاحب المهمة التي طلب حذفها. يمكن، على سبيل المثال، تمرير معرّف عشوائي إلى الرابط <code>{tasks/{task</code>، وستحذف الدالة المهمة ذات المعرّف <code>{task}</code>، إن وُجدت. نستخدم قدرات إدارة التصريحات Authorization في Laravel لحلّ هذه المشكلة، والتأكد من أن المستخدَم المُسجَّل هو فعلا صاحب المهمة التي يطلُب حذفها.
</p>

<h3 id="إنشاء-سياسة-تصريح">
	إنشاء سياسة تصريح
</h3>

<p>
	يستخدم Laravel سياسات Policies لتنظيم التصريحات في أصناف صغيرة وسهلة. تتعلّق كلّ سياسة - عادة - بنموذج. نستخدم <code>artisan</code> لإنشاء سياسة تصريحات للنموذج <code>Task</code> كالتالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_7837_30">
php artisan make:policy TaskPolicy
</pre>

<p>
	سينشئ الأمر ملفا باسم <code>TaskPolicy.php</code> على المسار <code>/app/Policies</code>.
</p>

<p>
	نضيف دالة باسم <code>destroy</code> إلى سياسة التصريح <code>TaskPolicy</code>. تتلقى هذه الدالة كائنا من صنف <code>User</code> وآخر من صنف <code>Task</code>، ثمّ تتحقّق من أن معرّف المستخدم يطابق الحقل <code>user_id</code> في المهمة. تُرجع الدالة <code>destroy</code> في الصّنف <code>TaskPolicy</code> قيمة منطقية (<code>false</code>أو <code>true</code>)، كما هي الحال في جميع دوال سياسات التصريح:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_32">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Policies</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\User</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Task</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Auth\Access\HandlesAuthorization</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TaskPolicy</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">HandlesAuthorization</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/**
    * Determine if the given user can delete the given task.
    *
    * @param  User  $user
    * @param  Task  $task
    * @return bool
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="typ">User</span><span class="pln"> $user</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> $task</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"> $user</span><span class="pun">-&gt;</span><span class="pln">id </span><span class="pun">===</span><span class="pln"> $task</span><span class="pun">-&gt;</span><span class="pln">user_id</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نحتاج الآن لإخبار Laravel بأن سياسة التصريح <code>TaskPolicy</code> تنطبق على النموذج <code>Task</code>. يتمّ هذا الأمر عبر إضافة عنصر جديد إلى خاصيّة <code>policies$</code> في مزوّد خدمات الاستيثاق <code>app/Providers/AuthServiceProvider.php</code>. سيعرف Laravel بهذه الطريقة سياسة التصريح التي يجب عليه استخدامها للسماح بإجراء مّا (أو رفضه) على النموذج <code>Task</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_34">
<span class="com">/**
* The policy mappings for the application.
*
* @var array
*/</span><span class="pln">
</span><span class="kwd">protected</span><span class="pln"> $policies </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
</span><span class="str">'App\Task'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'App\Policies\TaskPolicy'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">];</span></pre>

<h3 id="السماح-بحذف-المهمة">
	السماح بحذف المهمة
</h3>

<p>
	سياسة التصريح جاهزة، ويمكننا بالتالي استخدامها في المتحكّم <code>TaskController</code>. يمكن لجميع المتحكمات في Laravel استخدام الدالة <code>authorize</code> التي توفّرها السمة <code>AuthorizesRequest</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_36">
<span class="com">/**
* Destroy the given task.
*
* @param  Request  $request
* @param  Task  $task
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> $task</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">authorize</span><span class="pun">(</span><span class="str">'destroy'</span><span class="pun">,</span><span class="pln"> $task</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// حذف المهمة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المعطى الأوّل المُمرَّر للدالة <code>authorize</code> هو اسم الدالة التي نريد استدعاءها في سياسة التصريح؛ المعطى الثاني هو الكائن الذي نريد التعامل معه. تذكّر أننا أخبرنا Laravel للتو أن سياسة التصريح <code>TaskPolicy</code> تنطبق على النموذج <code>Task</code>، أي أن إطار العمل يعرف في أي سياسة تصريح سيبحث عن الدالة التي حدّدنا اسمها في المعطى الأول المُمرَّر للدالة <code>authorize</code>. بالنسبة للمستخدم فإن المستخدم الحالي سيُرسَل تلقائيا إلى الدالة <code>destroy</code> في الصّنف <code>TaskPolicy</code>. إن تحقّق الشرط (المستخدم صاحب المهمة هو من طلب حذفها) فسيستمرّ تنفيذ الدالة <code>destroy</code> في المتحكّم <code>TaskController</code> بصورة طبيعية؛ وإلا فسينطلق <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D8%A7%D9%84%D9%85%D8%AE%D8%B5%D9%91%D9%8E%D8%B5%D8%A9-%D9%81%D9%8A-laravel-r299/" rel="">استثناء Exception</a> برمز الخطأ 403 (غياب التصريح) وتظهر صفحة خطأ.
</p>

<p>
	<strong>ملحوظة:</strong> ليست هذه هي الطريقة الوحيدة للتخاطب مع خدمات التصريح التي يوفرها Laravel.
</p>

<h3 id="حذف-المهمة">
	حذف المهمة
</h3>

<p>
	أخذنا الاحتياطات اللازمة، ويمكننا الآن إضافة الشفرة الخاصة بحذف مهمة من قاعدة البيانات. نستخدم دالة <code>delete</code> التي تتوفّر عليها نماذج Eloquent؛ ثم نوجّه المستخدم بعد حذف المهمة إلى المسار <code>tasks/</code>. تصبح الدالة <code>destroy</code> في المتحكّم <code>TaskController</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7837_38">
<span class="com">/**
* Destroy the given task.
*
* @param  Request  $request
* @param  Task  $task
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> $task</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">authorize</span><span class="pun">(</span><span class="str">'destroy'</span><span class="pun">,</span><span class="pln"> $task</span><span class="pun">);</span><span class="pln">

    $task</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'/tasks'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة - بتصرّف - للجزء الثاني من مقال <a href="https://laravel.com/docs/5.2/quickstart-intermediate" rel="external nofollow">Intermediate Task List</a>.
</p>
]]></description><guid isPermaLink="false">364</guid><pubDate>Tue, 13 Sep 2016 11:16:00 +0000</pubDate></item><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x62D;&#x642;&#x642; &#x645;&#x646; &#x627;&#x644;&#x645;&#x62F;&#x62E;&#x644;&#x627;&#x62A; &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AD%D9%82%D9%82-%D9%85%D9%86-%D8%A7%D9%84%D9%85%D8%AF%D8%AE%D9%84%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r352/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_09/laravel-input-validation.png.00c7331ccb98eec4724128fa304b5e6d.png" /></p>

<p>
	كان من الشائع في بدايات التطوير للوب كتابةُ الاستمارات بوسوم HTML ثم إضافة شفرة مخصَّصة للتأكد من مُدخَلات الزائر. وفّرت لغة البرمجة PHP بعد ذلك دوالَّ معيارية للتحقّق من المُدخلات؛ خفّفت هذه الدوّال قليلا من العبء على المطوِّر إلا أنها تركت له مهمّة تعريف طريقة للتحقّق من المُدخلات ومن ثمّ معالجتها أو إشعار الزائر بالبيانات غير الصالحة وعرض الاستمارة من جديد. يزيح Laravel هذه المتاعب بتوفير شيفرة للتحقّق وطريقة للتعامل مع المُدخلات.
</p>

<p>
	يقدّم هذا المقال دليلا لكيفيّة إنشاء استمارات والتحقّق من مدخلات الزائر في Laravel. سنأخذ مثالا لإضافة تصنيف Category ضمن جدول تصنيفات Categories في تطبيق؛ يمكن أن يتعلّق الأمر بتصنيف منشورات مدوّنة، منتجات متجر أو أي شيء مماثل.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="19013" data-unique="8a3c6qscm" src="https://academy.hsoub.com/uploads/monthly_2016_09/laravel-input-validation.png.601610ba93bb7479a2dcb7b6ebd951af.png" alt="laravel-input-validation.png"></p>

<h2 id="تهيئة-تطبيق-laravel">
	تهيئة تطبيق Laravel
</h2>

<p>
	نفترض أن Laravel <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel-5-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D8%B9%D9%84%D9%89-windows-%D9%88ubuntu-r212/" rel="">مثبَّت</a> وجاهز <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%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-%D9%81%D9%8A-laravel-5-r224/" rel="">للعمل مع قاعدة البيانات</a>. نهيّئ التطبيق قبل أن نشرع في إنشاء الاستمارة وأدوات التحقّق المصاحبة لها.
</p>

<h3 id="إنشاء-نومذج-التصنيف-والتهجير-الموافق-له">
	إنشاء نموذج التصنيف والتهجير الموافق له
</h3>

<p>
	سيتكون نموذج التصنيف من حقل للاسم إضافة إلى حقل المعرّف <code>id</code> والأختام الزمنية Timestamps. نستخدم <code>artisan</code> لتوليد النموذج والتهجير:
</p>

<pre class="ipsCode" id="ips_uid_9225_7">
$ php artisan make:model Category -m
Model created successfully.
Created Migration: 2016_06_13_010501_create_categories_table</pre>

<p>
	ثم نفتح ملفّ التهجير (داخل المجلّد <code>database/migrations</code>) ونحدّث الدالة <code>up</code> على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_9225_11">
public function up()
{
  Schema::create('categories', function (Blueprint $table) {
      $table-&gt;increments('id');
      $table-&gt;string('name');
      $table-&gt;timestamps();
  });
}</pre>

<p>
	ثم ننفّذ التهجير:
</p>

<pre class="ipsCode" id="ips_uid_9225_13">
$ php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2016_06_13_010501_create_categories_table</pre>

<p>
	ننتقل الآن للعمل على المتحكّم Controller الذي سيكون المسؤول عن معالجة محتوى الاستمارة.
</p>

<h3 id="إنشاء-المتحكم-وتعريف-المسارات">
	إنشاء المتحكم وتعريف المسارات
</h3>

<p>
	نستخدم أداة <code>artisan</code> لإنشاء المتحكّم الذي سنستخدمه - من بين أمور أخرى - لعرض النموذج ومعالجة بياناته:
</p>

<pre class="ipsCode" id="ips_uid_9225_15">
$ php artisan make:controller CategoriesController.php --resource
Controller created successfully.</pre>

<p>
	ينشئ أمر <code>make:controller</code> عند استخدام المعطى <code>resource--</code>متحكّما بدوال <code>update</code>، <code>edit</code>، <code>store</code>، <code>create</code>، <code>show``index</code> و<code>destroy</code>. راجع درس <a href="https://academy.hsoub.com/programming/php/laravel/%d8%a3%d8%b3%d8%a7%d8%b3%d9%8a%d8%a7%d8%aa-%d8%a8%d9%86%d8%a7%d8%a1-%d8%a7%d9%84%d8%aa%d8%b7%d8%a8%d9%8a%d9%82%d8%a7%d8%aa-%d9%81%d9%8a-%d8%a5%d8%b7%d8%a7%d8%b1-%d8%a7%d9%84%d8%b9%d9%85%d9%84-laravel-5-r216/" rel="">أساسيات بناء التطبيقات في إطار العمل Laravel 5 </a> للمزيد عن هذه الدوال.
</p>

<p>
	بقي لنا تعريف المسارات في الملفّ <code>app/Http/routes.php</code>؛ نستخدم <code>Route::resource</code> لهذا الغرض: 
</p>

<pre class="ipsCode" id="ips_uid_9225_17">
Route::resource('categories', 'CategoriesController');
</pre>

<h3 id="إنشاء-العروض-views">
	إنشاء العروض Views
</h3>

<p>
	نركّز لأغراض هذا الدّرس على الدالتيْن <code>create</code> و<code>store</code> المسؤولتيْن على التوالي عن عرض الاستمارة وتخزين بياناتها (في حال تجاوز اختبار التحقّق؛ كما سنرى). تبدو الدالتان لحدّ الساعة فارغتيْن:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_39">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</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="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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>create</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_37">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</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"> view</span><span class="pun">(</span><span class="str">'categories.create'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أي أننا نطلُب تقديم العرض <code>create.blade.php</code> الموجود في المجلّد <code>resources/views/categories</code>. ننشئ المجلّد <code>categories</code> وننشئ بداخله الملفّ <code>create.blade.php</code>. سنكتفي الآن بإضافة الوسوم التالية إلى ملفّ العرض:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9225_35">
<span class="tag">&lt;h1&gt;</span><span class="pln">Create a Category</span><span class="tag">&lt;/h1&gt;</span></pre>

<p>
	يمكنك بعد حفظ الملفّ زيارة الرابط <code>categories/create/</code> وسيظهر العنوان أعلاه.
</p>

<h2 id="إنشاء-استمارة-في-laravel">
	إنشاء استمارة في Laravel
</h2>

<p>
	نريد أن نعرض للزائر استمارة لملئها؛ يمكن أن ننشئ هذه الاستمارة بكتابة وسوم HTML المطلوبة في ملفّ العرض <code>create</code>؛ إلا أنه يمكننا الاستفادة من حزمة <code>laravelcollective/html</code> لتولّي هذه المهمّة. نضيف الحزمة إلى مشروع Laravel بتنفيذ الأمر التالي داخل مجلّد المشروع:
</p>

<pre class="ipsCode" id="ips_uid_9225_27">
$ composer require laravelcollective/html
</pre>

<p>
	ثم نفتح ملفّ الإعداد <code>config/app</code> ونضيف السطر التالي إلى مصفوفة <code>providers</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_33">
<span class="typ">Collective</span><span class="pln">\Html\HtmlServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span></pre>

<p>
	لتبدو المصفوفة كالتالي (نزعنا بعض محتويات المصفوفة للاختصار):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_31">
<span class="str">'providers'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="pun">...</span><span class="pln">
    </span><span class="typ">App</span><span class="pln">\Providers\AuthServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">App</span><span class="pln">\Providers\EventServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">App</span><span class="pln">\Providers\RouteServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">Collective</span><span class="pln">\Html\HtmlServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
</span><span class="pun">]</span></pre>

<p>
	نكمل مع نفس الملفّ بالانتقال إلى المصفوفة <code>aliases</code> التي نضيف إليها السّطر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_41">
<span class="pln">  </span><span class="str">'Form'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Collective</span><span class="pln">\Html\FormFacade</span><span class="pun">::</span><span class="kwd">class</span></pre>

<p>
	لتصبح كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_43">
<span class="str">'aliases'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
    </span><span class="str">'URL'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\URL</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Validator'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Validator</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'View'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\View</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Form'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Collective</span><span class="pln">\Html\FormFacade</span><span class="pun">::</span><span class="kwd">class</span><span class="pln">
</span><span class="pun">]</span></pre>

<p>
	احفظ الملفّ.
</p>

<p>
	أكملنا تثبيت الحزمة وإعدادها. نعيد فتح ملفّ العرض <code>create</code> ونعدّل محتواه ليصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9225_45">
<span class="tag">&lt;h1&gt;</span><span class="pln">Create a Category</span><span class="tag">&lt;/h1&gt;</span><span class="pln">

{!! Form::open(
array(
    'route' =&gt; 'categories.store', 
    'class' =&gt; 'form')
) !!}

@if (count($errors) &gt; 0)
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"alert alert-danger"</span><span class="tag">&gt;</span><span class="pln">
    There were some problems adding the category.</span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;ul&gt;</span><span class="pln">
        @foreach ($errors-&gt;all() as $error)
            </span><span class="tag">&lt;li&gt;&lt;/li&gt;</span><span class="pln">
        @endforeach
    </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
@endif

</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span><span class="pln">
    {!! Form::label('Category') !!}
    {!! Form::text('name', null, 
    array(
        'class'=&gt;'form-control', 
        'placeholder'=&gt;'List Name'
    )) !!}
</span><span class="tag">&lt;/div&gt;</span><span class="pln">

</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span><span class="pln">
    {!! Form::submit('Create Category!', 
    array('class'=&gt;'btn btn-primary'
    )) !!}
</span><span class="tag">&lt;/div&gt;</span><span class="pln">
{!! Form::close() !!}
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	تضيف حزمة <code>laravelcollective/html</code> تعليمات خاصّة بإنشاء الاستمارات إلى <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">نظام Blade للقوالب</a>.
</p>

<ul>
<li>
		يشير مسار الاستمارة إلى <code>categories/store</code> لأن دالّة <code>store</code> في المتحكّم <code>CategoriesController</code> هي التي ستتولّى معالجة بيانات الاستمارة. تستخدم التعليمة <code>Form::open</code> مبدئيا إجراء <code>POST</code>؛ لذا لا حاجة لتعيينه.
	</li>
	<li>
		يُستخدَم المقطع <code>if..@endif@</code> لتقديم معلومات إلى المستخدم عن أخطاء التحقق. سنفصّل هذا الأمر بعد قليل.
	</li>
	<li>
		مرّرنا لأغراض جمالية أصنافا وخاصيّات من Bootstrap إلى الاستمارة ؛ هذا ليس ضروريا وستعمل الاستمارة بدونه.
	</li>
</ul>
<p>
	تظهر الآن الاستمارة بالذهاب إلى <code>categories/create/</code>.
</p>

<p style="text-align: center;">
	<img alt="01_categories_create.png" class="ipsImage ipsImage_thumbnailed" data-fileid="17840" data-unique="9tg4fzbbz" src="https://academy.hsoub.com/uploads/monthly_2016_06/01_categories_create.png.25b0183d81761fa56ff66e247a214c95.png"></p>

<p>
	يمكنك إدخال اسم تصنيف وإرسال الاستمارة وستُوجَّه إلى <code>categories/store/</code> لكنّ شيئا لن يحدُث لأننا لم نكتب حتى الآن شيئا في الدالة <code>store</code> من المتحكّم <code>CategoriesController</code>.
</p>

<h3 id="معالجة-الاستمارة">
	معالجة الاستمارة
</h3>

<p>
	نعود للدالة <code>store</code> في المتحكم <code>CategoriesController</code>. هذه هي الدالة التي تُرسَل إليها بيانات الاستمارة بعد النقر على زرّ الإرسال. نحدّث المتحكّم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_47">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</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"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">

    $category </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">;</span><span class="pln">

    $category</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">

    $category</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> \Redirect</span><span class="pun">::</span><span class="pln">route</span><span class="pun">(</span><span class="str">'categories.show'</span><span class="pun">,</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">$category</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">));</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	بدأنا أولا باستيراد النموذج <code>Category</code> في المتحكّم ثم استخدمناه في الدالة <code>store</code> لتخزين تسجيلة Record جديدة في جدول قاعدة البيانات اعتمادا على محتويات الاستمارة؛ ثم بعد التخزين نعيد توجيه المستخدم إلى الدالة <code>show</code> ضمن المتحكّم <code>CategoriesController</code> مع معرّف التصنيف الذي أضفناه للتو. يمكننا تعديل الدالة <code>show</code> كالتالي لعرض رسالة تفيد بنجاح إضافة التصنيف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_49">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> show</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">//</span><span class="pln">
    $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
    $message </span><span class="pun">=</span><span class="pln"> </span><span class="str">"$category-&gt;name has been added succefully"</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> $message</span><span class="pun">;</span><span class="pln">       
</span><span class="pun">}</span></pre>

<p>
	من الملاحظ أننا لم نتحقّق في العمليّة السابقة من مُدخلات المستخدم. يعني هذا أنه يمكن - مثلا - ترك الحقل الخاصّ باسم التصنيف فارغا وسيُحفظ تصنيف بدون اسم في قاعدة البيانات؛ طبعا هذا غير مقبول.
</p>

<h2 id="التحقق-من-الاستمارة-قبل-الإرسال">
	التحقق من الاستمارة قبل الإرسال
</h2>

<p>
	يوفّر Laravel 5 ميزة تُسمى طلب الاستمارة Form request تسمح بالتحقق من حقول الاستمارة دون تلويث المتحكّم. يدير ملفّ منفصل قواعد التحقّق من الاستمارة؛ نستخدم أمر <code>artisan</code> التالي لإنشاء هذا الملفّ:
</p>

<pre class="ipsCode" id="ips_uid_9225_51">
$ php artisan make:request CreateCategoryFormRequest
Request created successfully.</pre>

<p>
	ينشئ الأمر ملفا باسم <code>CreateCategoryFormRequest.php</code> في المجلد <code>app/Http/Requests</code>. يبدو الملفّ كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_53">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Requests</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Requests\Request</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CreateCategoryFormRequest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Request</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"> authorize</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="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> rules</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">
            </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="pun">}</span></pre>

<p>
	عدّل الدالة <code>authorize</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_55">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> authorize</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></pre>

<p>
	نحتاج لتحديد القيمة <code>true</code> بالنسبة للدالة <code>authorize</code> لأنه في حال كانت القيمة <code>false</code> فلن تُعالج بيانات الاستمارة.
</p>

<p>
	ثم نعدّل الدالة <code>rules</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_57">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> rules</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">
    </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'required'</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تعرّف الدالة قواعد التحقّق؛ عرّفنا أعلاه الحقل <code>name</code> ضمن الاستمارة بأنه مطلوب <code>required</code>؛ أي أن الاستمارة لن تُرسَل إلا إذا كانت توجد قيمة لهذا الحقل. تمكن إضافة أكثر من شرط على الحقل كالتالي: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_59">
<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">'required|alpha'</span></pre>

<p>
	نحتاج الآن لدمج طلب الاستمارة في الدالة <code>store</code> ضمن المتحكّم <code>CategoriesController</code>. نبدأ باستيراد الصنف في المتحكّم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_61">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Requests\CreateCategoryFormRequest</span><span class="pun">;</span></pre>

<p>
	ثم نحدّث الدالة <code>store</code> ليكون الكائن الممرَّر إليها من الصّنف <code>CreateCategoryFormRequest</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9225_63">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">CreateCategoryFormRequest</span><span class="pln"> $request</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>
	ابتداءً من الآن سيتحقّق Laravel من بيانات الحقل قبل إرسالها؛ وفي حال الإخفاق في التحقق من الشرط سيعيد الزائر إلى صفحة الاستمارة مع عرض رسالة بوجود خطأ.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://www.easylaravelbook.com/blog/2015/08/17/creating-and-validating-a-laravel-5-form-the-definitive-guide/" rel="external">Creating and Validating a Laravel 5 Form: The Definitive Guide</a>. حقوق المقال محفوظة لصاحبه W. Jason Gilmore.
</p>
]]></description><guid isPermaLink="false">352</guid><pubDate>Thu, 08 Sep 2016 08:16:00 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644; &#x645;&#x637;&#x648;&#x651;&#x631;&#x64A; PHP &#x644;&#x644;&#x628;&#x62F;&#x621; &#x641;&#x64A; &#x628;&#x646;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; Laravel - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x623;&#x648;&#x651;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AF%D9%84%D9%8A%D9%84-%D9%85%D8%B7%D9%88%D9%91%D8%B1%D9%8A-php-%D9%84%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%91%D9%84-r363/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2018_04/5acf1dfbc0d61_--PHP-----Laravel----.png.12094571cdbed6489904667096d8c246.png" /></p>

<p>
	يقدّم دليل الانطلاق السريع هذا، المكوّن من جزأين، مقدّمة لإطار العمل Laravel. سنغطّي خلال هذه المقدّمة مواضيع تهجير قواعد البيانات Database migrations، ربط كائنات التطبيق بجداول قاعدة البيانات باستخدام Eloquent، التوجيه، الاستيثاق Authentication، التصريح Authorization، حقن الاعتمادات، التحقّق، العروض Views وقوالب Blade. هذه المقدّمة مناسبة إن كنت متعوّدا على أساسيات إطار العمل Laravel أو أطر العمل الأخرى التي تستخدم PHP.
</p>

<p>
	سنعمل في هذا الدرس على بناء تطبيق قاعدي، عبارة عن قائمة مهامّ، نوضّح من خلاله مجموعة مختارة من أهمّ ميزات Laravel. المصدر الكامل للمشروع <a href="https://github.com/laravel/quickstart-intermediate" rel="external nofollow">متوفّر على GitHub</a>.
</p>

<h2 id="التثبيت">
	التثبيت
</h2>

<p>
	نحتاج أولا لإنشاء مشروع Laravel جديد. يمكنك استخدام آلة <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-homestead-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r361/" rel="">Homestead</a> افتراضية أو <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel-5-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D8%B9%D9%84%D9%89-windows-%D9%88ubuntu-r212/" rel="">بيئة PHP محليّة</a> على جهازك. استخدم Composer بعد تجهيز بيئة العمل لإنشاء مشروع Laravel جديد على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_197_7">
composer create-project laravel/laravel quickstart --prefer-dist "5.2.*"
</pre>

<p>
	يمكنك، إن أردت، تنزيل الشفرة المصدريّة النهائية للمشروع لتشغيلها على حاسوبك الشخّصي باستنساخ مستودع Git وتثبيت الاعتمادات الخاصّة بالمشروع على النحو التالي (حدّدنا الفرع 5.2 من المشروع؛ وهو الإصدار المستقرّ من المستودع أثناء كتابة هذا الدرس):
</p>

<pre class="ipsCode" id="ips_uid_7628_7">
git clone -b 5.2 --single-branch https://github.com/laravel/quickstart-intermediate/ quickstart-final
cd quickstart-final
composer install
php artisan migrate</pre>

<p>
	كما يمكنك متابعة خطوات هذا الدرس للحصول في النهاية على نتيجة مشابهة، مع شرح الميزات المستخدمة.
</p>

<h2 id="تهيئة-قاعدة-البيانات">
	تهيئة قاعدة البيانات
</h2>

<h3 id="التهجيرات">
	التهجيرات
</h3>

<p>
	سنبدأ بإنشاء <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%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-%D9%81%D9%8A-laravel-5-r224/" rel="">تهجيرات</a> لتعريف جدول قاعدة البيانات الذي سيخزّن جميع المهامّ التي سيديرها التطبيق. توفّر التهجيرات في Laravel وسيلة سهلة ومعبّرة لتعريف جداول البيانات باستخدام شفرة PHP. تفيد التهجيرات - مثلا - أثناء العمل في فريق للحصول على نفس البنية في قاعدة البيانات؛ فبدلا من أن ينشئ كل عضو يدويا قاعدة بيانات محليّة لاحتياجات التطوير، فإنه ينفّذ التهجيرات للحصول على قاعدة بيانات بنفس البنية الموجودة لدى بقية الفريق.
</p>

<h4 id="جدول-المستخدمين">
	جدول المستخدمين
</h4>

<p>
	نخطّط لجعل التطبيق يتيح للمستخدمين إنشاء حسابات، أي أنه يتوجّب علينا إنشاء جدول لحفظ بيانات هؤلاء المستخدمين. يأتي Laravel مبدئيا بتهجير لإنشاء جدول للمستخدمين، مما يغنينا عن إنشائه يدويا. يوجد التهجير المبدئي للمستخدمين في المجلّد <code>database/migrations</code>.
</p>

<h4 id="جدول-المهام">
	جدول المهامّ
</h4>

<p>
	العنصر الثاني في تطبيقنا هو المهامّ؛ التي يتوجّب علينا حفظ معلومات عنها. لذا، سننشئ جدولا خاصّا بالمهامّ. تُستخدَم <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-laravel-5-r216/#%D8%A3%D8%AF%D8%A7%D8%A9-artisan" rel="">أداة <code>artisan</code></a> التي تعمل من سطر الأوامر لتوليد أنواع مختلفة من الأصناف Classes وتختصر الكثير من الوقت أثناء تطوير التطبيقات في Laravel. سنستعين بهذه الأداة لإنشاء التهجير الخاصّ بجدول المهامّ، وذلك على النحو التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_5457_11">
php artisan make:migration create_tasks_table --create=tasks
</pre>

<p>
	يطلُب أمر <code>artisan</code> أعلاه توليد تهجيرٍ باسم <code>create_tasks_table</code> ويحدّد اسم جدول البيانات الذي نريد إنشاءه <code>create=tasks--</code>. يوضَع التهجير المولَّد في المجلّد <code>database/migrations</code> الموجود في مجلّد المشروع. إن فتحت ملفّ التهجير <code>create_tasks_table</code> (اسم الملفّ يبدأ بختم زمني يوافق وقت توليد الملفّ) ستجد أن الأمر أضاف حقلا لمعرّف يزداد تلقائيا Auto-incrementing ID وأختاما زمنيّة Timestamps ضمن حقول الجدول. نحرّر الملفّ المولَّد ونضيف عمودا من نوع سلسلة محارف String لأسماء المهامّ وعمودا آخر باسم <code>user_id</code> لربط المهامّ بالمستخدمين (حتى نعرف صاحب المهمة):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_13">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CreateTasksTable</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * Run the migrations.
    *
    * @return void
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">integer</span><span class="pun">(</span><span class="str">'user_id'</span><span class="pun">)-&gt;</span><span class="pln">index</span><span class="pun">();</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</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">/**
    * Reverse the migrations.
    *
    * @return void
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">drop</span><span class="pun">(</span><span class="str">'tasks'</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="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%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-%D9%81%D9%8A-laravel-5-r224#%D9%85%D8%AA%D8%B7%D9%84%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1" rel="">متطلّبات التهجير</a> لتمكين الاتصال بين التطبيق وقاعدة البيانات وبين أداة <code>artisan</code> وقاعدة البيانات (ليكن اسمُ قاعدة البيانات <code>quickstartdb</code>، مثلا). ثم بعد التأكد نفّذ أمر التهجير على النحو التالي (إن كنت تستخدم Homestead فسيتوجب عليك تنفيذ الأمر من داخل الآلة الافتراضية):
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_5457_15">
php artisan migrate
</pre>

<p>
	سينشئ الأمر السابق الجداول التي عرّفناها في التهجيرات. يمكنك التأكد من الأمر بالنظر في قاعدة البيانات وسرد الجداول الموجودة فيها.
</p>

<p>
	ننتقل الآن لتعريف نماذج Eloquent الخاصّة بالمشروع.
</p>

<h3 id="نماذج-eloquent">
	نماذج Eloquent
</h3>

<p>
	يستخدم Laravel مبدئيا إطار العمل Eloquent ل<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-eloquent-orm-%D9%84%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r227/#%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-eloquent" rel="">ربط الكائنات في التطبيق بالجداول في قاعدة البيانات</a> Object-relational mapping. يسهّل Eloquent استرجاع البيانات وتخزينها في قاعدة البيانات، وذلك عن طريق نماذج معرَّفة بوضوح. يوافق كلّ نموذج Eloquent عادة جدولًا في قاعدة البيانات.
</p>

<h4 id="نموذج-المستخدم">
	نموذج المستخدم
</h4>

<p>
	نحتاج أولا إلى نموذج Model ليربط الكائنات التي تمثّل المستخدمين في التطبيق بجدول المستخدمين <code>users</code> في قاعدة البيانات. إن نظرت في مجلّد التطبيق <code>app</code> داخل مشروعك فستجد أن Laravel يأتي مبدئيا بنموذج مستخدم <code>User.php</code>؛ أي أننا لن نحتاج لإنشاء واحد.
</p>

<h4 id="نموذج-المهمة">
	نموذج المهمة
</h4>

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

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_5457_17">
php artisan make:model Task
</pre>

<p>
	ينشئ الأمر نموذجا فارغا باسم <code>Task.php</code> ويضعه في المجلد <code>app</code>. لن تحتاج لإخبار Eloquent بجدول البيانات الذي يتوافق مع النموذج لأن Eloquent يفترض أن اسم الجدول هو جمع لاسم النموذج. بمعنى أن النموذج <code>User</code> يتوافق مع الجدول <code>users</code> والنموذج <code>Task</code> مع الجدول <code>tasks</code> (تبدأ أسماء النماذج بأحرف كبيرة، فيما تبدأ أسماء الجداول بأحرف صغيرة).
</p>

<p>
	نعدّل على ملفّ النموذج <code>Task</code> لإتاحة إمكانية الإسناد الشامل Mass assignment للحقل <code>name</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8132_7">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * The attributes that are mass assignable.
    *
    * @var array
    */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pun">];</span><span class="pln">
    
   </span><span class="com">/**
   * The attributes that should be cast to native types.
   *
   * @var array
   */</span><span class="pln">
   </span><span class="kwd">protected</span><span class="pln"> $casts </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
      </span><span class="str">'user_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'int'</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سنعود لاستخدام النماذج عند الحديث عن تعريف مسارات Routes التطبيق.
</p>

<p>
	<strong>ملحوظة:</strong>  عند الاستعلام عن بيانات من قاعدة بيانات MySQL في PHP فإن نوع البيانات المتحصَّل عليه هو دائما <code>string</code> (سلسلة محارف). استخدمنا في النموذج أعلاه المصفوفة <code>casts</code> للتأكيد على أن الخاصية <code>user_id</code> في الصنف <code>Task</code> يجب أن تكون من النوع <code>int</code>. سنتمكّن بهذه الطريقة من استخدام المعامل <code>===</code> (المساواة التامة، في القيمة ونوع البيانات).
</p>

<h3 id="علاقات-eloquent">
	علاقات Eloquent
</h3>

<p>
	عرفنا في الفقرتين السابقتين النموذجيْن <code>User</code> و<code>Task</code>؛ المستخدم والمهمة على التوالي، يجب الآن تعريف العلاقة التي تربط بين الاثنين. يمكن لمستخدم إنشاء أكثر من مهمّة، لكنّ مهمّة محدّدة لا يمكن أن تُسنَد سوى لمستخدم واحد فقط. يمكّن تعريف العلاقات بين النماذج من الحصول بسهولة على البيانات الطلوبة. مثلا؛ يمكن، بعد تعريف العلاقة بين المستخدم والمهام، إيجادُ مهامّ المستخدم ذي المعرّف <code>1</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_21">
<span class="pln">$user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\User</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="lit">1</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">$user</span><span class="pun">-&gt;</span><span class="pln">tasks </span><span class="kwd">as</span><span class="pln"> $task</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $task</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4 id="علاقة-المستخدم-بالمهام">
	علاقة المستخدم بالمهام
</h4>

<p>
	نحدّد أولا طبيعة العلاقة بين المستخدم والمهامّ. تعرَّف العلاقات في Eloquent بدوالّ في النموذج. تحدّد الدوال طبيعة العلاقة بين النموذجين. يمكن أن يكون للمستخدم، كما أسلفنا، أكثرُ من مهمة، تُسمّى هذه العلاقة في Eloquent بـ<code>hasMany</code>، وتعرَّف بإضافة دالة <code>tasks</code> على النحو التالي إلى النموذج <code>User</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_23">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Foundation\Auth\User </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">Authenticatable</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">User</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Authenticatable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * The attributes that are mass assignable.
    *
    * @var array
    */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'email'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'password'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

    </span><span class="com">/**
    * The attributes that should be hidden for arrays.
    *
    * @var array
    */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $hidden </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'remember_token'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
    </span><span class="com">/**
    * Get all of the tasks for the user.
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> tasks</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">hasMany</span><span class="pun">(</span><span class="typ">Task</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4 id="علاقة-المهمة-بالمستخدم">
	علاقة المهمّة بالمستخدم
</h4>

<p>
	نعرفّ، في الجانب الآخر، على مستوى النموذج <code>Task</code>، طبيعة العلاقة التي تربط المهمة بالمستخدم. نعرّف، كما فعلنا عند تعريف علاقة المستخدم بالمهامّ، دالةً مع تحديد طبيعة العلاقة التي هي في هذه الحالة <code>belongsTo</code>. بمعنى أن المهمة تتبع للمستخدم؛ أي أنه لا يمكن أن تتبع نفس المهمة لأكثر من مستخدم.
</p>

<p>
	يمكن تقريب الفكرة بالقول إن الناظر للعلاقة من جهة المهمة يرى أنه تسير في اتجاه واحد <code>belongsTo</code> (مستخدم واحد)؛ أما الناظر إليها من جهة المستخدم فيرى أنها يمكن أن تسير في عدّة اتجاهات <code>hasMany</code> (مهامّ متعدّدة):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_25">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\User</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * The attributes that are mass assignable.
    *
    * @var array
    */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pun">];</span><span class="pln">

    </span><span class="com">/**
    * Get the user that owns the task.
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</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">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="typ">User</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="التوجيه">
	التوجيه
</h2>

<p>
	تُستخدَم <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-laravel-5-r216/#%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%8A%D9%87-%D9%81%D9%8A-laravel" rel="">المسارات</a> Routes لتوجيه الروابط URL إلى متحكّم أو دالة تُنفَّذ عند زيارة رابط محدَّد. تُعرَّف المسارات مبدئيا في Laravel ضمن الملفّ <code>app/Http/routes.php</code>. تتيح المتحكمات التعامل مع طلبات Http بتوزيعها بين ملفات مختلفة من أجل تنظيم أفضل وصيانة أسهل.
</p>

<h3 id="إظهار-عرض">
	إظهار عرض
</h3>

<p>
	سيكون لدينا مسار <code>/</code> تظهر للزائر عند طلبه صفحة ترحيبية. تنتُج الصفحة الترحيبية عن معالجة قالب HTML. مبدئيا؛ يُخزّن Laravel جميع قوالب HTML في المجلّد <code>resources/views</code>.
</p>

<p>
	ستجد عند فتح الملفّ <code>routes.php</code> أنه يحوي الدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_27">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'welcome'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تستقبل هذه الدالة الطالبات الواردة على المسار <code>/</code> (مثلا <code>www.example.com</code>) وتقدّم إليها العرض <code>welcome.blade.php</code> باستخدام الدالة المساعدة <code>view</code>. لاحظ أننا لم نحدّد امتداد الملفّ في الدالة، اسم العرض (<code>welcome</code>) يكفي. سنعرّف العرض في ما بعد.
</p>

<h3 id="الاستيثاق">
	الاستيثاق
</h3>

<p>
	ذكرنا في تقديم المشروع الذي نودّ بناءه أننا نريد أن يتمكّن المستخدمون من إنشاء حسابات والولوج بها إلى التطبيق؛ أي أننا سنحتاج لآلية للاستيثاق. قد يتطلّب إنشاء آلية للاستيثاق الكثير من الجهد والوقت؛ إلا أن Laravel يحاول جعل هذه العمليّة أسهل ما يمكن.
</p>

<p>
	أولا؛ تمكن ملاحظة وجود المتحكّم <code>AuthController</code> في المجلد <code>app/Http/Controllers/Auth</code>. يستخدم هذا المتحكّم <a href="https://academy.hsoub.com/programming/php/%d8%a7%d9%84%d8%aa%d8%ac%d8%b1%d9%8a%d8%af-abstraction%c2%a0%d9%88%d8%a7%d9%84%d9%88%d8%a7%d8%ac%d9%87%d8%a7%d8%aa-interfaces-%d9%88%d8%a7%d9%84%d8%b3%d9%85%d8%a7%d8%aa-traits-%d9%81%d9%8a-php-r317/#%D8%A7%D9%84%D8%B3%D9%85%D8%A7%D8%AA-traits" rel="">السمة</a> <code>AuthenticatesAndRegistersUsers</code> التي تحوي الدوال المطلوبة لإنشاء المستخدمين والاستيثاق منهم.
</p>

<h4 id="مسارات-الاستيثاق-وعروضه">
	مسارات الاستيثاق وعروضه
</h4>

<p>
	الأساسيات المطلوبة لإنشاء مستخدمين والاستيثاق منهم موجودة مبدئيا كما أسلفنا؛ ولكن يبقى تعريف قوالب (عروض) التسجيل والاستيثاق، والمسارات التي تشير إلى متحكّم الاستيثاق. يمكننا باستخدام <code>artisan</code> تعريفُ القوالب بسهولة:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_29">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">auth</span></pre>

<p>
	لاحظ مخرجات الأمر والعروض التي أضافها للمشروع. تمكن أيضا ملاحظة أن الأمر أضاف المسارات التالية إلى ملفّ المسارات:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_31">
<span class="typ">Route</span><span class="pun">::</span><span class="pln">auth</span><span class="pun">();</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/home'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@index'</span><span class="pun">);</span></pre>

<p>
	تسجّل الدالة <code>auth</code> من الصّنف <code>Route</code> جميع المسارات التي نحتاجها لتسجيل حسابات جديدة للمستخدمين، ولوج مستخدمين مسجَّلين وإعادة تعيين كلمة السّر.
</p>

<p>
	يعرّف الأمر في المسار الثاني الرابط <code>home/</code> الذي تتعامل معه الدالة <code>index</code> في المتحكم <code>HomeController</code> الذي أنشأه الأمر السابق. إن فتحت ملفّ المتحكم <code>HomeController</code> فستجد أن الدالة <code>index</code> تطلُب إظهار العرض <code>home</code>.
</p>

<p>
	<strong>ملحوظة:</strong> إن كنت ترغب في الاطّلاع على الشفرة المصدرية الكاملة للعروض فهي متوفّرة ضمن شفرة المشروع على <a href="https://github.com/laravel/quickstart-intermediate/tree/master/resources/views" rel="external nofollow">GitHub</a>.
</p>

<p>
	افتح ملفّ المتحكّم <code>AuthController</code> (في المجلّد <code>app/Http/Controllers/Auth</code>) وغيّر قيمة <code>redirectTo$</code> كالتالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_33">
<span class="kwd">protected</span><span class="pln"> $redirectTo </span><span class="pun">=</span><span class="pln"> </span><span class="str">'/tasks'</span><span class="pun">;</span></pre>

<p>
	تحدّد هذه الخاصّيّة المسار الذي يُوجَّه الزائر إليه بعد الاستيثاق من بياناته. يجب أيضا التعديل على الملفّ <code>app/Http/Middleware/RedirectIfAuthenticated.php</code> ليرجع نفس المسار بعد ولوج الزائر:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_35">
<span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'/tasks'</span><span class="pun">);</span></pre>

<h4 id="المتحكم-في-المهام">
	المتحكم في المهام
</h4>

<p>
	ننشئ متحكّما جديدا خاصّا بالعمليات على المهامّ، مثل العثور على المهامّ المخزّنة وتخزين مهامّ جديدة. سنستخدم - كالعادة - أداة <code>artisan</code> لهذا الغرض:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_5457_37">
php artisan make:controller TaskController
</pre>

<p>
	ثم نعدّل ملفّ المسارات بإضافة المسارات التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_39">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'TaskController@index'</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/task'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'TaskController@store'</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">delete</span><span class="pun">(</span><span class="str">'/task/{task}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'TaskController@destroy'</span><span class="pun">);</span></pre>

<p>
	سنستخدم المسار <code>tasks/</code> مع الإجراء <code>get</code> للعثور على مهامّ مستخدِم، المسار <code>task/</code> مع الإجراء <code>post</code> لإضافة مهمة جديدة والمسار <code>{task/{task</code> مع الإجراء <code>delete</code> لحذف مهمّة؛ حيثُ <code>{task}</code> معرّف المهمة.
</p>

<h3 id="الاستيثاق-من-جميع-مسارات-المهام">
	الاستيثاق من جميع مسارات المهامّ
</h3>

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

<p>
	يمكن، بإضافة نداء لصنف الاستيثاق الوسيط <code>auth</code> داخل مشيّد Constructor المتحكّم <code>TaskController</code>، جعلُ جميع الإجراءات في المتحكّم تستدعي الاستيثاق من المستخدم (أن يكون مسجّلَ الدّخول). يعرّف الملف <code>app/Http/Kernel.php</code> جميع الأصناف الوسيطة الممكن تطبيقها على المسارات. يصبح المتحكم <code>TaskController</code> بعد إضافة الوسيط إلى المشيّد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_41">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Requests</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TaskController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * Create a new controller instance.
    *
    * @return void
    */</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">middleware</span><span class="pun">(</span><span class="str">'auth'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="إنشاء-القوالب-والعروض">
	إنشاء القوالب والعروض
</h2>

<p>
	يتضمّن الجزء الأساسي من التطبيق الذي نعملُ عليه عرضا واحدا توجد به استمارة لإضافة مهامّ جديدة، كما تظهر لائحة بالمهامّ الموجودة سلفا. في ما يلي لقطة من التطبيق المكتمل:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="18235" href="https://academy.hsoub.com/uploads/monthly_2016_06/01_application_layout.png.9cac9ce0b6f74eefcf982f082ec3b80d.png" rel=""><img alt="01_application_layout.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18235" data-unique="ar85ukdzg" src="https://academy.hsoub.com/uploads/monthly_2016_06/01_application_layout.thumb.png.53975759ed41c535134ae0e516c0599b.png"></a>
</p>

<h3 id="تعريف-مخطط-العرض">
	تعريف مخطّط العرض
</h3>

<p>
	تستخدم غالبية تطبيقات الوِب نفس المخطّط في كلّ الصفحات. بالنسبة للتطبيق الذي نعمل عليه فهو يحتوي على شريط تصفّح علوي يوجد في جميع الصفحات (في حال وجود أكثر من صفحة). تسهّل <a href="https://academy.hsoub.com/programming/php/laravel/%d8%a7%d8%b3%d8%aa%d8%ae%d8%af%d8%a7%d9%85-%d9%82%d9%88%d8%a7%d9%84%d8%a8-blade-%d9%84%d8%a5%d9%86%d8%b4%d8%a7%d8%a1-%d8%b9%d8%b1%d9%88%d8%b6-laravel-r220/" rel="">قوالب Blade</a> تشارك العناصر بين الصفحات.
</p>

<p>
	يحتفظ Laravel بجميع العروض ضمن المجلّد <code>resources/views</code>. سنعرّف قالبا جديدا لعروض Blade في الملفّ <code>resources/views/layouts/app.blade.php</code>. يستخدم Laravel نظام القوالب Blade لمعالجة الملفات التي تنتهي بالامتداد <code>blade.php.</code>. يمكن استخدام قوالب PHP تقليدية لتقديم العروض، إلا أن نظام Blade يوفّر قوالب مختصرة ومحكمة.
</p>

<p>
	افتح الملفّ <code>resources/views/layouts/app.blade.php</code> وستجد أن محتواه يشبه التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5457_43">
<span class="com">&lt;!-- resources/views/layouts/app.blade.php --&gt;</span><span class="pln">

</span><span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&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">Laravel Quickstart - Intermediate</span><span class="tag">&lt;/title&gt;</span><span class="pln">

        </span><span class="com">&lt;!-- شفرات CSS و JavaScript --&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;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;nav</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar navbar-default"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="com">&lt;!-- محتوى شريط التصفح Navbar  --&gt;</span><span class="pln">
            </span><span class="tag">&lt;/nav&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">

        @yield('content')
    </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	تحدّد التعليمة <code>('yield('content@</code> مكان الصفحات التي ستمدّد المخطّط الرئيس وتضيف محتوى خاصّا بها. راجع <a href="https://academy.hsoub.com/programming/php/laravel/%d8%a7%d8%b3%d8%aa%d8%ae%d8%af%d8%a7%d9%85-%d9%82%d9%88%d8%a7%d9%84%d8%a8-blade-%d9%84%d8%a5%d9%86%d8%b4%d8%a7%d8%a1-%d8%b9%d8%b1%d9%88%d8%b6-laravel-r220/#%D8%AA%D9%88%D8%B1%D9%8A%D8%AB-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8" rel="">توريث القوالب</a> في Laravel للمزيد من التفصيل. سننتقل الآن لتعريف العرض الإبن الذي سيستخدم المخطّط ويعرّف داخله محتوى خاصّا به.
</p>

<h4 id="تعريف-العرض-الممدد-للمخطط">
	تعريف العرض المُمدِّد للمخطَّط
</h4>

<p>
	سنحتاج لتعريف عرض يحوي استمارة لإنشاء مهمة جديدة وجدولا لعرض المهامّ الموجودة. ننشئ لهذا الغرض عرضا على المسار <code>resources/views/tasks/index.blade.php</code>، الذي ستطلب الدالة <code>index</code> في المتحكّم <code>TaskController</code> عرضه.
</p>

<p>
	سنركّز في ما يلي على التعليمات المتعلّقة بـBlade ونتجاوز شفرة Bootstrap CSS (يمكن الحصول على الشفرة كاملة من مستودع المشروع على <a href="https://github.com/laravel/quickstart-intermediate/tree/master/resources/views" rel="external nofollow">GitHub</a>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1712_9">
<span class="com">&lt;!-- resources/views/tasks/index.blade.php --&gt;</span><span class="pln">

@extends('layouts.app')

@section('content')

    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-sm-offset-2 col-sm-8"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"panel panel-default"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"panel-heading"</span><span class="tag">&gt;</span><span class="pln">
                    New Task
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">

    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"panel-body"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="com">&lt;!-- إظهار أخطاء التحقّق --&gt;</span><span class="pln">
        @include('common.errors')

        </span><span class="com">&lt;!-- استمارة إنشاء مهمة --&gt;</span><span class="pln">
        </span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ url('task') }}"</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"POST"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-horizontal"</span><span class="tag">&gt;</span><span class="pln">
            {{ csrf_field() }}

            </span><span class="com">&lt;!-- اسم المهمة --&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"task-name"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-sm-3 control-label"</span><span class="tag">&gt;</span><span class="pln">Task</span><span class="tag">&lt;/label&gt;</span><span class="pln">

                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-sm-6"</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">"text"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"task-name"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">

            </span><span class="com">&lt;!-- زرّ إضافة مهمة --&gt;</span><span class="pln">
            </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-sm-offset-3 col-sm-6"</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="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-default"</span><span class="tag">&gt;</span><span class="pln">
                        </span><span class="tag">&lt;i</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"fa fa-plus"</span><span class="tag">&gt;&lt;/i&gt;</span><span class="pln"> Add Task
                    </span><span class="tag">&lt;/button&gt;</span><span class="pln">
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
            </span><span class="tag">&lt;/div&gt;</span><span class="pln">
        </span><span class="tag">&lt;/form&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">

     </span><span class="com">&lt;!-- سنضع هنا الشفرة الخاصة بعرض المهام التي أنشأها المستخدم --&gt;</span><span class="pln">
@endsection</span></pre>

<ul>
<li>
		<p>
			تُخبر التعليمة <code>extends@</code> نظام القوالب Blade أننا في طور استخدام المخطّط المعرَّف في الملفّ <code>resources/views/layouts/app.blade.php</code>. يضع نظامُ القوالب جميعَ المحتوى الموجود بين التعليمتيْن <code>('section('content@</code> و<code>endsection@</code> مكان التعليمة <code>('yield('content@</code> في المخطّط <code>app.blade.php</code>.
		</p>
	</li>
	<li>
		<p>
			تحمّل التعليمة <code>('include('common.errors@</code> القالب <code>resources/views/common/errors.blade.php</code>. هذا القالب غير معرَّف لحد الساعة، ولكن سنعرّفه بعد قليل.
		</p>
	</li>
</ul>
<p>
	نعود للمتحكّم <code>TaskController</code> ونضيف الدالة <code>index</code> التي تطلُب تقديم العرض <code>resources/views/tasks/index.blade.php</code> الذي أنشأناه للتو:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5457_47">
<span class="com">/**
* Display a list of all of the user's task.
*
* @param  Request  $request
* @return Response
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</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"> view</span><span class="pun">(</span><span class="str">'tasks.index'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يشير الاسم <code>tasks.index</code> إلى أن المطلوب هو إظهار العرض <code>index.blade.php</code> الموجود في المجلد <code>tasks</code> الذي يوجد بدوره في مجلد العروض (أي <code>resources/view</code>).
</p>

<p>
	أصبحت أغلب عناصر التطبيق جاهزة. سنكمل في الجزء الثاني لهذا المقال بقية العناصر التي ستمكّن من إضافة مهامّ جديدة، عرض مهام موجودة أو حذفها.
</p>

<p>
	سنواصل في المقال القادم بناء التّطبيق.
</p>

<p>
	ترجمة - بتصرّف - للجزء الأول من مقال <a href="https://laravel.com/docs/5.2/quickstart-intermediate" rel="external nofollow">Intermediate Task List</a>.
</p>
]]></description><guid isPermaLink="false">363</guid><pubDate>Mon, 05 Sep 2016 11:18:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x642;&#x627;&#x626;&#x645;&#x62A;&#x64A;&#x646; &#x645;&#x646;&#x633;&#x62F;&#x644;&#x62A;&#x64A;&#x646; (Dropdown lists) &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Laravel &#x648; jQuery</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%82%D8%A7%D8%A6%D9%85%D8%AA%D9%8A%D9%86-%D9%85%D9%86%D8%B3%D8%AF%D9%84%D8%AA%D9%8A%D9%86-dropdown-lists-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-%D9%88-jquery-r323/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/laravel-jquery-dropdown-menu.png.865539d1d5c8f7386edbdd47354ac771.png" /></p>

<p>
	نسعى في هذا الدّرس إلى إنشاء قائمتين منسدلتين Dropdown lists ترتبط إحداهما بالأخرى. تحتوي الأولى مثلا على تصنيف والثانية على تصنيف فرعي من التصنيف الموجود في القائمة الأولى. يعني هذا أنْ تتغيّر التصنيفات الفرعيّة الموجودة في القائمة الثّانيّة عند تغيّر العنصُر المحدّد في القائمة الأولى.
</p>

<p style="text-align: center;">
	<img alt="laravel-jquery-dropdown-menu.png" class="ipsImage ipsImage_thumbnailed" data-fileid="17905" data-unique="ythvqu7xh" src="https://academy.hsoub.com/uploads/monthly_2016_06/laravel-jquery-dropdown-menu.png.4071f068c33dcd424c3751d9b3b27b4f.png"></p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="15892" href="https://academy.hsoub.com/uploads/monthly_2016_05/01_dependent_dropdown.png.097ba1f13c611ff6600e009b1248a061.png" rel=""><img alt="01_dependent_dropdown.png" class="ipsImage ipsImage_thumbnailed" data-fileid="15892" data-unique="164kww4by" src="https://academy.hsoub.com/uploads/monthly_2016_05/01_dependent_dropdown.thumb.png.61115b85f20eda7680fa9af6b42afcfa.png"></a>
</p>

<p>
	نستخدم Laravel في الجانب الخلفيّ Backend لتولي التعامل مع الطّلبات والتخاطب مع قاعدة البيانات للحصول على التصنيفات والتّصنيفات الفرعيّة منها. يتولّى سكربت <a href="https://academy.hsoub.com/programming/javascript/jquery/" rel="">jQuery</a> العمل في الواجهة الأماميّة Frontend لتحديث محتويات القائمة الثانيّة عند تعديل محتوى الأولى.
</p>

<p>
	في ما يلي نظرة عامّة على الخطوات التي سنتّبعها:
</p>

<ul>
<li>
		إنشاء النماذج Models والتهجيرات Migrations.
	</li>
	<li>
		تهيئة معمل نماذج Model factory وبذر Seed جداول البيانات.
	</li>
	<li>
		إعداد المسارات Routes والمتحكّمات Controllers.
	</li>
	<li>
		إعداد العروض Views.
	</li>
</ul>
<p>
	الطريقة التي نريد تنفيذها هي كالتالي: عند الدخول إلى المسار <code>categories/</code> يتلقى ملف المسارات الطّلب ويحوّله إلى الدالّة <code>categories</code> في المتحكّم <code>HomeController</code>. تستقبل الداّلة الطلب وتطلب قائمة بالتّصنيفات من نموذج التّصنيف <code>Category</code>؛ ثم ترسل التّصنيفات إلى العرض <code>categories</code> الذي يعرضها في القائمة المنسدلة الأولى. نستخدم سكربت jQuery في العرض للإنصات لتغييرات القائمة المنسدلة العلويّة، وعند اختيّار أحد عناصرها يأخذ السكربت معرّف العنصر المحدَّد ثم يرسل به طلب Ajax إلى المسار <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/category-dropdown/</code> الذي يجيب بلائحة التصنيفات الفرعيّة للتّصنيف المحدّد في القائمة الأولى. يستقبل السكربت اللائحة ويعرضها في القائمة الثانية.
</p>

<p>
	تمكنك مراجعة المقالات التاليّة لتفصيلات أكثرعن <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%86%D9%85%D9%88%D8%B0%D8%AC%D8%A7-model-%D9%81%D9%8A-laravel-r297/" rel="">إنشاء النماذج</a>، <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D8%B9%D9%85%D9%84-%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-model-factory-%D9%81%D9%8A-laravel-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-r298/" rel="">استخدام معمل النماذج</a> و <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">العروض</a>.
</p>

<p>
	نبدأ بتثبيت Laravel بالأمر التالي:<br>
	 
</p>

<pre class="ipsCode" id="ips_uid_247_7">
composer create-project --prefer-dist laravel/laravel laradropdown "5.3.*"</pre>

<p>
	انتظر اكتمال التثبيت ثم انتقل لمجلد المشروع <code>laradropdown</code> لمتابعة بقيّة الخطوات. سنفترض في ما يلي أن لاتصال بقاعدة البيانات مضبوط.
</p>

<h2 id="إنشاء-النماذج-والتهجيرات">
	إنشاء النماذج والتهجيرات
</h2>

<p>
	نبدأ بإنشاء نموذجيْن <code>Category</code> و <code>SubCategory</code>. الأوّل للتصنيفات والثاني للتصنيفات الفرعيّة. ننفّذ ما يلي في مجلّد المشروع:
</p>

<pre class="ipsCode" id="ips_uid_9836_7">
php artisan make:model Category -m
php artisan make:model SubCategory -m</pre>

<p>
	استخدمنا خيار <code>m-</code> لإنشاء التهجيرات مع إنشاء النماذج.
</p>

<p>
	نفتح ملفّ التهجير الخاصّ بالتصنيف ونعدّله:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_7">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">)-&gt;</span><span class="pln">unique</span><span class="pun">();</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</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"> down</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يحوي الملفّ كما هو ظاهر أربعة حقول: معرّفا، اسما للتّصنيف وحقليْ الأختام الزمنية.
</p>

<p>
	ننتقل لملفّ التهجير الخاصّ بالتصنيف الفرعي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_9">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'sub_categories'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">)-&gt;</span><span class="pln">unique</span><span class="pun">();</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">integer</span><span class="pun">(</span><span class="str">'category_id'</span><span class="pun">)-&gt;</span><span class="kwd">unsigned</span><span class="pun">();</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
  </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'sub_categories'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">foreign</span><span class="pun">(</span><span class="str">'category_id'</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="pln">references</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="pln">on</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">)</span><span class="pln">
          </span><span class="pun">-&gt;</span><span class="pln">onDelete</span><span class="pun">(</span><span class="str">'cascade'</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"> down</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'sub_categories'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $table</span><span class="pun">-&gt;</span><span class="pln">dropForeign</span><span class="pun">(</span><span class="str">'sub_categories_category_id_foreign'</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">});</span><span class="pln">
  </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'sub_categories'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يختلف ملفّ التهجير هذا قليلا عن الملفّ السّابق؛ إذ يحوي إلى جانب حقول المعرّف، الاسم والأختام الزمنيّة معرفَ التصنيف الذي يتفرّع منه. هذا المعرف هو مفتاح خارجي Foreign key يحيل إلى جدول التّصنيفات. نعرّف الحقول أولا ثم نحدّد الحقل <code>category_id</code> على أنه مفتاح خارجي. ينبغي أن يكون الحقل مطابقا تماما من حيث النوع للحقل الذي يحيل إليه. في الدالة <code>down</code> نبدأ بحذف القيد من على الحقل حتى يمكننا حذف الجدول.
</p>

<p>
	أنهينا إعداد التهجيرات. ننتقل لإعداد النماذج.
</p>

<p>
	نغيّر ملف النموذج <code>Category</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_11">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Category</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'id'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'name'</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"> sub_categories</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">hasMany</span><span class="pun">(</span><span class="str">'SubCategory'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نحدّد أولا الحقول التي يمكن إسنادها (خاصيّة <code>fillable</code>) ثم نضيف الدالة <code>sub_categories</code> التي تعرّف العلاقة بين التّصنيف <code>Category</code> والتّصنيف الفرعي <code>SubCategory</code>. هذه العلاقة هي من النوع <code>hasMany</code> بمعنى أنه توجد بالتّصنيف تصنيفات فرعية تابعة له.
</p>

<p>
	يفيدنا تعريف العلاقات بين النماذج في الاستعلامات ويجعلها أسهل بكثير كما سنرى.
</p>

<p>
	نفس الشيء تقريبا بالنسبة للنموذج <code>SubCategory</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_9">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">SubCategory</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'id'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'category_id'</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"> category</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">belongsTo</span><span class="pun">(</span><span class="str">'Category'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نعرّف في النموذج <code>SubCategory</code> العلاقة العكسيّة لتلك المعرّفة في النموذج <code>Category</code>؛ وهي <code>belongsTo</code> التي تعني أن هذا الصّنف يتبع للصّنف <code>Category</code>.
</p>

<p>
	النماذج والتهجيرات جاهزة؛ يمكننا الآن تنفيذ التهجيرات: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_17">
<span class="pln">php artisan migrate</span></pre>

<h2 id="تهيئة-معامل-النماذج-وبذر-جداول-البيانات">
	تهيئة معامل النماذج وبذر جداول البيانات
</h2>

<p>
	سنستفيد من الخبرى التي تحصّلنا عليها في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D8%B9%D9%85%D9%84-%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-model-factory-%D9%81%D9%8A-laravel-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-r298/" rel=""> استخدام معمل النماذج (Model factory) في Laravel لتوليد بيانات الاختبار</a> لتهيئة معملَيْ نماذج نستخدمهما لبذر البيانات في الجدوليْن <code>categories</code> و <code>sub_categories</code>.
</p>

<p>
	ننشئ ملفيْن في المجلّد <code>/database/factories</code>؛ واحدا باسم <code>CategoryFactory.php</code> والآخر <code>SubCategoryFactory.php</code>. ثم نضيف المحتوى التالي إلى <code>CategoryFactory.php</code> :
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_19">
<span class="pun">&lt;?</span><span class="pln">php
    $factory</span><span class="pun">-&gt;</span><span class="pln">define</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Faker</span><span class="pln">\Generator $faker</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">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">unique</span><span class="pun">()-&gt;</span><span class="pln">word
        </span><span class="pun">];</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	نفس المبدأ المستخدَم في الدرس المُشار إليه أعلاه. نعرّف النموذج الذي نريد توليد بيانات له ثم نستخدم مكتبة <code>Faker</code> لملْء الحقل المحدَّد (<code>name</code>). طلبنا توليد كلمات فريدة Unique حتى نوافق الشّرط المعرَّف في تهجير قاعدة البيانات الخاصّ بالجدول <code>categories</code>.
</p>

<p>
	الأمر مختلف قليلا مع الملف <code>SubCategoryFactory.php</code> الذي نعدّله كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_13">
<span class="pun">&lt;?</span><span class="pln">php

    $factory</span><span class="pun">-&gt;</span><span class="pln">define</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\SubCategory</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Faker</span><span class="pln">\Generator $faker</span><span class="pun">){</span><span class="pln">
        $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">()-&gt;</span><span class="pln">pluck</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">)-&gt;</span><span class="pln">all</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">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">unique</span><span class="pun">()-&gt;</span><span class="pln">word</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'category_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">  $faker</span><span class="pun">-&gt;</span><span class="pln">randomElement</span><span class="pun">(</span><span class="pln">$categories</span><span class="pun">),</span><span class="pln">
        </span><span class="pun">];</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	بما أن الحقل <code>category_id</code> مفتاح خارجي على معرّف التّصنيف فلن تقبل قاعدة البيانات إضافة معرّف لتصنيف غير موجود في جدول التصنيفات. لتجاوز هذا القيد نبدأ بطلب معرّفات التصنيفات: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_15">
<span class="pln">$categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">()-&gt;</span><span class="pln">pluck</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">)-&gt;</span><span class="pln">all</span><span class="pun">();</span></pre>

<p>
	ثم عند توليد بيانات للحقل <code>category_id</code> نطلب منه أن يختار واحدا عشوائيا من المعرّفات التي تحصّلنا عليها سابقا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_25">
<span class="str">'category_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">  $faker</span><span class="pun">-&gt;</span><span class="pln">randomElement</span><span class="pun">(</span><span class="pln">$categories</span><span class="pun">),</span></pre>

<p>
	هذا كلّ شيء بالنسبة لمعمل النماذج. ننتقل للبذر. ننشئ صنفا سنستخدمه لبذر النموذجيْن <code>Category</code> و <code>SubCategory</code>:
</p>

<pre class="ipsCode" id="ips_uid_9836_27">
php artisan make:seeder SubCategoryTableSeeder
</pre>

<p>
	نفتح الملف ونعدّله كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_29">
<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">
  </span><span class="typ">App</span><span class="pln">\SubCategory</span><span class="pun">::</span><span class="pln">truncate</span><span class="pun">();</span><span class="pln">
  factory</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)-&gt;</span><span class="pln">create</span><span class="pun">();</span><span class="pln">
  factory</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\SubCategory</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">)-&gt;</span><span class="pln">create</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نطلُب في الملفّ توليد 10 تصنيفات و50 تصنيفا فرعيا.
</p>

<p>
	نعدّل ملف البذر <code>DatabaseSeeder</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_31">
<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">
    </span><span class="typ">Model</span><span class="pun">::</span><span class="pln">unguard</span><span class="pun">();</span><span class="pln">
    $this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">SubCategoryTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Model</span><span class="pun">::</span><span class="pln">reguard</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا ننسى استدعاء النموذج <code>Model</code> في الملف <code>DatabaseSeeder</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_17">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">
</span></pre>

<p>
	نستدعي ملفّ البذر <code>SubCategoryTableSeeder</code> الذي يستخدم معمليْ النماذج لتوليد البيانات. يمكننا الآن تنفيذ البذر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_33">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<h2 id="إعداد-المسارات-والمتحكمات">
	إعداد المسارات والمتحكمات
</h2>

<p>
	نريد أن نصل إلى صفحة القائمتين المنسدلتين عبر الرابط <code>categories/</code>؛ لذا سنعرّف مسارا له في ملف مسارات الوِب  <code>routes/web.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_35">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/categories'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@categories'</span><span class="pun">);</span></pre>

<p>
	لا خصوصيةَ هنا؛ المسار والمتحكّم والدالة اللذان يعالجان الطّلب.
</p>

<p>
	إن لم يكن المتحكّم <code>HomeController</code> معرّفا لديك فاستخدم الأمر <code>php artisan make:controller HomeController</code> وأضف إليه دالة باسم <code>categories</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_18">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> categories</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">orderBy</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'asc'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'layouts.categories'</span><span class="pun">,</span><span class="pln"> compact</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استيراد النموذج <code>Category</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_20">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">;</span><span class="pln">
</span></pre>

<p>
	نستخدم النموذج <code>Category</code> في الدالة للحصول على لائحة التصنيفات مرتبة تصاعديا حسب الاسم؛ ثم نرسل النتيجة إلى العرض <code>categories</code> الموجود في المجلّد <code>layouts </code>ضمن مجلّد العروض <code>resources/views</code>. هذا العرض غير موجود لحدّ الساعة لذا يجب أن ننشئه. لكن قبل ذلك يجب أن ننهي إعداد المتحكّمات.
</p>

<p>
	سنضع في العرض سكربت jQuery -كما أشرنا سابقا- للحصول على لائحة بالتصنيفات الفرعيّة للتّصنيف المحدّد في القائمة المنسدلة العلوية. يرسل السكربت طلب Ajax إلى المسار <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/category-dropdown/</code>. ننشئ هذا المسار في ملفّ المسارات الخاصّ بواجهة التطبيقات البرمجيّة <code>routes/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_19">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/category-dropdown'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'ApiController@categoryDropDownData'</span><span class="pun">);</span></pre>

<p>
	يمكن أن نستخدم نفس المتحكّم السابق (<code>HomeController</code>) ونعرّف دالة فيه كما يمكن أن ننشئ متحكّما جديدا. اخترنا الحلّ الأخير حتى نفصل بين التحكّم في المسارات العادية والمسارات المعدّة لتكون واجهة برمجية Application programming interface, <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>.
</p>

<p>
	نستخدم الأمر التالي لإنشاء متحكّم باسم <code>ApiController</code>: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_41">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">ApiController</span></pre>

<p>
	ثم نعدّل عليه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_43">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> categoryDropDownData</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    $category_id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Input</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'category_id'</span><span class="pun">);</span><span class="pln">
    $subcategories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$category_id</span><span class="pun">)-&gt;</span><span class="pln">sub_categories</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Response</span><span class="pun">::</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$subcategories</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يتلقى المسار <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/category-dropdown/</code> معرّف التّصنيف المحدّد في القائمة ضمن متغيّر <code>category_id</code>. نستقبل المتغيّر المُرسَل من المستخدم بالدّالة <code>get</code> من الصّنف <code>Input</code>.
</p>

<p>
	بما أننا عرّفنا علاقات بين التصنيف والتصنيف الفرعي في النموذجين المقابليْن فيمكننا بسهولة العثور على التّصنيفات الفرعيّة لتصنيف؛ كلّ ما علينا فعله هو استخدام الدّالة <code>sub_categories</code> التي عرّفناها في الصّنف <code>Category</code>.
</p>

<p>
	تعثُر التعليمة التالية على جميع التّصنيفات الفرعيّة للتّصنيف ذي المعرّف <code>category_id.</code> 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_11">
<span class="pln">$subcategories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$category_id</span><span class="pun">)-&gt;</span><span class="pln">sub_categories</span><span class="pun">;</span></pre>

<p>
	في الأخير نرمّز التصنيفات الفرعيّة بصيغة Json ثم نرسلها في الإجابة.
</p>

<p>
	لا تنس استدعاء الأصناف التي استخدمناها وإضافتها إلى بداية الملف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_14">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Response</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Input</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">;</span></pre>

<p>
	المحصّلة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7558_16">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Response</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Input</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Category</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ApiController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</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"> categoryDropDownData</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

      $category_id </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Input</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'category_id'</span><span class="pun">);</span><span class="pln">
      $subcategories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$category_id</span><span class="pun">)-&gt;</span><span class="pln">sub_categories</span><span class="pun">;</span><span class="pln">

      </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Response</span><span class="pun">::</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$subcategories</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="إعداد-العروض">
	إعداد العروض
</h2>

<p>
	أكملنا الإعدادات من جهة النهاية الخلفيّة؛ تبقى فقط إعداد العرض لاستقبال البيانات وتقديمها للزائر.
</p>

<p>
	ننشئ لهذا الغرض عرضا باسم <code>categories.blade.php</code> في المجلّد <code>layouts</code>. يمدّد هذا العرض عرضا رئيسا Master view اسمُه <code>app.blade.php</code>، يوجد في نفس المجلّد. ينفّذ <code>categories.blade.php</code> مقطعًا باسم <code>content </code>معرّفًا في العرض الرّئيس ويوجد به محتوى الصفحة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_247_23">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.app'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"container"</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"row"</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-md-10 col-md-offset-1"</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"panel panel-default"</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"panel-heading"</span><span class="pun">&gt;</span><span class="typ">Dashboard</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"panel-body"</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-group"</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="str">&lt;label&gt;</span><span class="typ">Category</span><span class="pun">:&lt;/</span><span class="pln">label</span><span class="pun">&gt;&lt;</span><span class="pln">br</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;</span><span class="kwd">select</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-control input-lg"</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"category_id"</span><span class="pln"> id</span><span class="pun">=</span><span class="str">"category_id"</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;</span><span class="pln">option value</span><span class="pun">=</span><span class="str">""</span><span class="pun">&gt;</span><span class="typ">Select</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">&lt;/</span><span class="pln">option</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="lit">@foreach</span><span class="pun">(</span><span class="pln">$categories </span><span class="kwd">as</span><span class="pln"> $category</span><span class="pun">)</span><span class="pln">
                        </span><span class="pun">&lt;</span><span class="pln">option value</span><span class="pun">=</span><span class="str">"{{ $category-&gt;id }}"</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{{</span><span class="pln">$category</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">}}&lt;/</span><span class="pln">option</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="lit">@endforeach</span><span class="pln">
                    </span><span class="pun">&lt;/</span><span class="kwd">select</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-group"</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="str">&lt;label&gt;</span><span class="typ">Subcategory</span><span class="pun">:&lt;/</span><span class="pln">label</span><span class="pun">&gt;&lt;</span><span class="pln">br</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;</span><span class="kwd">select</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-control input-lg"</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"subcategory_id"</span><span class="pln"> id</span><span class="pun">=</span><span class="str">"subcategory_id"</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;</span><span class="pln">option value</span><span class="pun">=</span><span class="str">""</span><span class="pun">&gt;</span><span class="typ">First</span><span class="pln"> </span><span class="typ">Select</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">&lt;/</span><span class="pln">option</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;/</span><span class="kwd">select</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="str">&lt;script&gt;</span><span class="pln">
$</span><span class="pun">(</span><span class="str">'#category_id'</span><span class="pun">).</span><span class="pln">on</span><span class="pun">(</span><span class="str">'change'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">e</span><span class="pun">){</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> cat_id </span><span class="pun">=</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">value</span><span class="pun">;</span><span class="pln">
</span><span class="com">//ajax</span><span class="pln">
$</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/category-dropdown?category_id='</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> cat_id</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">data</span><span class="pun">){</span><span class="pln">
    </span><span class="com">//success data</span><span class="pln">
    $</span><span class="pun">(</span><span class="str">'#subcategory_id'</span><span class="pun">).</span><span class="pln">empty</span><span class="pun">();</span><span class="pln">
    $</span><span class="pun">(</span><span class="str">'#subcategory_id'</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="str">'&lt;option value=""&gt; Please choose one&lt;/option&gt;'</span><span class="pun">);</span><span class="pln">
    $</span><span class="pun">.</span><span class="pln">each</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">index</span><span class="pun">,</span><span class="pln"> subcatObj</span><span class="pun">){</span><span class="pln">
    $</span><span class="pun">(</span><span class="str">'#subcategory_id'</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="str">'&lt;option value="'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> subcatObj</span><span class="pun">.</span><span class="pln">id</span><span class="pun">+</span><span class="str">'"&gt;'</span><span class="pln">
    </span><span class="pun">+</span><span class="pln"> subcatObj</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">'&lt;/option&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><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	يستقبل المقطع <code>content</code> التصنيفات في المتغيّر <code>categories</code> ثم يستخدم دالة <code>foreach</code> التكراريّة لعرضها في القائمة المنسدلة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9836_53">
<span class="pln">        @foreach($categories as $category)
            </span><span class="tag">&lt;option</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"{{ $category-&gt;</span><span class="pln">id }}"&gt; {{$category-&gt;name}}</span><span class="tag">&lt;/option&gt;</span><span class="pln">
        @endforeach</span></pre>

<p>
	نضيف في المقطع <code>script</code> سكربت jQuery الذي سيتولى مزامنة محتوى القائمتيْن.
</p>

<p>
	يأخذ الجزء الأول من السكربت العنصر <code>category_id</code> الذي يمثّل القائمة الأولى ويستخدم الحدث <code>on change</code> لمراقبة التغيّرات عليه. نحتفظ بمعرّف التصنيف في المتغيّر <code>cat_id</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_55">
<span class="pln">$</span><span class="pun">(</span><span class="str">'#category_id'</span><span class="pun">).</span><span class="pln">on</span><span class="pun">(</span><span class="str">'change'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">e</span><span class="pun">){</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> cat_id </span><span class="pun">=</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">value</span><span class="pun">;</span></pre>

<p>
	ثم يأتي دور نداء Ajax الذي يرسل المتغيّر <code>cat_id </code>إلى المسار <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/category-dropdown/</code> ضمن المعطى <code>category_id</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_57">
<span class="pln">$</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/category-dropdown?category_id='</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> cat_id</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span></pre>

<p>
	يخزّن النداء النتيجة في المتغيّر <code>data</code>. عند تلقّي الطلب ننفّذ ثلاثة أمور:
</p>

<ul>
<li>
		<p>
			حذف محتوى القائمة المنسدلة الثّانية لمحو المحتوى الموجود فيها (المحتوى الأصلي أو المحتوى المرتبط بعنصُر محدد سابقا في القائمة الأولى): 
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_59">
<span class="pln">$</span><span class="pun">(</span><span class="str">'#subcategory_id'</span><span class="pun">).</span><span class="pln">empty</span><span class="pun">();</span></pre>

		<p>
			ثم نضيف تعليمة جديدة تطلب من الزائر الاختيّار:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_61">
<span class="pln">$</span><span class="pun">(</span><span class="str">'#subcategory_id'</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="str">' Please choose one'</span><span class="pun">);</span></pre>

		<p>
			ثم في الأخير نستخدم دالة <code>each</code> التكرارية في jQuery للمرور على البيانات (التصنيفات الفرعيّة) الواحدة تلو الأخرى وإضافتها إلى القائمة المنسدلة الثانيّة:
		</p>

		<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9836_63">
<span class="pln">$</span><span class="pun">.</span><span class="pln">each</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">index</span><span class="pun">,</span><span class="pln"> subcatObj</span><span class="pun">){</span><span class="pln">
    $</span><span class="pun">(</span><span class="str">'#subcategory_id'</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="str">''</span><span class="pln">
    </span><span class="pun">+</span><span class="pln"> subcatObj</span><span class="pun">.</span><span class="pln">subcategory_name </span><span class="pun">+</span><span class="pln"> </span><span class="str">'&lt;/option'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<p>
	بالنسبة للعرض الرّئيس <code>app.blade.php</code> فقد استخدمنا <a href="http://academy.hsoub.com/applications/core/interface/file/attachment.php?id=20217" data-fileid="20217" rel="">هذا الملف</a>.
</p>

<p>
	لم يتبق سوى زيارة الرابط <code>categories/</code> لمعاينة النتيجة.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/12/07/dependent-dropdown-list-with-jquery-in-laravel-5-1/" rel="external nofollow">Dependent Dropdown List with jquery in Laravel 5.1</a> لصاحبه  Bill Keck.
</p>
]]></description><guid isPermaLink="false">323</guid><pubDate>Sun, 19 Jun 2016 08:17:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; inject@ &#x644;&#x62D;&#x642;&#x646; &#x645;&#x632;&#x648;&#x62F; &#x62E;&#x62F;&#x645;&#x629; Service provider &#x641;&#x64A; &#x642;&#x627;&#x644;&#x628; Blade &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-inject-%D9%84%D8%AD%D9%82%D9%86-%D9%85%D8%B2%D9%88%D8%AF-%D8%AE%D8%AF%D9%85%D8%A9-service-provider-%D9%81%D9%8A-%D9%82%D8%A7%D9%84%D8%A8-blade-%D9%81%D9%8A-laravel-r331/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/laravel-inject-service-provider-blade.png.3a6ffe7d923a450f2c107669d692301a.png" /></p>

<p>
	رأينا في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%85%D8%B2%D9%88%D8%AF-%D8%AE%D8%AF%D9%85%D8%A9-service-provider-%D9%81%D9%8A-laravel-r326/" rel="" title="أكمل قراءة كيف تنشئ مزود خدمة Service provider في Laravel">كيف تنشئ مزود خدمة Service provider في Laravel</a> طريقة عمل مزوّدات الخدمة والآليّة التي تتيح بها مرونة أكبر في التعامل مع الأصناف في Laravel.
</p>

<p>
	سنرى في هذا الدّرس كيفيّة الاستفادة من تعليمة <code>inject@ </code>لإعادة استخدام مزوّد خدمة في قالب Blade.
</p>

<p style="text-align: center;">
	<img alt="laravel-inject-service-provider-blade.png" class="ipsImage ipsImage_thumbnailed" data-fileid="17707" data-unique="dal9gcqef" src="https://academy.hsoub.com/uploads/monthly_2016_06/laravel-inject-service-provider-blade.png.988d18fe9e7f7fd0626324d8db939132.png"></p>

<p>
	<span style="line-height: 2em;">استخدمنا في الدرس السابق مزوّد خدمة داخل متحكّم على النحو التالي:</span>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_7">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="typ">RocketShipContract</span><span class="pln"> $rocketship</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
        $boom </span><span class="pun">=</span><span class="pln"> $rocketship</span><span class="pun">-&gt;</span><span class="pln">blastOff</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'demo.index'</span><span class="pun">,</span><span class="pln"> compact</span><span class="pun">(</span><span class="str">'boom'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سنفترض أن لدينا ثلاثة عروض <code>view1</code> و<code>view2</code> إضافة للعرض <code>index</code> (كلّها في نفس المجلّد):
</p>

<p>
	العرض <code>view1</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_9">
<span class="com">&lt;!--  تعليمات خاصّة بالعرض view1 --&gt;</span><span class="pln">
@include('demo.index')
</span><span class="com">&lt;!--  تعليمات خاصّة بالعرض view1 --&gt;</span></pre>

<p>
	العرض <code>view2</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_11">
<span class="com">&lt;!--  تعليمات خاصّة بالعرض view2 --&gt;</span><span class="pln">
@include('demo.index')
</span><span class="com">&lt;!--  تعليمات خاصّة بالعرض view2 --&gt;</span></pre>

<p>
	العرض <code>index</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_15">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.master'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> $boom </span><span class="pun">}}</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	نلاحظ أن العرض <code>index</code> يُضمَّن في العرضيْن <code>view1</code> و<code>view2</code>. سنفترض أيضا أن لدينا الدالتين التاليتين في المتحكّم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_17">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> function1</span><span class="pun">(</span><span class="typ">RocketShipContract</span><span class="pln"> $rocketship</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
        $boom </span><span class="pun">=</span><span class="pln"> $rocketship</span><span class="pun">-&gt;</span><span class="pln">blastOff</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'demo.view1'</span><span class="pun">,</span><span class="pln"> compact</span><span class="pun">(</span><span class="str">'boom'</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"> function2</span><span class="pun">(</span><span class="typ">RocketShipContract</span><span class="pln"> $rocketship</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
        $boom </span><span class="pun">=</span><span class="pln"> $rocketship</span><span class="pun">-&gt;</span><span class="pln">blastOff</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'demo.view2'</span><span class="pun">,</span><span class="pln"> compact</span><span class="pun">(</span><span class="str">'boom'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تعمل الطريقة أعلاه دون مشكل؛ ولكن ماذا لو أضفنا مسارا ثالثا يستدعي عرضا آخر يُضمِّن العرض <code>index</code>؟
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_19">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> function3</span><span class="pun">(</span><span class="typ">RocketShipContract</span><span class="pln"> $rocketship</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
        $boom </span><span class="pun">=</span><span class="pln"> $rocketship</span><span class="pun">-&gt;</span><span class="pln">blastOff</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'demo.view3'</span><span class="pun">,</span><span class="pln"> compact</span><span class="pun">(</span><span class="str">'boom'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن أن نلاحظ بوضوح وجود الكثير من التكرار لاستخدام الصّنف <code>RocketShipContract</code>.
</p>

<p>
	لتلافي هذا الوضع يعرّف Laravel حقن الخدمة Service injection.
</p>

<p>
	يقوم المبدأ على استخدام التعليمة <code>inject@</code> التي تتيح استدعاء صنف مّا مباشرة في العرض. بتطبيق هذا المبدأ في الحالة أعلاه نعدّل العرض <code>index</code> ليصبح كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_21">
<span class="lit">@inject</span><span class="pun">(</span><span class="str">'boom'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'App\Helpers\Contracts\RocketShipContract'</span><span class="pun">)</span><span class="pln">

</span><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.master'</span><span class="pun">)</span><span class="pln">

</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">

    </span><span class="pun">{{</span><span class="pln"> $boom</span><span class="pun">-&gt;</span><span class="pln">blastOff</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">

</span><span class="lit">@endsection</span></pre>

<p>
	تأخذ التعليمة <code>inject@</code> معطييْن؛ الأول (<code>boom</code> في المثال) اسم المتغيّر الذي سنحتفظ فيه بكائن من الصّنف الممرّر في المعطى الثاني (<code>RocketShipContract</code>). يمكننا بعد ذلك استخدام المتغيّر واستدعاء الدالة.
</p>

<p>
	بالعودة إلى دوال المتحكّم فيمكننا تغييرها كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5305_23">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> function1</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"> view</span><span class="pun">(</span><span class="str">'view1'</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"> function2</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"> view</span><span class="pun">(</span><span class="str">'view2'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نرى بوضوح أن الطريقة الأخيرة تتيح قابليّةً أكبر لإعادة الاستخدام.
</p>

<p>
	حقن الخدمة - كما رأينا - وسيلة مفيدة لإعادة استخدام وظائف من التطبيق وتقديمها في عروض، إلا أنه لا يُنصَح باستخدامها إلا عند الحاجة؛ ومن الضروريّ عدم المبالغة في استخدامها.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/06/12/how-to-use-inject-in-blade-in-laravel-5-1/" rel="external nofollow">How to Use @inject in Blade in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">331</guid><pubDate>Fri, 10 Jun 2016 14:01:40 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x646;&#x634;&#x626; &#x645;&#x632;&#x648;&#x62F; &#x62E;&#x62F;&#x645;&#x629; (Service provider) &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%85%D8%B2%D9%88%D8%AF-%D8%AE%D8%AF%D9%85%D8%A9-service-provider-%D9%81%D9%8A-laravel-r326/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_05/laravel-service-provider.png.e8ea9e4ac312c19bcffdac5199174ed4.png" /></p>

<p>
	تعتمد بنية Laravel كثيرا على مزوّدي الخدمة Service providers لتحميل الأصناف Classes إلى الذاكرة مع بدء عمل التطبيق أو عند الحاجة إليها. يستخدم Laravel حاويةَ خدمة Service container لإدارة الاعتمادات بين الأصناف: ماهي الأصناف التي يعتمد عليها الصّنف الجديد للعمل؟ كيف يمكنه الحصول على كائن من هذه الأصناف؟ أين يوجد الصّنف وهل سبق لإطار العمل تحميلُه إلى الذاكرة؟ تمكننا بإعداد مزوّد خدمة وتعريفه إضافةُ صنف إلى حاويّة الخدمة ممّا يسهّل بالتالي استخدامه؛ إذ سيتعرّف إطار العمل على ما يحتاجه هذا الصّنف (أي الاعتمادات) وينشئه إن لم يكن موجودا سلفا.
</p>

<p>
	سنشرح في هذا الدرس أساسيّات إنشاء مزود خدمة في Laravel.
</p>

<p style="text-align: center;">
	<img alt="laravel-service-provider.png" class="ipsImage ipsImage_thumbnailed" data-fileid="16766" data-unique="c5xd9nlfp" src="https://academy.hsoub.com/uploads/monthly_2016_05/laravel-service-provider.png.7426b4d25ccea4a9f77fbae9a8fb47f9.png"></p>

<p>
	نبدأ بإنشاء مسار سنستخدمه للتوضيح: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_7">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/demo'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'DemoController@index'</span><span class="pun">);</span></pre>

<p>
	ثم ننشئ المتحكّم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_9">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">DemoController</span></pre>

<p>
	ثم نعرّف الدالة <code>index</code> في المتحكّم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_11">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</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"> view</span><span class="pun">(</span><span class="str">'demo.index'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تطلب الدالة <code>index</code> تقديم العرض <code>demo.index</code>؛ لذا سننشئ مجلّدا باسم <code>demo</code> في مجلّد العروض وننشئ فيه عرضا باسم <code>index.blade.php</code>. نضيف المحتوى التالي للعرض <code>index</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_13">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.master'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;h1&gt;</span><span class="typ">Demo</span><span class="pln"> </span><span class="typ">Page</span><span class="pun">&lt;/</span><span class="pln">h1</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	يمدّد العرض <code>index</code> عرضا رئيسا باسم <code>master</code> ضمن مجلّد العروض <code>layouts</code>. أنشئ العرض الرئيس إن احتجت لذلك.
</p>

<p>
	لم ندخل في صميم الموضوع لحد السّاعة، فقط ضبطنا بعض الإعدادات البدائية. تظهر عند الدخول إلى الرابط <code>demo/</code> صفحة بها عنوان <code>Demo Page</code>.
</p>

<h3 id="إعداد-مزود-خدمة">
	إعداد مزود خدمة
</h3>

<p>
	سنشرح في الفقرات المواليّة كيفية إنشاء مزوّد خدمة. نبدأ بإنشاء مجلّد باسم <code>Helpers</code> في مجلّد <code>app</code> ثم ننشئ مجلّدا متفرعا عن <code>Helpers</code> باسم <code>Contracts</code>؛ بداخل الأخير ننشئ ملفّا باسم <code>RocketShipContract.php</code> نضيف إليه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_15">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\Contracts</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Interface</span><span class="pln"> </span><span class="typ">RocketShipContract</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"> blastOff</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ تعريف الصّنف أعلاه. عرّفنا <code>RocketShipContract</code> على أنه واجهة Interface. تعرّف <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-abstraction%C2%A0%D9%88%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-interfaces-%D9%88%D8%A7%D9%84%D8%B3%D9%85%D8%A7%D8%AA-traits-%D9%81%D9%8A-php-r317#%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-interfaces" rel="">الواجهات في PHP </a>(ولغات برمجيّة أخرى) "عقدا" يجب على الأصناف التي تطبّق الواجهة اتّباعه. يجب على الأصناف التي تنفّذ Implement الواجهة المعرَّفة أعلاه أن تحوي دالة عمومية <code>public</code> باسم <code>blastOff</code>.
</p>

<p>
	نأتي الآن بعد تعريف الواجهة إلى الصّنف الذي ينفّذها. تحوي الواجهة خطوطا عريضة يأتي الصّنف المنفّذ لتخصيصها. ننشئ صنفا باسم <code>RocketShip.php</code> في مجلّد <code>Helpers</code> ونضيف إليه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_17">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> app\Helpers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\Contracts\RocketShipContract</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">RocketShip</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">RocketShipContract</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"> blastOff</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">'Houston, we have ignition'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	يمكن أن تعالج في هذا الصّنف الكثير من الأمور، إلا أننا لا نودّ التعقيد. كل ما تفعله هذه الدالة هو إرجاع العبارة <code>Houston, we have ignition</code>.
</p>

<p>
	عرفنا الواجهة وكيفيةً لتنفيذها. يأتي الآن دور مزوّد الخدمة الذي سننشئه بالأمر التالي: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_19">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">provider </span><span class="typ">RocketShipServiceProvider</span></pre>

<p>
	ينشئ الأمر ملفّا باسم <code>RocketShipServiceProvider.php</code> في المجلّد. تجد عند فتح الملف ما يلي (بعد نزع التعليقات):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_21">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Providers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\ServiceProvider</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">RocketShipServiceProvider</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">ServiceProvider</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"> boot</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"> </span><span class="kwd">register</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_2571_23">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Providers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\ServiceProvider</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\RocketShip</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">RocketShipServiceProvider</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">ServiceProvider</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $defer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</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"> boot</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"> </span><span class="kwd">register</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">app</span><span class="pun">-&gt;</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'App\Helpers\Contracts\RocketShipContract'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">

            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RocketShip</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"> provides</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="str">'App\Helpers\Contracts\RocketShipContract'</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	أولى التعديلات هي استدعاء الصّنف <code>RocketShip</code>: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_25">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\RocketShip</span><span class="pun">;</span></pre>

<p>
	ثم إضافة الخاصّية التاليّة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_27">
<span class="kwd">protected</span><span class="pln"> $defer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span></pre>

<p>
	يعني تمكين الخاصيّة <code>defer$</code> أننا نطلُب ألا يُحمَّل الصّنف إلا عند الضرورة؛ مما يسهِم في الرفع من أداء التطبيق.
</p>

<p>
	ثم يأتي دور الدالة <code>register</code> التي تربط بين الواجهة والصّنف الذي ينفّذها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_29">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">register</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">app</span><span class="pun">-&gt;</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'App\Helpers\Contracts\RocketShipContract'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RocketShip</span><span class="pun">();</span><span class="pln">

    </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يتيح هذا الربط إمكانية استخدام الواجهة في أي مكان تريده وسيستخدم مزوّد الخدمة الصنف الذي تربطه بها في دالة <code>register</code> تلقائيا. يزيد هذا الإعداد من مرونة التطبيق؛ فكل ما عليك فعله لتغيير سلوك الواجهة هو تعديل الصّنف المربوط بها.
</p>

<p>
	التعديل الأخير هو إضافة الدالة <code>provides</code> التي تُرجع الواجهة. يجب تعريف هذه الدالة عند تمكين الخاصيّة <code>defer</code>.
</p>

<p>
	الخطوة الأخيرة من إعداد مزوّد الخدمة هي إضافته إلى ملف إعداد التطبيق <code>config\app.php</code> ضمن مصفوفة <code>providers</code> (أدرجنا بعضا من محتويات الملف في الشفرة أدناه، مزوّد الخدمة الخاص بنا هو الأخير):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_31">
<span class="pln">    </span><span class="com">/*
     * Application Service Providers...
     */</span><span class="pln">

    </span><span class="typ">App</span><span class="pln">\Providers\AppServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">App</span><span class="pln">\Providers\EventServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">App</span><span class="pln">\Providers\RouteServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">App</span><span class="pln">\Providers\RocketShipServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span></pre>

<h3 id="استخدام-مزود-الخدمة">
	استخدام مزود الخدمة
</h3>

<p>
	نعود الآن للمتحكّم <code>DemoController</code> ونعدّل الدالة <code>index</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_33">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="typ">RocketShipContract</span><span class="pln"> $rocketship</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
        $boom </span><span class="pun">=</span><span class="pln"> $rocketship</span><span class="pun">-&gt;</span><span class="pln">blastOff</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'demo.index'</span><span class="pun">,</span><span class="pln"> compact</span><span class="pun">(</span><span class="str">'boom'</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_2571_35">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\Contracts\RocketShipContract</span><span class="pun">;</span></pre>

<p>
	نمرّر للدّالة <code>index</code> كائنا من الصنف <code>RocketShipContract</code> (أي الواجهة). سيعرف Laravel تلقائيا أننا نريد الصّنف <code>RocketShip</code> الذي ينفّذ الواجهة. يعود السبب في ذلك إلى الربط الموجود في مزوّد الخدمة. نمرّر النتيجة المتحصّل عليها من استدعاء <code>blastOff</code> إلى العرض لتقديمه.
</p>

<p>
	نعدّل العرض لاستخدام المتغيّر الذي ممرناه إليه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_37">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.master'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{{</span><span class="pln"> $boom </span><span class="pun">}}</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	تظهر العبارة التاليّة في المتصفّح عند زيارة الرابط <code>demo/</code>: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_39">
<span class="typ">Houston</span><span class="pun">,</span><span class="pln"> we have ignition </span></pre>

<p>
	سننشئ لتوضيح المرونة التي تتيحها مزودات الخدمة صنفا آخر ينفّذ الواجهة <code>RocketShipContract</code>. سنسمّي هذا الصنف الجديد <code>RocketLauncher</code> ونضعه في نفس المجلد الذي يوجد به صنف التنفيذ السابق (<code>Helpers</code>):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_41">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">namespace</span><span class="pln"> app\Helpers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\Contracts\RocketShipContract</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">RocketLauncher</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">RocketShipContract</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"> blastOff</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">'Houston, we have launched!'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	لم نغيّر الكثير بالمقارنة مع الصنف <code>RocketShip</code> السّابق؛ فقط العبارة.
</p>

<p>
	نعود إلى مزوّد الخدمة ونغيّر ربط الواجهة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2571_44">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">register</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">app</span><span class="pun">-&gt;</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'App\Helpers\Contracts\RocketShipContract'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RocketLauncher</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_2571_46">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Helpers\RocketLauncher</span><span class="pun">;</span></pre>

<p>
	ستلاحظ الآن تغير العبارة الظاهرة في المتصفّح عند زيارة الرابط <code>demo/</code>.
</p>

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

<p>
	يوجد أمران ينبغي الانتباه إليهما عند التعامل مع مزوّدات الخدمة في Laravel:
</p>

<ul>
<li>
		اجعل إضافة مزوّد الخدمة إلى ملف الإعداد <code>config/app.php</code> هي آخر الخطوات؛ بعد تعريف الواجهة ومزوّد الخدمة. إضافة صنف غير موجود إلى ملف الإعداد تؤدي إلى التشويش على عمل <code>artisan</code>.
	</li>
	<li>
		من الأفضل حذف مزوّد الخدمة ثم إنشاء واحد جديد بأداة <code>artisan</code>؛ بدلا من إعادة تسميّته. قد تؤدي إعادة التسميّة إلى عدم تحميل مزوّد الخدمة فلا يتعرّف عليه التطبيق.
	</li>
</ul>
<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/06/11/how-to-create-a-service-provider-in-laravel-5-1/" rel="external nofollow">How to Create a Service Provider in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">326</guid><pubDate>Thu, 26 May 2016 09:22:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x62D;&#x62F;&#x627;&#x62B; (Events) &#x648;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645;&#x647;&#x627; &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%A3%D8%AD%D8%AF%D8%A7%D8%AB-events-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87%D8%A7-%D9%81%D9%8A-laravel-r305/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_05/laravel-events.png.02a0f925e4c815ab6ace8d006a066df8.png" /></p>

<p>
	الأحداث Events هي إجراءات يمكن لبرنامج التعرّف عليها ومن ثمّ التعامل معها. يمكن أن نأخذ مثالا على ذاك عملية تسجيل مستخدم في الموقع. عندما يكمل زائر ملء حقول الاستمارة الخاصّة بالتسجيل في موقع فإنه يكون قد فعّل حدثا يمكننا تسميّته "التسجيل في الموقع"؛ نستطيع بعد ذلك التعامل مع هذا الحدث لنقرّر ما التالي.
</p>

<p style="text-align: center;">
	<img alt="laravel-events.png" class="ipsImage ipsImage_thumbnailed" data-fileid="16700" data-unique="uwcvelttv" src="https://academy.hsoub.com/uploads/monthly_2016_05/laravel-events.png.b19683bb6a0709adabe89f2c36e50c63.png"></p>

<p>
	كانت الطريقة القديمة تقضي بكتابة شفرة برمجية مباشرةً في المتحكّم Controller للتعامل مع الحدث؛ إلا أن توسّع التطبيق وزيادة الحاجة للتعامل مع أحداث جديدة يجعل الحاجة أكبر لطريقة جديدة أنظف وأكثر قابلية للتمديد. يستجيب Laravel لهذه الحاجة بالصنف Event والأدوات المساعدة المتعلّقة به.
</p>

<p>
	لا تقتصر الأحداث على إرسال البريد؛ إلا أن هذا الأخير وسيلة سهلة لشرح المبدأ. سنرى في هذا الدرس الخطوات اللازمة لتعريف حدث واستخدامه.
</p>

<p>
	نفترض أن لدينا جدولا ببيانات الاتصال ببعض الأشخاص؛ ونريد أن نرسل لأحدهم بريدا في كل مرة يُعرَض فيها الرابط <code>contacthandler/id/</code> حيث <code>id</code> معرّف من نرسل له البريد.
</p>

<p>
	سنستخدم في هذا الجدول <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-morrisjs-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AE%D8%B7%D9%91%D8%B7%D8%A7%D8%AA-%D8%A8%D9%8A%D8%A7%D9%86%D9%8A%D8%A9-%D9%81%D9%8A-laravel-r304/" rel="">نفس المشروع الذي أنشأناه في الدرس السابق</a> ونزيد عليه بإنشاء نموذج Model وجدول بيانات لحفظ جهات الاتّصال.
</p>

<h2 id="تهيئة-المشروع">
	تهيئة المشروع
</h2>

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

<h3 id="إنشاء-النموذج-contact">
	إنشاء النموذج Contact
</h3>

<p>
	ننفذ الأمر التالي في مجلّد المشروع لإنشاء نموذج باسم <code>Contact</code> مع ملف التهجير الخاصّ به:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_7">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">model </span><span class="typ">Contact</span><span class="pln"> </span><span class="pun">-</span><span class="pln">m</span></pre>

<p>
	نعدّل ملف التهجيرعلى النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_9">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'contacts'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'email'</span><span class="pun">)-&gt;</span><span class="pln">unique</span><span class="pun">();</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'subject'</span><span class="pun">);</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="pln">text</span><span class="pun">(</span><span class="str">'body'</span><span class="pun">);</span><span class="pln">
        $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</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_2419_11">
<span class="pln">php artisan migrate</span></pre>

<h3 id="بذر-البيانات">
	بذر البيانات
</h3>

<p>
	سنحتاج لبيانات اتصّال للتجربة عليها. نستخدم معمل نماذج Model factory لبذر الجدول <code>contacts</code>. ننشئ ملفا باسم <code>ContactFactory.php</code> في المسار <code>/app/factories</code> ونضيف إليه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_13">
<span class="pun">&lt;?</span><span class="pln">php
    $factory</span><span class="pun">-&gt;</span><span class="pln">define</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\Contact</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Faker</span><span class="pln">\Generator $faker</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">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">unique</span><span class="pun">()-&gt;</span><span class="pln">safeEmail</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'subject'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">word</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'body'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">text

        </span><span class="pun">];</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يستدعي معمل النماذج مكتبة Faker لإدراج بيانات في جدول <code>contacts</code> عبر النموذج <code>Contact</code>.
</p>

<p>
	ثم ننشئ صنفا للبذر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_15">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">ContactTableSeeder</span></pre>

<p>
	نستورد النموذج <code>Contact</code> في صنف البذر <code>ContactTableSeeder</code> ونستخدم معمل النماذج لتوليد بيانات عشوائية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_17">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Contact</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ContactTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</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">
        </span><span class="typ">Contact</span><span class="pun">::</span><span class="pln">truncate</span><span class="pun">();</span><span class="pln">
        factory</span><span class="pun">(</span><span class="typ">Contact</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">)-&gt;</span><span class="pln">create</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نأتي الآن للخطوة الأخيرة قبل تنفيذ أمر البذر وهي تحرير الملف <code>DataBaseSeeder.php</code> ليستدعي الصّنف <code>ContactTableSeeder</code> في الدالة <code>run</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_19">
<span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">ContactTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span></pre>

<p>
	ثم ننفذ البذر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_21">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<h3 id="المسار-والمتحكم">
	المسار والمتحكم
</h3>

<p>
	نفتح ملف <code>routes.php</code> لإضافة مسار للرابط <code>contacthandler/id/</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_23">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/contacthandler/{id}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@contactHandler'</span><span class="pun">);</span></pre>

<p>
	يحيل ملف المسارات الطلب على الرابط إلى الدالة <code>contacthandler</code> في المتحكّم <code>HomeController</code>. نذهب للمتحكم ونضيف هذه الدالة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_25">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> contactHandler</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="pun">}</span></pre>

<p>
	نترك الدالة خاوية لحد الساعة.
</p>

<h2 id="التعامل-مع-الأحداث">
	التعامل مع الأحداث
</h2>

<p>
	جهزنا المشروع ويمكننا الآن الانتقال إلى الأحداث والتعامل معها. نذكّر بأننا نريد إرسال بريد لصاحب جهة الاتصال عند طلب رابط به معرّفه. مثلا نرسل بريدا إلى جهة الاتصال ذات المعرّف <code>6</code> عند زيارة يُعرَض فيها الرابط <code>contacthandler/6/</code>. نحصُل على البريد الإلكتروني الذي سنرسل إليه الرسالة من خلال النموذج <code>Contact</code>؛ إضافة لاسمه وموضوع الرسالة وفحواها. ولدنا هذه البيانات تلقائيا أثناء البذر السابق.
</p>

<h3 id="تعريف-الحدث">
	تعريف الحدث
</h3>

<p>
	يتلخّص الأمر في أننا سننفّذ إجراءً عند وقوع الحدث "زيارة رابط المعرّف الخاص بجهة الاتصال". سنسميّ الصنف الموافق للحدث بـ <code>ContactHandlerAction</code>. نستعين بأداة <code>artisan</code> لإنشاء الحدث على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_27">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="kwd">event</span><span class="pln"> </span><span class="typ">ContactHandlerAction</span></pre>

<p>
	ستجد أن الأداة أنشأت الملف <code>ContactHandlerAction.php</code> على المسار <code>app/Events</code> وأضافت إليه المحتوى التالي (بعد نزع التعليقات):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_29">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ContactHandlerAction</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Event</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">SerializesModels</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="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> broadcastOn</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">
    </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_2419_31">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ContactHandlerAction</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Event</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">SerializesModels</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> $contact</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">$contact</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">contact </span><span class="pun">=</span><span class="pln"> $contact</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"> broadcastOn</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">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أضفنا متغيّرا جديدا لحفظ بيانات الاتصال واستخدامها عند الحاجة.<br>
	نعود لدالّة <code>contactHandler</code> في المتحكّم <code>HomeController</code> ونعدّلها لتصبح كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_33">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> contactHandler</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $contact </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Contact</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">event</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ContactHandlerAction</span><span class="pun">(</span><span class="pln">$contact</span><span class="pun">));</span><span class="pln">

   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'mail.success_view'</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_2419_35">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Contact</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Events\ContactHandlerAction</span><span class="pun">;</span></pre>

<p>
	عند استدعاء الدالة <code>contactHandler</code> نأخذ المعطى <code>id</code> المُمرَّر في الرابط ونحيله إلى الدالة <code>find</code> في النموذج <code>Contact</code> من أجل العثور عليه في قاعدة البيانات.<br>
	في التعليمة التالية يبدأ عمل آلية إدارة الأحداث في Laravel: نستدعي الدالة المساعدة <code>event</code> ونمرّر لها كائنا من الحدث <code>ContactHandlerAction</code> الذي أنشأناه قبل قليل. نستخدم جهة الاتصال التي عثرنا عليها <code>contact$</code> من أجل بناء الحدث. يعني هذا أننا أطلقنا الحدث “زيارة رابط المعرّف الخاص بجهة الاتصال” وزوّدناه بجهة الاتصال المعنيّة. مالذي يترتّب عن إطلاق الحدث؟ هذا هو ما سنراه الآن.
</p>

<h3 id="التعامل-مع-الحدث">
	التعامل مع الحدث
</h3>

<p>
	توجد في Laravel ما تُعرَف بالمستمعات Listeners ومهمتها انتظار وقوع أحداث لتبدأ عملها. نعود لأداة <code>artisan</code> وننفّذ الأمر التالي: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_37">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">listener </span><span class="typ">EmailContactListener</span><span class="pln"> </span><span class="pun">--</span><span class="kwd">event</span><span class="pun">=</span><span class="str">"ContactHandlerAction"</span></pre>

<p>
	ينشئ الأمر صنفا باسم <code>EmailContactListener</code> للاستماع للأحداث <code>ContactHandlerAction</code>. يوجد الصّنف <code>EmailContactListener</code> في المجلّد <code>/app/Listeners</code> ومحتواه التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_39">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">EmailContactListener</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">
        </span><span class="com">//</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"> handle</span><span class="pun">(</span><span class="typ">ContactHandlerAction</span><span class="pln"> $event</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>handle</code> تنتظر معطى من نوع <code>ContactHandlerAction</code>. يشغّل المستمِع الدالة <code>handle</code> بعد تلقيه إخطارا بإطلاق الحدث <code>ContactHandlerAction</code>. سنعود بعد قليل للدالة <code>handle</code> بعد أن نعرّف الآلية التي سيُخطَر بها المستمِع بوقوع الحدث.
</p>

<h3 id="ربط-الحدث-بآلية-التعامل-معه">
	ربط الحدث بآلية التعامل معه
</h3>

<p>
	يوفّر Laravel مزوّد خدمة خاصًّا بالأحداث اسمه <code>EventServiceProvider</code> يوجد في المجلّد <code>/app/Providers</code>. إن فتحت الملف <code>EventServiceProvider.php</code> ستجد التالي (إن لم يسبق لأحد التعديل عليه):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_41">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">EventServiceProvider</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">ServiceProvider</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $listen </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'App\Events\ContactHandlerAction'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'App\Listeners\EmailContactListener'</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"> boot</span><span class="pun">(</span><span class="typ">DispatcherContract</span><span class="pln"> $events</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">boot</span><span class="pun">(</span><span class="pln">$events</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>listen$</code>. نعدّلها لتصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_43">
<span class="pln"> </span><span class="kwd">protected</span><span class="pln"> $listen </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'App\Events\ContactHandlerAction'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'App\Listeners\EmailContactListener'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">],</span><span class="pln">
</span><span class="pun">];</span></pre>

<p>
	يمكن تعريف أكثر من مستمِع لنفس الحدث (لاحظ أن قيمة <code>App\Events\ContactHandlerAction</code> في الخاصيّة هي مصفوفة Array).
</p>

<p>
	تمكننا الآن العودة إلى المنصِت بعد أن أعلمنا Laravel بالرابط بينه والحدث.
</p>

<h3 id="تنفيذ-آلية-التعامل-مع-الحدث">
	تنفيذ آلية التعامل مع الحدث
</h3>

<p>
	نعدّل الدالة <code>handle</code> لتصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_45">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> handle</span><span class="pun">(</span><span class="typ">ContactHandlerAction</span><span class="pln"> $event</span><span class="pun">)</span><span class="pln">
</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="str">'name'</span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> $event</span><span class="pun">-&gt;</span><span class="pln">contact</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'email'</span><span class="pln">     </span><span class="pun">=&gt;</span><span class="pln"> $event</span><span class="pun">-&gt;</span><span class="pln">contact</span><span class="pun">-&gt;</span><span class="pln">email</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'subject'</span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> $event</span><span class="pun">-&gt;</span><span class="pln">contact</span><span class="pun">-&gt;</span><span class="pln">subject</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'body'</span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> $event</span><span class="pun">-&gt;</span><span class="pln">contact</span><span class="pun">-&gt;</span><span class="pln">body
  </span><span class="pun">];</span><span class="pln">

  </span><span class="typ">Mail</span><span class="pun">::</span><span class="pln">send</span><span class="pun">(</span><span class="str">'mail.email_view'</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">$message</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">use</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">
    $message</span><span class="pun">-&gt;</span><span class="kwd">from</span><span class="pun">(</span><span class="str">'hsoub@academy.com'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Hsoub Academy'</span><span class="pun">);</span><span class="pln">
    $message</span><span class="pun">-&gt;</span><span class="pln">to</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">[</span><span class="str">'email'</span><span class="pun">])-&gt;</span><span class="pln">subject</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">[</span><span class="str">'subject'</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="typ">Mail</span><span class="pun">::</span><span class="pln">failures</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">EmailSendingException</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نعرّف مصفوفةً باسم <code>data$</code> تحوي اسم جهة الاتصال، بريدها الإلكتروني، موضوع الرسالة وفحواها. نعثُر على هذه البيانات من الكائن <code>contact</code> الذي مررناه للحدث <code>event</code> عند زيارة الرابط. نستخدم هذه البيانات لجدولة إرسال بريد عبر الدالة <code>Mail::send</code>. تأخذ الدالة <code>Mail::send</code> عرضا View تستخدمه لتنسيق الرسالة والبيانات التي أخذناها من جهة الاتصال. ثم نختبر أخطاء إرسال البريد الإلكتروني بالدالة <code>Mail::failures</code>؛ فإن وجدت أخطاء استخدمنا استثناءً Exception مخصّصًا لمعالجتها. يمكنك الحصول على هذا الاستثناء في <a data-fileid="14644" href="http://academy.hsoub.com/applications/core/interface/file/attachment.php?id=14644" rel="">الملف المرفق</a> أو <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D8%A7%D9%84%D9%85%D8%AE%D8%B5%D9%91%D9%8E%D8%B5%D8%A9-%D9%81%D9%8A-laravel-r299/#%D8%AA%D8%AE%D8%B5%D9%8A%D8%B5-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA" rel="">مراجعة الدرس الخاص بالاستثناءات</a>.
</p>

<p>
	نحن الآن جاهزون تقريبا لتجربة الأحداث والتعامل معها في Laravel. بقي لنا إنشاء بضعة عروض لحاجات تطبيقنا المختلفة: <code>mail.success_view</code> في المتحكّم، <code>mail.email_view</code> لتنسيق الرسالة، إضافة لعروض أخرى قد تحتاجها أثناء تخصيص الاستثناء. يمكنك الحصول عليها في الملف المرفق.
</p>

<p>
	بقيت لنا خطوة أخيرة قبل اختبار التطبيق: إعداد Laravel لإرسال البريد. يوفّر Laravel وسيلة لمحاكاة إرسال البريد يمكننا استخدامها للتجربة. ابحث في ملف متغيّرات النظام <code>env.</code> عن المعطى <code>MAIL_DRIVER</code> وعيّن قيمته بـ<code>log</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_47">
<span class="pln">MAIL_DRIVER</span><span class="pun">=</span><span class="pln">log</span></pre>

<p>
	نطلُب بهذه الطريقة من Laravel كتابة البريد في ملفّ السجل بدلا من إرساله. هذه الطريقة مفيدة أثناء الاختبار.
</p>

<p>
	افتح الرابط التالي في المتصفّح (ضع اسم المضيف المناسب بدلا من <code>laraveltips</code>):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2419_49">
<span class="pln">http</span><span class="pun">:</span><span class="com">//laraveltips.dev/contacthandler/45</span></pre>

<p>
	<strong>ملحوظة:</strong> لا يتعدّى عدد جهات الاتصال التي أضفناها الخمسين؛ سيؤدي البحث عن جهة اتصال بمعرّف أكبر من <code>50</code> إلى خطأ يمكنك التقاطه في استثناء كما فعلنا في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D8%A7%D9%84%D9%85%D8%AE%D8%B5%D9%91%D9%8E%D8%B5%D8%A9-%D9%81%D9%8A-laravel-r299/" rel=""> استخدام الاستثناءات Exceptions المخصَّصة في Laravel</a>.
</p>

<p>
	ثم اذهب إلى ملف السجل <code>storage/logs/laravel.log</code> للتأكد من نجاح معالجة الحدث؛ ستجد في آخر الملف ما يشبه التالي:
</p>

<pre class="ipsCode" id="ips_uid_2419_51">
[2016-03-30 22:16:29] local.DEBUG: Message-ID: &lt;8c79163440df2d3b5bbb3efd97ad549f@laraveltips.dev&gt;
Date: Wed, 30 Mar 2016 22:16:29 +0000
Subject: distinctio
From: Hsoub Academy &lt;hsoub@academy.com&gt;
To: fFranecki@example.net
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable</pre>

<p>
	يليه محتوى العرض المستخدم لتنسيق الرسالة (<code>mail.email_view</code> في المثال). إن حدثت مشكلة في إرسال البريد فسيتولّى الاستثناء -إن أعددتَه - إظهار العرض المناسب للزائر؛ وفي حال سريان الأمور على الوجه الأمثل فسيُظهر المتحكّم العرض <code>mail.success_view</code> للدلالة على نجاح الإرسال.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="14643" href="https://academy.hsoub.com/uploads/monthly_2016_03/01_eventing_laravel.png.40c7a02e4c57aea108a44d7b7792c7a0.png" rel="external"><img alt="01_eventing_laravel.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14643" data-unique="p7iasnumr" src="https://academy.hsoub.com/uploads/monthly_2016_03/01_eventing_laravel.thumb.png.4cf10c81787186c7993c0a58814dc4cb.png"></a>
</p>

<p>
	الملف المرفق: <a class="ipsAttachLink" data-fileid="14644" href="//academy.hsoub.com/applications/core/interface/file/attachment.php?id=14644" rel="">الأحداث في Laravel.zip</a>
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/10/01/eventing-in-laravel-5-1/" rel="external nofollow">Eventing in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">305</guid><pubDate>Sun, 22 May 2016 08:13:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x645;&#x643;&#x62A;&#x628;&#x629; Morris.js &#x644;&#x625;&#x646;&#x634;&#x627;&#x621; &#x645;&#x62E;&#x637;&#x637;&#x627;&#x62A; &#x628;&#x64A;&#x627;&#x646;&#x64A;&#x629; &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-morrisjs-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AE%D8%B7%D8%B7%D8%A7%D8%AA-%D8%A8%D9%8A%D8%A7%D9%86%D9%8A%D8%A9-%D9%81%D9%8A-laravel-r304/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_05/morris-charts-laravel.png.dc5fe7bd3148fac78ba1f5a60401058d.png" /></p>

<p>
	يكثُر استخدام المخططات البيانيّة في مواقع الويب لتقريب المعلومة للزّائر. سنرى في هذا الدرس كيفية إنشاء مخطّطات بيانية في تطبيق Laravel باستخدام مكتبة Morris.js.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="16261" data-unique="p759h7kps" src="https://academy.hsoub.com/uploads/monthly_2016_05/morris-charts-laravel.png.774f78974a4ccddcb60445372af19667.png" alt="morris-charts-laravel.png"></p>

<p>
	سنفترض أن لديك مشروع Laravel معدًّا وجاهزًا للعمل، وقاعدة بيانات مضبوطة. تتلخّص خطوات هذا الدرس في ما يلي:
</p>

<ul>
<li>
		إنشاء نموذج Model للتطبيق إضافة للتهجيرات Migrations المرتبطة به.
	</li>
	<li>
		إنشاء متحكّمات Controllers وعروض Views لإظهار البيانات للزائر.
	</li>
	<li>
		إنشاء معمل نماذج Model Factory لإضافة بيانات إلى قاعدة البيانات من أجل عرضها على هيئة مخططات بيانية.
	</li>
	<li>
		استخدام Mirror.js لتنسيق البيانات وعرضها في مخطّطات.
	</li>
</ul>
<h2 id="النموذج">
	النموذج
</h2>

<p>
	نبدأ بإنشاء نموذج نُسمّيه <code>Widget</code>؛ نستخدم الخيار <code>m-</code> لإنشاء تهجير في نفس الوقت:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5156_8">
<span class="pln">php artisan make:model Widget -m</span></pre>

<p>
	نفتح ملف التهجير ونعدّله ليصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_10">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Widget</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</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"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'widget_name'</span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $timestamps </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></pre>

<p>
	أعطينا القيمة <code>false</code> للمتغيّر <code>timestamps$</code> حتى لا يُملأ الحقلان <code>created_at</code> و<code>updated_at</code> تلقائيا في جدول البيانات. سنتستخدم معمل النماذج في ما بعد لملْء هذين الحقلين.
</p>

<p>
	ننتقل لملف التهجير ونضيف حقلا جديدا باسم <code>widget_name</code> إلى الجدول في قاعدة البيانات؛ تصبح الدالة <code>up</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_14">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'widgets'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'widget_name'</span><span class="pun">)-&gt;</span><span class="pln">unique</span><span class="pun">();</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</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="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%86%D9%85%D9%88%D8%B0%D8%AC%D8%A7-model-%D9%81%D9%8A-laravel-r297/" rel=""> كيف تنشئ نموذجا Model في Laravel</a> للمزيد.
</p>

<p>
	نفذ التهجير بالأمر التالي في مجلد المشروع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5156_16">
<span class="pln">php artisan migrate</span></pre>

<h2 id="تهيئة-التطبيق">
	تهيئة التطبيق
</h2>

<p>
	سنحتاج لمسارات للوصول إلى صفحات الموقع، عروض لإظهار البيانات، ومتحكمات للربط بين المسارات، النماذج والعروض. سنستخدم الأمر التالي الذي يُنشئ نموذجا للمستخدمين مع مسارات وعروض جاهزة لتسجيل المستخدمين في قاعدة البيانات وللولوج إلى التطبيق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_18">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">auth</span></pre>

<p>
	نفتح ملفّ العرض <code>app.blade.php</code> الموجود في المجلّد <code>resources/views/layouts</code> لتحريره. هذا هو <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/#%D8%AA%D9%88%D8%B1%D9%8A%D8%AB-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8" rel="">المخطّط الرئيس لعروض Blade</a> الذي أنشأه الأمر السابق.
</p>

<p>
	ابحث عن التعليق التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5156_20">
<span class="com">&lt;!-- Left Side Of Navbar --&gt;</span></pre>

<p>
	والذي توجد أسفله العناصر اليسرى من القائمة العلوية. سنضيف رابطين جديدين إلى القائمة، الأول للائحة بجميع التسجيلات الموجودة في الجدول <code>widgets</code> (كما فعلنا في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D8%A7%D9%84%D9%85%D8%AE%D8%B5%D9%91%D9%8E%D8%B5%D8%A9-%D9%81%D9%8A-laravel-r299/" rel=""> استخدام الاستثناءات Exceptions المخصَّصة في Laravel</a>) والثاني لصفحة المخطَّط البياني:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5156_22">
<span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ url('/widgets') }}"</span><span class="tag">&gt;</span><span class="pln">Widgets</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ url('/charts') }}"</span><span class="tag">&gt;</span><span class="pln">Chart</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span></pre>

<h3 id="المسارات">
	المسارات
</h3>

<p>
	أضفنا أعلاه رابطين؛ إلا أن المسارات التي تتولى الإجابة عنهما غير موجودة حتى الآن. نفتح ملف <code>routes.php</code> الموجود على المسار <code>app\Http</code> لإضافتها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_24">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">group</span><span class="pun">([</span><span class="str">'middleware'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'web'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">auth</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/charts'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@charts'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">group</span><span class="pun">([</span><span class="str">'middleware'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'web'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">auth</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/widgets'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@widgets_list'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">group</span><span class="pun">([</span><span class="str">'middleware'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'web'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">auth</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/widget/{id}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@widget_detail'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	جعلنا المسارات <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D9%8A%D8%AB%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-user-authentication-%D9%81%D9%8A-laravel-5-r229#%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%AD%D9%85%D9%8A%D8%A9" rel="">محمية</a> لكي يصل إليها المستخدمون المسجّلون فقط. الجديد هنا (مقارنة مع درس الاستثناءات المخصّصة المُشار إليه أعلاه) هو إضافة المسار <code>charts/</code> الذي تتولى دالة <code>charts</code> في المتحكّم <code>HomeController</code> الإجابة عنه. بالنسبة للمسارين الآخرين فأحدهما (<code>widgets/</code>) يعرض أسماء جميع التسجيلات في الجدول <code>widgets</code> والآخر (<code>{widget/{id/</code>) يعرض اسم التسجيلة ذات المعرّف <code>id</code>.
</p>

<h3 id="المتحكم">
	المتحكم
</h3>

<p>
	يوجد لدينا متحكّم واحد ناتج عن تطبيق أمر <code>artisan</code> الأخير. هذا المتحكّم هو <code>HomeController</code>. نفتح ملف المتحكّم <code>HomeController.php</code> الموجود على المسار <code>app/Http/Controllers</code> لتحريره. نضيف الدوال المذكورة في ملف المسارات السابق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_27">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> widgets_list</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $widgets </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Widget</span><span class="pun">::</span><span class="typ">Paginate</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'widgets.widgets'</span><span class="pun">,</span><span class="pln">array</span><span class="pun">(</span><span class="str">'widgets'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $widgets</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"> widget_detail</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $widget </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Widget</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'widgets.widget_detail'</span><span class="pun">,</span><span class="pln"> array</span><span class="pun">(</span><span class="str">'widget_name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $widget</span><span class="pun">-&gt;</span><span class="pln">widget_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"> charts</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    $yearCounts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Widget</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="pln">DB</span><span class="pun">::</span><span class="pln">raw</span><span class="pun">(</span><span class="str">'year(created_at) as year'</span><span class="pun">),</span><span class="pln">
            DB</span><span class="pun">::</span><span class="pln">raw</span><span class="pun">(</span><span class="str">'count(widget_name) as `count`'</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">groupBy</span><span class="pun">(</span><span class="str">'year'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">

    $chartData </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">$yearCounts</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"> </span><span class="pun">?</span><span class="pln"> $yearCounts </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">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$chartData</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"> view</span><span class="pun">(</span><span class="str">'widgets.widgets_chart'</span><span class="pun">,</span><span class="pln">array</span><span class="pun">(</span><span class="str">'chartData'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $chartData</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"> view</span><span class="pun">(</span><span class="str">'widgets.nowidgets'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	تبحث الدالة <code>widgets_list</code> عن محتويات الجدول <code>widgets</code> باستخدام دوال النموذج <code>Widget</code>. لاحظ أننا نريد تقسيم النتائج إلى صفحات بحيث تحوي كل صفحة عشرة نتائج، لذا استدعينا الدالة <code>Paginate</code> في الصّنف (النموذج) <code>Widget</code>. نُرسل ما عثرنا عليه إلى العرض <code>widgets</code> الموجود في مجلّد <code>widgets</code> ضمن مجلد العروض <code>resources/views</code>. في الدالة <code>widget_detail</code> نبحث عن التسجيلة ذات المعرّف <code>id</code> ونظهرها في العرض <code>widget_detail</code> ضمن مجلد <code>widgets</code> السابق.
</p>

<p>
	نأتي الآن للدالة <code>charts</code> التي تهيّئ البيانات لعرضها على هيئة مخطط بياني. نريد أن نعثُر على عدد التسجيلات المدرجة في جدول قاعدة البيانات مجموعة حسب السنة؛ على النحو التالي مثلا:
</p>

<pre class="ipsCode" id="ips_uid_5156_29">
year-|--count
2016 |  16
2015 |  12
2014 |  15
2013 |  11</pre>

<p>
	يمكّننا استعلام SQL التالي من الحصول على ما نريد:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5156_31">
<span class="pln">SELECT COUNT</span><span class="pun">(</span><span class="pln">widget_name</span><span class="pun">)</span><span class="pln"> AS count</span><span class="pun">,</span><span class="pln"> YEAR</span><span class="pun">(</span><span class="pln">created_at</span><span class="pun">)</span><span class="pln"> AS year FROM widgets GROUP BY year</span><span class="pun">;</span></pre>

<p>
	يمكن أن ننفّذ هذا الاستعلام باستخدام الواجهة <code>DB</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_35">
<span class="pln">DB</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="str">'SELECT COUNT(widget_name) AS count, YEAR(created_at) AS year FROM widgets GROUP BY year;'</span><span class="pun">);</span></pre>

<p>
	أو على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_37">
<span class="typ">Widget</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="pln">DB</span><span class="pun">::</span><span class="pln">raw</span><span class="pun">(</span><span class="str">'year(created_at) as year'</span><span class="pun">),</span><span class="pln"> DB</span><span class="pun">::</span><span class="pln">raw</span><span class="pun">(</span><span class="str">'count(widget_name) as `count`'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln">groupBy</span><span class="pun">(</span><span class="str">'year'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span></pre>

<p>
	نحصُل في كلتا الحالتين على مصفوفة Array من عمودين بناتج تنفيذ الاستعلام. راجع مقال <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-eloquent-orm-%D9%84%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r227/" rel="">استخدام Eloquent ORM للتعامل مع قاعدة البيانات في Laravel 5</a> حول الموضوع.
</p>

<p>
	لا تنس استيراد النموذج <code>Widget</code> والواجهة <code>DB</code> قبل استخدامهما في المتحكّم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_39">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Widget</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> DB</span><span class="pun">;</span></pre>

<p>
	نفحص المصفوفة المتحصَّل عليها؛ في حال وجود نتائج نرسلها إلى العرض <code>widgets_chart</code> ضمن المجلد <code>resources/views/widgets</code>؛ وإلا نظهر العرض <code>nowidgets</code> الموجود في نفس المجلّد. سنؤخّر الحديث عن العروض إلى أن ننشئ معمل نماذج لملْء جدول قاعدة البيانات.
</p>

<h3 id="معمل-النماذج-وبذر-قاعدة-البيانات">
	معمل النماذج وبذر قاعدة البيانات
</h3>

<p>
	تحدثنا في درس عن استخدام <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D8%B9%D9%85%D9%84-%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-model-factory-%D9%81%D9%8A-laravel-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-r298/" rel="">معمل النماذج Model factory لتوليد بيانات الاختبار</a>، سنعمل بنفس المبدأ هنا. ننشئ ملفا باسم <code>WidgetFactory.php</code> على المسار <code>database/factories</code> ونضيف إليه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_41">
<span class="pun">&lt;?</span><span class="pln">php
$factory</span><span class="pun">-&gt;</span><span class="pln">define</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\Widget</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Faker</span><span class="pln">\Generator $faker</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">
        </span><span class="str">'widget_name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $faker</span><span class="pun">-&gt;</span><span class="pln">unique</span><span class="pun">()-&gt;</span><span class="pln">word</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"> $faker</span><span class="pun">-&gt;</span><span class="pln">dateTimeBetween</span><span class="pun">(</span><span class="pln">$startDate </span><span class="pun">=</span><span class="pln"> </span><span class="str">'-4 years'</span><span class="pun">,</span><span class="pln"> $endDate </span><span class="pun">=</span><span class="pln"> </span><span class="str">'now'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تنشئ الشفرة السابقة تسجيلا في جدول البيانات <code>widgets</code> بتوليد محتويات الحقلين <code>widget_name</code> و<code>created_at</code>. لاحظ أننا نستخدم مكتبة Faker. حدّدنا تاريخ <code>created_at</code> بالمجال من قبل أربع سنوات إلى الآن.
</p>

<p>
	يأتي الآن دور بذر البيانات. ننشئ صنفا لبذر الجدول <code>widgets</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_45">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">WidgetTableSeeder</span></pre>

<p>
	نفتح الملف <code>database/seeds/WidgetTableSeeder.php</code> ونحرّر الدالة <code>run</code> ليصبح كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5156_43">
<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">
        </span><span class="typ">Widget</span><span class="pun">::</span><span class="pln">truncate</span><span class="pun">();</span><span class="pln">
        factory</span><span class="pun">(</span><span class="typ">Widget</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">)-&gt;</span><span class="pln">create</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	نحذف محتوى الجدول لكي لا يحصُل تعارض مع البيانات الجديدة التي سنولّدها؛ ثم نستخدم معمل النماذج لإدراج 50 تسجيلة. لا تنس استيراد النموذج <code>Widget</code>: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_8">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Widget</span><span class="pun">;</span></pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_10">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed </span><span class="pun">--</span><span class="kwd">class</span><span class="pun">=</span><span class="typ">WidgetTableSeeder</span></pre>

<p>
	توجد طريقة أخرى هي التي سنستخدمها. نحرّر الملف <code>DataBaseSeeder.php</code> الموجود على نفس مسار <code>WidgetTableSeeder.php</code> ونضيف ما يلي إلى الدالة <code>run</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_12">
<span class="typ">Widget</span><span class="pun">::</span><span class="pln">unguard</span><span class="pun">();</span><span class="pln">
$this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">WidgetTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Widget</span><span class="pun">::</span><span class="pln">reguard</span><span class="pun">();</span></pre>

<p>
	نطلُب نزع الحماية عن الجدول قبل بذره ثم نعيدها إليه. يؤدي النداء <code>call</code> مهمّة البذر.
</p>

<p>
	يتيح الملف <code>DataBaseSeeder</code> إمكانية تنفيذ أصناف بذر عدّة بنفس الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_14">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<p>
	بقيت الخطوة الأخيرة وهي إنشاء العروض.
</p>

<h2 id="العروض">
	العروض
</h2>

<p>
	نأتي الآن للعروض التي ورد ذكرها في المتحكّم دون أن تكون أنشئت. ستجد العروض في <a data-fileid="14529" href="http://academy.hsoub.com/applications/core/interface/file/attachment.php?id=14529" rel="">الملف المرفق</a>. نشير إلى استخدام التعليمة التاليّة في العرض <code>widgets</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_16">
<span class="pun">{!!</span><span class="pln"> $widgets</span><span class="pun">-&gt;</span><span class="pln">render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">!!}</span></pre>

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

<p>
	نأتي الآن لشرح العرض <code>widgets_chart</code> الذي يتضمن المخطّط البياني الذي نهدف لإنشائه في هذا الدرس.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_26">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.app'</span><span class="pun">)</span><span class="pln">

</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"container"</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"row"</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-md-10 col-md-offset-1"</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"panel panel-default"</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"panel-heading"</span><span class="pun">&gt;</span><span class="typ">Chart</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"panel-body"</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div id</span><span class="pun">=</span><span class="str">"chart"</span><span class="pln"> style</span><span class="pun">=</span><span class="str">"height: 250px;"</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">link rel</span><span class="pun">=</span><span class="str">"stylesheet"</span><span class="pln"> href</span><span class="pun">=</span><span class="str">"//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">script src</span><span class="pun">=</span><span class="str">"//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"</span><span class="pun">&gt;&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">script src</span><span class="pun">=</span><span class="str">"//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"</span><span class="pun">&gt;&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">script src</span><span class="pun">=</span><span class="str">"//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"</span><span class="pun">&gt;&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln">
</span><span class="str">&lt;script&gt;</span><span class="pln">
        </span><span class="kwd">var</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;?</span><span class="pln">php echo json_encode</span><span class="pun">(</span><span class="pln">$chartData</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?&gt;;</span><span class="pln">

        </span><span class="typ">Morris</span><span class="pun">.</span><span class="typ">Line</span><span class="pun">({</span><span class="pln">
            element</span><span class="pun">:</span><span class="pln"> </span><span class="str">'chart'</span><span class="pun">,</span><span class="pln">
            data</span><span class="pun">:</span><span class="pln"> data</span><span class="pun">,</span><span class="pln">
            xkey</span><span class="pun">:</span><span class="pln"> </span><span class="str">'year'</span><span class="pun">,</span><span class="pln">
            ykeys</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'count'</span><span class="pun">],</span><span class="pln">
            labels</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'widgets created'</span><span class="pun">]</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	يمدّد العرضُ العرض الرئيس <code>layouts.app</code> ويعرّف محتوى المقطع <code>content</code>. يوجد في هذا المقطع العنصُر التالي ذي المعرّف <code>chart</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4482_28">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"chart"</span><span class="pln"> </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="pln">height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">250px</span><span class="pun">;</span><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	سيُعرَض المخطّط البياني في هذا العنصُر. تأتي بعد ذلك اعتماديات مكتبة Morris:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4482_30">
<span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"</span><span class="tag">&gt;&lt;/script&gt;</span></pre>

<p>
	وأخيرا السكربت الذي سيرسُم المخطّط:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4482_32">
<span class="tag">&lt;script&gt;</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;?</span><span class="pln">php echo json_encode</span><span class="pun">(</span><span class="pln">$chartData</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?&gt;;</span><span class="pln">

    </span><span class="typ">Morris</span><span class="pun">.</span><span class="typ">Line</span><span class="pun">({</span><span class="pln">
        element</span><span class="pun">:</span><span class="pln"> </span><span class="str">'chart'</span><span class="pun">,</span><span class="pln">
        data</span><span class="pun">:</span><span class="pln"> data</span><span class="pun">,</span><span class="pln">
        xkey</span><span class="pun">:</span><span class="pln"> </span><span class="str">'year'</span><span class="pun">,</span><span class="pln">
        ykeys</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'count'</span><span class="pun">],</span><span class="pln">
        labels</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'widgets created'</span><span class="pun">]</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="tag">&lt;/script&gt;</span></pre>

<p>
	يستقبل السكربت البيانات التي أرسلتها الدالة <code>charts</code> المعرّفة في المتحكم <code>HomeController</code> ويحوّلها إلى صيغة JSON التي تستخدمها مكتبة Morris:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4482_34">
<span class="kwd">var</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;?</span><span class="pln">php echo json_encode</span><span class="pun">(</span><span class="pln">$chartData</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?&gt;;</span></pre>

<p>
	ثم نستدعي الدالة <code>Line</code> في مكتبة Morris:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4482_38">
<span class="typ">Morris</span><span class="pun">.</span><span class="typ">Line</span><span class="pun">({</span><span class="pln">
    element</span><span class="pun">:</span><span class="pln"> </span><span class="str">'chart'</span><span class="pun">,</span><span class="pln">
    data</span><span class="pun">:</span><span class="pln"> data</span><span class="pun">,</span><span class="pln">
    xkey</span><span class="pun">:</span><span class="pln"> </span><span class="str">'year'</span><span class="pun">,</span><span class="pln">
    ykeys</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'count'</span><span class="pun">],</span><span class="pln">
    labels</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'widgets created'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	نمرّر للدالة معرّف العنصُر الذي سنرسم في المخطّط (المعطى <code>element</code>)، البيانات التي نودّ رسمها (<code>data</code>)، عنصُر المصفوفة الذي سيكون في المحور الأفقي للمخطّط (<code>xkey</code>) والعنصُر-أ و العناصر- الذي سيكون على المحور العمودي (<code>ykeys</code>)؛ إضافة للصيقة Label تظهر في المخطّط.
</p>

<p>
	نذهب الآن لرابط المشروع؛ بالنسبة لي الرابط هو:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4482_40">
<span class="pln">http://laraveltips.dev</span></pre>

<p>
	نسجّل مستخدما جديدا (<code>register</code>) ثم نضغط على الرابط <code>Chart</code> لنجد النتيجة التالية (قد يختلف المخطّط البياني عن الموجود في الصورة بسسب أن البيانات مولَّدة عشوائيا).
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="14528" href="https://academy.hsoub.com/uploads/monthly_2016_03/01_chart.png.072513e956a30ef01df4ba8e5ff85e59.png" rel="external"><img alt="01_chart.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14528" data-unique="0daipeosq" src="https://academy.hsoub.com/uploads/monthly_2016_03/01_chart.thumb.png.fb45be8c5e37bf6db8ad8f694e05e5db.png"></a>
</p>

<p>
	الملف المرفق: <a class="ipsAttachLink" data-fileid="14529" href="//academy.hsoub.com/applications/core/interface/file/attachment.php?id=14529" rel="">laravelchart.zip</a>
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/08/22/charts-in-laravel-5-1-with-morris-js/" rel="external nofollow">Charts in Laravel 5.1 with Morris.js</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">304</guid><pubDate>Tue, 10 May 2016 08:19:59 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x635;&#x648;&#x631; &#x627;&#x644;&#x631;&#x645;&#x632;&#x64A;&#x629; &#x627;&#x644;&#x639;&#x627;&#x644;&#x645;&#x64A;&#x629; Gravatar &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D8%A7%D9%84%D8%B1%D9%85%D8%B2%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%A7%D9%84%D9%85%D9%8A%D8%A9-gravatar-%D9%81%D9%8A-laravel-r321/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_05/gravatar-laravel.png.73c7c2e8db3b0a0422d6c67e89634eaa.png" /></p>

<p dir="rtl">
	لم تعد الصور الرمزيّة لحسابات المستخدمين أمرًا جديدًا ويندر أن تجد برنامجًا لا يسمح لمستخدميه بعرض صورة للمستخدم في صفحته الشّخصية مثلًا أو نحو ذلك، وقد ظهرت من عدّة سنوات فكرة أن يكون للمستخدم صورة رمزية يمكنه استخدامها في الكثير من المواقع والخدمات دون أن يحتاج في كلّ مرّة إلى اختيارها ورفعها، وهذا ما تمّ فعلًا في <a href="https://en.gravatar.com/" rel="external nofollow">مشروع أطلق عليه اسم </a><a href="https://en.gravatar.com/" rel="external nofollow">Gravatar</a> اختصارًا للصورة الرمزيّة المتعارف عليها عالميًّا Globally Recognized Avatar.
</p>

<p dir="rtl" style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="15891" data-unique="u8f23pe62" src="https://academy.hsoub.com/uploads/monthly_2016_05/gravatar-laravel.png.179be9b0d8d17cc28152d890268c45b5.png" alt="gravatar-laravel.png"></p>

<p dir="rtl">
	<a name="_GoBack" rel="external"></a> إنّ إضافة صورة Gravatar إلى شريط التصفّح في مشروع مبني بـ Laravel من أكثر الأعمال سهولة فلا تتطلب العملية أكثر من 4 خطوات بسيطة، ويعود الفضل في هذا إلى فريق CreativeOrange، الذين يمكن زيارة <a href="http://packalyst.com/packages/package/creativeorange/gravatar" rel="external nofollow">صفحة مشروعهم</a> لقراءة الإرشادات الأصليّة، فيما إذا طرأت تغييرات ما.
</p>

<h2 dir="rtl">
	الخطوة الأولى
</h2>

<p dir="rtl">
	لنقم بتحميل نسخة من الحزمة المطلوبة باستخدام <a href="https://getcomposer.org/" rel="external nofollow">Composer</a> عبر سطر الأوامر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8097_9">
<span class="pln">composer require creativeorange/gravatar ~1.0</span></pre>

<p dir="rtl">
	أو من الممكن التعديل على ملف <span style="font-family:courier new,courier,monospace;">composer.json</span> وإضافة اسم الحزمة والإصدار المطلوب إلى لائحة الحزم المطلوبة:
</p>

<pre class="ipsCode" id="ips_uid_8097_18">
"require": {
    "creativeorange/gravatar": "~1.0"
}</pre>

<p dir="rtl">
	وفي حال تعديل الملف، فيتوجّب علينا أن نقوم بتنفيذ الأمر التّالي من سطر الأوامر ليتمّ تحديث المشروع وتحميل الحزمة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8097_14">
<span class="pln">composer update</span></pre>

<h2 dir="rtl">
	الخطوة الثانية
</h2>

<p dir="rtl">
	نحتاج الآن لإضافة مزوّد خدمة Service Provider إلى ملف<span style="font-family:courier new,courier,monospace;"> app/config/app.php </span>في مصفوفة <span style="font-family:courier new,courier,monospace;">providers</span> بالشّكل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_41">
<span class="str">'providers'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

    </span><span class="com">// Other Service Providers</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">

    </span><span class="typ">App</span><span class="pln">\Providers\AppServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">

    </span><span class="com">// ...</span><span class="pln">
    </span><span class="com">// Other Service Providers</span><span class="pln">

</span><span class="pun">],</span></pre>

<p dir="rtl">
	<strong>ملاحظة</strong>: لا تنس الفاصلة في نهاية السطر إن لم تدرج السطر في نهاية المصفوفة.
</p>

<p dir="rtl">
	نلاحظ فيما سبق بأننا استخدمنا الصيغة الخاصة بـ PHP 5.6 وهي الصيغة القياسية لمصفوفة <span style="font-family:courier new,courier,monospace;">providers</span> في الإصدار 5.* من Laravel.
</p>

<h2 dir="rtl">
	الخطوة الثالثة
</h2>

<p dir="rtl">
	لنقم الآن بإضافة إختصار في مصفوفة <span style="font-family:courier new,courier,monospace;">aliases</span> في ملف <span style="font-family:courier new,courier,monospace;">app.php</span> ذاته:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_39">
<span class="str">'aliases'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

    </span><span class="com">// ...</span><span class="pln">

    </span><span class="str">'Gravatar'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Creativeorange</span><span class="pln">\Gravatar\Facades\Gravatar</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">

    </span><span class="com">// ...</span><span class="pln">

</span><span class="pun">],</span></pre>

<p dir="rtl">
	نلاحظ بأن كلّ ما احتجنا لإضافته في الخطوتين السابقتين هو سطر واحد فقط، وهذا من الأمور المميّزة في معمارية Laravel، حيث أنّ حزّم Service Providers كأحجار البناء في التطبيق البرمجيّ ويمكن ملاحظة مدى سهولة استخدامها في البرنامج، فلا يتطلّب الأمر أكثر من سطرين.
</p>

<p dir="rtl">
	أصبح الآن بالإمكان استخدام الصفّ Gravatar في البرنامج بسهولة من خلال الواجهة التي حصلنا عليّها، الأمر الذي يمكن القيام به على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_37">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Gravatar</span><span class="pun">;</span></pre>

<p dir="rtl">
	لكن لن نحتاج لاستخدامه بهذا الشكل في مثالنا.
</p>

<h2 dir="rtl">
	الخطوة الرابعة
</h2>

<p dir="rtl">
	من المحتمل أن الاستخدام الأسهل للإضافة Gravatar يكون عبر إدراجها مباشرة في عرض View، كالصّفحة الرّئيسية كأن تكون عنصر قائمة في شريط التصفّح الرئيسي العلويّ. سنحتاج بداية للتحقّق فيما إذا قد تمّ تسجيل الدخول أولًا أم لا، ويمكن ذلك باستخدام<span style="font-family:courier new,courier,monospace;"> ()Auth::check</span> المتاحة للاستخدام دومًا عند الحاجة لها، كما في الشّكل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_26">
<span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Auth</span><span class="pun">::</span><span class="pln">check</span><span class="pun">())</span><span class="pln">
    </span><span class="com">// أظهر العنصر</span><span class="pln">
</span><span class="lit">@endif</span></pre>

<p dir="rtl">
	تستخدم الشّيفرة السابقة الصّيغة القياسية لنظام القوالب Blade والذي نحتاج لمعرفة استخدامه عند اختيار إطار العمل Laravel، وتسمح صيغة blade بالمزج ما بين شيفرات HTML و PHP بسهولة عند الاستخدام، دون الحاجة لاستخدام وسوم البدء الخاصّة بـ PHP، من خلال إدراج التعليمات ما بين الأقواس {{ .. }} كما يظهر في الكود البرمجيّ التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_35">
<span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Auth</span><span class="pun">::</span><span class="pln">check</span><span class="pun">())</span><span class="pln"> 
    </span><span class="str">&lt;li&gt;</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"{{ Gravatar::get(Auth::user()-&gt;email) }}"</span><span class="pln"> style</span><span class="pun">=</span><span class="str">"height:50px; width:50px; border-radius:50%;"</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="lit">@endif</span></pre>

<p dir="rtl">
	والآن لنأخذ الجزء الأهمّ ما بين الأقواس ولنقم بتوضيحه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_30">
<span class="typ">Gravatar</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="typ">Auth</span><span class="pun">::</span><span class="pln">user</span><span class="pun">()-&gt;</span><span class="pln">email</span><span class="pun">)</span></pre>

<p dir="rtl">
	يؤدّي استدعاء التابع <span style="font-family:courier new,courier,monospace;">()get</span> من الصنفّ Gravatar إلى إعادة مسار نصيّ بصيغة URL لصورة gravatar بعد أن نقوم بتزويده ببريد إلكترونيّ، ونظرًا لأنّا نرغب بعرض صورة حساب المستخدم النشط في البرنامج فإنّ بالإمكان الحصول على البريد الإلكتروني للحساب من الكائن object الذي يعيده استدعاء التابع <span style="font-family:courier new,courier,monospace;">()Auth::user</span> الذي يحمل معلومات عن المستخدم صاحب جلسة العمل النشطة.
</p>

<p dir="rtl">
	قد لا يكون قياس الصّورة التي نحصل عليها مناسبًا لنا، ولحلّ هذه المشكلة يمكن تغيير القياس الافتراضيّ المطلوب من خلال تعديل قيمة المتغيّر <span style="font-family:courier new,courier,monospace;">size</span> في المصفوفة <span style="font-family:courier new,courier,monospace;">default</span> في الملف <span style="font-family:courier new,courier,monospace;">vendor/creativeorange/gravatar/config/gravatar.php:</span>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8097_33">
<span class="str">'default'</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">'size'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">80</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'fallback'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'mm'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'secure'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'maximumRating'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'g'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'forceDefault'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'forceExtension'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'jpg'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">),</span></pre>

<p dir="rtl">
	وهناك العديد من القيم الافتراضية التي يمكن تغييرها لتتناسب مع احتياجاتنا في هذا الملف، كالصّورة الافتراضيّة التي يتم عرضها في حال لم يكن للمستخدم صورة Gravatar، أو طلب الصورة بصيغة مختلفة عن JPG، وغير ذلك.
</p>

<p dir="rtl">
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/06/10/laravel-5-gravatar-plugin/" rel="external nofollow">Laravel 5.1 Gravatar Plugin</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">321</guid><pubDate>Mon, 02 May 2016 11:29:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x62B;&#x646;&#x627;&#x621;&#x627;&#x62A; Exceptions &#x627;&#x644;&#x645;&#x62E;&#x635;&#x635;&#x629; &#x641;&#x64A; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D8%A7%D9%84%D9%85%D8%AE%D8%B5%D8%B5%D8%A9-%D9%81%D9%8A-laravel-r299/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_04/laravel-custom-exceptions.png.1da26aff2e5394a0fbef1040b7802284.png" /></p>

<p>
	يستخدم Laravel الصنف <code>Handler</code> الموجود على المسار <code>app/Exceptions</code> للتعامل مع جميع الاستثناءات. يحوي هذا الصّنف دالتين: <code>report</code> و<code>render</code>. تُستخدَم دالة <code>report</code> لتسجيل الاستثناءات أو إرسالها إلى خدمة خارجية؛ أما الدالة <code>render</code> فتُستخدَم لاعتراض الاستثناءات وإرسال إجابة مناسبة إلى المتصفّح ليعرضها للزّائر.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="15422" data-unique="9u1804xnz" src="https://academy.hsoub.com/uploads/monthly_2016_04/laravel-custom-exceptions.png.109ac86560ac61ecd3ad4e5f74072f98.png" alt="laravel-custom-exceptions.png"></p>

<p>
	<strong>ملحوظة:</strong> اعتمدنا العروض، المسارات والمتحكّم الذي أنشأناه في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-phpunit-%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r296/#%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D8%B3%D8%AA%D9%85%D8%A7%D8%B1%D8%A9-form-%D9%84%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85" rel="">كيف تستخدم PHPUnit لاختبار تطبيقات Laravel</a> وبنينا عليها لتطبيق الخطوات الواردة هنا. يمكنك تجربة الدّرس على مشروعك الخاص أو استخدام <a data-fileid="14332" href="http://academy.hsoub.com/applications/core/interface/file/attachment.php?id=14332" rel="">الملفّ المرفَق</a> الذي يمثّل الحصيلة النهائية لهذا الدرس. إن استخدمت الملفّ المرفق فستحتاج لتسجيل مستخدم أولا عبر رابط <code>register</code> والدخول إلى الموقع حتى يظهر بقية المحتوى (سنترك لك اكتشاف الآلية المستخدمة في ذلك. كلمة السّر: <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D9%8A%D8%AB%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-user-authentication-%D9%81%D9%8A-laravel-5-r229/#%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%AD%D9%85%D9%8A%D8%A9" rel="">المسارات المحميّة</a>).
</p>

<h2 id="تخصيص-رسائل-الاستثناءات">
	تخصيص رسائل الاستثناءات
</h2>

<p>
	يُعدّ <code>ErrorException</code> أحد أكثر الاستثناءات انتشارا ويظهر مثلا عند إضافة معرف كائن غير موجود إلى مسار URL، أو عند طلب خاصيّة غير موجودة في الكائن. عند محاولة دخول المسار التالي دون أن تكون التسجيلة ذات المعرّف <code>56</code> موجودة في جدول البيانات <code>widgets</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7579_7">
<span class="pln">laravel.dev/widget/56</span></pre>

<p>
	فستظهر في المتصفّح صفحة خطأ كالتالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="14329" href="https://academy.hsoub.com/uploads/monthly_2016_03/01_ErrorException.png.1e7c8176fbd5db4ea0e10bfc127261eb.png" rel="external"><img alt="01_ErrorException.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14329" data-unique="ji6a9t0qd" src="https://academy.hsoub.com/uploads/monthly_2016_03/01_ErrorException.thumb.png.155ad02c2f488e876277586d05d69b7e.png"></a>
</p>

<p>
	صفحة الخطأ هذه مفيدة للمطوّرين إلا أننا لا نرغب في أن يراها زوار الموقع؛ لذا يجب علينا التعامل مع هذا الاستثناء وقت حدوثه وعرض رسالة مغايرة للزائر.
</p>

<p>
	نعدّل دالة <code>render</code> في ملف <code>Handler.php</code> لتصبِح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_9">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> render</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">,</span><span class="pln"> </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">
        </span><span class="kwd">switch</span><span class="pun">(</span><span class="pln">$e</span><span class="pun">){</span><span class="pln">

            </span><span class="kwd">case</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$e </span><span class="kwd">instanceof</span><span class="pln"> </span><span class="typ">ErrorException</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="typ">ErrorException</span><span class="pun">(</span><span class="pln">$e</span><span class="pun">);</span><span class="pln">
                </span><span class="kwd">break</span><span class="pln">

            </span><span class="kwd">default</span><span class="pun">:</span><span class="pln">

                </span><span class="kwd">return</span><span class="pln"> parent</span><span class="pun">::</span><span class="pln">render</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">,</span><span class="pln"> $e</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_7579_11">
<span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> renderErrorException</span><span class="pun">(</span><span class="pln">$e</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"> response</span><span class="pun">()-&gt;</span><span class="pln">view</span><span class="pun">(</span><span class="str">'errors.404'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[],</span><span class="pln"> </span><span class="lit">404</span><span class="pun">);</span><span class="com">/*
    }</span></pre>

<p>
	يمكنك أن تلاحظ أننا أضفنا <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AC%D9%85%D9%84-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%81%D9%8A-php-r238/" rel="">عبارة <code>switch</code></a> إلى الدالة من أجل تحديد نوعيّة الاستثناء فإن كان من نوع <code>ErrorException</code> استدعينا الدالة <code>renderErrorException</code> وإلا نترك الدالة المبدئية تتكفّل بالموضوع. استخدمنا عبارة <code>switch</code> هنا لتسهيل إضافة معالَجات خاصّة في ما بعد لأنواع أخرى من الاستثناءات.
</p>

<p>
	نستخدم في الدالة <code>renderErrorException</code> عرضا خاصّا سميناه <code>404</code>. يحوي مجلد العروض في Laravel مجلّدا خاصّا لعروض الأخطاء <code>errors</code>؛ ننشئ فيه العرض <code>404</code> ذي المحتوى التالي مع إضافة اللاحقة <code>blade.php.</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8709_7">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.app'</span><span class="pun">)</span><span class="pln">

</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">

</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"alert alert-danger alert-dismissible alert-important"</span><span class="pln"> role</span><span class="pun">=</span><span class="str">"alert"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">button type</span><span class="pun">=</span><span class="str">"button"</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"close"</span><span class="pln"> data</span><span class="pun">-</span><span class="pln">dismiss</span><span class="pun">=</span><span class="str">"alert"</span><span class="pln"> aria</span><span class="pun">-</span><span class="pln">label</span><span class="pun">=</span><span class="str">"Close"</span><span class="pun">&gt;&lt;</span><span class="pln">span aria</span><span class="pun">-</span><span class="pln">hidden</span><span class="pun">=</span><span class="str">"true"</span><span class="pun">&gt;×&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">button</span><span class="pun">&gt;</span><span class="pln">
</span><span class="str">&lt;strong&gt;</span><span class="typ">Oh</span><span class="pln"> </span><span class="typ">Snap</span><span class="pun">!&lt;/</span><span class="pln">strong</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">We</span><span class="pln"> can</span><span class="str">'t find what you are looking for...
&lt;/div&gt;

@endsection</span></pre>

<p>
	بقي لنا استيراد صنف الاستثناءات <code>ErrorException</code> في ملف <code>Handler.php</code>: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_15">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">ErrorException</span><span class="pun">;</span></pre>

<p>
	هذا كل ما نحتاجه. نعود الآن لنرى الرابط السابق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_17">
<span class="pln">laravel</span><span class="pun">.</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">widget</span><span class="pun">/</span><span class="lit">56</span></pre>

<p>
	إن لم يكن الكائن ذو المعرّف موجودا فستظهر رسالة الخطأ التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="14330" href="https://academy.hsoub.com/uploads/monthly_2016_03/02_ErrorException.png.05da72f426083ecaea532a68eded53f1.png" rel="external"><img alt="02_ErrorException.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14330" data-unique="n93e01kyq" src="https://academy.hsoub.com/uploads/monthly_2016_03/02_ErrorException.thumb.png.d79d0e5a95e960c7ee8338c86abdc4cc.png"></a>
</p>

<h2 id="تخصيص-الاستثناءات">
	تخصيص الاستثناءات
</h2>

<p>
	استخدمنا في الفقرة السابقة استثناءً موجودا وخصّصنا النتيجة التي يعرضها للزائر. نريد في هذه الفقرة إنشاء استثناء مخصَّص لتلبية حاجة خاصّة بمشروعنا. سنفرض مثلا أننا نريد إظهار رسالة خطأ للزائر عند تصفّح الرابط <code>/create/widget/</code>، سنسمّي الاستثناء الجديد <code>WidgetCreateException</code>.
</p>

<p>
	نبدأ بإنشاء ملف <code>WidgetCreateException.php</code> في المجلّد <code>Exceptions</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_19">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Exceptions</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">WidgetCreateException</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> \Exception
</span><span class="pun">{</span><span class="pln">


</span><span class="pun">}</span></pre>

<p>
	لاحظ مساحة الأسماء Namespace. لا نريد أن نعقّد الأمور، لذا سنترك الصّنف على ماهو عليه دون إضافة معالجات خاصّة، حتى نفهم المبدأ.
</p>

<p>
	نعود للملف <code>Handler.php</code> ونعدّله باستيراد الصّنف الذي أنشأناه للتّو:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_21">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Exceptions\WidgetCreateException</span><span class="pun">;</span></pre>

<p>
	ثم نعدّل دالّة <code>render</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_23">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> render</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">,</span><span class="pln"> </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">
            </span><span class="kwd">switch</span><span class="pun">(</span><span class="pln">$e</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="pun">(</span><span class="pln">$e </span><span class="kwd">instanceof</span><span class="pln"> </span><span class="typ">ErrorException</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">renderErrorException</span><span class="pun">(</span><span class="pln">$e</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="pun">(</span><span class="pln">$e </span><span class="kwd">instanceof</span><span class="pln"> </span><span class="typ">WidgetCreateException</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">renderWidgetCreateException</span><span class="pun">(</span><span class="pln">$e</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">

                </span><span class="kwd">return</span><span class="pln"> parent</span><span class="pun">::</span><span class="pln">render</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">,</span><span class="pln"> $e</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_7579_25">
<span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> renderWidgetCreateException</span><span class="pun">(</span><span class="pln">$e</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"> response</span><span class="pun">()-&gt;</span><span class="pln">view</span><span class="pun">(</span><span class="str">'errors.widgetcreate'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[],</span><span class="pln"> </span><span class="lit">404</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يعني هذا أنه في حالة ظهور استثناء من نوع <code>WidgetCreateException</code> فسنستدعي الدالة <code>renderWidgetCreateException</code> التي تُظهر العرض <code>widgetcreate</code>.
</p>

<p>
	بقي لنا الآن إنشاء ملف العرض <code>widgetcreate.blade.php</code> في المجلّد <code>errors</code> التابع لمجلد العروض:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_27">
<span class="lit">@extends</span><span class="pun">(</span><span class="str">'layouts.app'</span><span class="pun">)</span><span class="pln">

</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">

</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"alert alert-danger alert-dismissible alert-important"</span><span class="pln"> role</span><span class="pun">=</span><span class="str">"alert"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">button type</span><span class="pun">=</span><span class="str">"button"</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"close"</span><span class="pln"> data</span><span class="pun">-</span><span class="pln">dismiss</span><span class="pun">=</span><span class="str">"alert"</span><span class="pln"> aria</span><span class="pun">-</span><span class="pln">label</span><span class="pun">=</span><span class="str">"Close"</span><span class="pun">&gt;&lt;</span><span class="pln">span aria</span><span class="pun">-</span><span class="pln">hidden</span><span class="pun">=</span><span class="str">"true"</span><span class="pun">&gt;×&lt;</span><span class="str">/span&gt;&lt;/</span><span class="pln">button</span><span class="pun">&gt;</span><span class="pln">
</span><span class="str">&lt;strong&gt;</span><span class="typ">Yes</span><span class="pun">!&lt;/</span><span class="pln">strong</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">You</span><span class="pln"> threw a </span><span class="typ">Widget</span><span class="pln"> </span><span class="typ">Creation</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="lit">@endsection</span></pre>

<p>
	سننشئ لتجربة صنف الاستثناء الجديد داالةً في المتحكّم المناسب (<code>HomeController</code> في حالتي) كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_29">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</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">WidgetCreateException</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استيراد الصنف <code>WidgetCreateException</code> في المتحكم: 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_31">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Exceptions\WidgetCreateException</span><span class="pun">;</span></pre>

<p>
	وإضافة مسار لـ<code>/create/widget</code> في ملف <code>routes.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_7579_33">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">group</span><span class="pun">([</span><span class="str">'middleware'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'web'</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"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">auth</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/create/widget'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'HomeController@create'</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_7579_35">
<span class="pln">http</span><span class="pun">:</span><span class="com">//laranew.dev/create/widget</span></pre>

<p>
	لاحظ النتيجة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="14331" href="https://academy.hsoub.com/uploads/monthly_2016_03/03_WidgetCreationException.png.039435c0fcff6ceeaa760d4c3a6a6a93.png" rel="external"><img alt="03_WidgetCreationException.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14331" data-unique="ifzgze8aq" src="https://academy.hsoub.com/uploads/monthly_2016_03/03_WidgetCreationException.thumb.png.9420cf099c822d4b629f321492ec7030.png"></a>
</p>

<p>
	قدّمنا في هذا المقال أساسيات تخصيص الاستثناءات في Laravel؛ ما زال يوجد الكثير لتعلمّه في هذا الإطار انطلاقا من هذه الأساسيات.
</p>

<p>
	حمل <a data-fileid="14332" href="http://academy.hsoub.com/applications/core/interface/file/attachment.php?id=14332" rel="">الملف المرفق</a> لهذا الدرس.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/08/19/handling-exceptions-custom-exceptions-in-laravel-5-1/" rel="external nofollow">Handling Exceptions and Custom Exceptions in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">299</guid><pubDate>Tue, 19 Apr 2016 11:43:38 +0000</pubDate></item></channel></rss>
