<?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/3/?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>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x645;&#x639;&#x645;&#x644; &#x627;&#x644;&#x646;&#x645;&#x627;&#x630;&#x62C; (Model factory) &#x641;&#x64A; Laravel &#x644;&#x62A;&#x648;&#x644;&#x64A;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x627;&#x644;&#x627;&#x62E;&#x62A;&#x628;&#x627;&#x631;</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%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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_04/laravel-model-factory.png.85df16c5160e973689f7943202ab925f.png" /></p>

<p>
	يأتي Laravel مبدئيا بمعمل نماذج Model factory يُستخدَم لتسريع بناء النماذج واختبارها. سنرى في هذا المقال طريقتين لإدراج تسجيلات في جدول قاعدة بيانات باستخدام معمل النماذج. سنعتمد في الخطوات الموالية على النموذج الذي أنشأناه في الدرس السابق <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 style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="15139" data-unique="o4n2rd3lm" src="https://academy.hsoub.com/uploads/monthly_2016_04/laravel-model-factory.png.1612ba91c53eea1c78a71dfdbbf3e284.png" alt="laravel-model-factory.png"></p>

<h2 id="الطريقة-الأولى-بذر-جدول-البيانات">
	الطريقة الأولى: بذر جدول البيانات
</h2>

<p>
	نبدأ بفتح الملف <code>database/factories/ModelFactory.php</code>. يأتي الملف مبدئيا بدالّة لـ<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/#%D8%A8%D8%B0%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" rel="">بذر</a> جدول المستخدمين:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5703_7">
<span class="pln">$factory</span><span class="pun">-&gt;</span><span class="pln">define</span><span class="pun">(</span><span class="typ">App</span><span class="pln">\User</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="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">email</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"> bcrypt</span><span class="pun">(</span><span class="pln">str_random</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)),</span><span class="pln">
        </span><span class="str">'remember_token'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> str_random</span><span class="pun">(</span><span class="lit">10</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
</span><span class="pun">});</span></pre>

<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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/" rel="">Faker</a> عبر المتغيّر <code>faker$</code>. يجب تنفيذ التهجيرات المبدئية التي تأتي مع Laravel لإنشاء الجداول في قاعدة البيانات حتى يمكن إدراج تسجيلات فيها.
</p>

<p>
	سنعلّق الدّالة السابقة ونضيف دالة جديدة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1032_7">
<span class="pln">$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="pln">$faker</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">'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="pun">];</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تستدعي الشفرة السابقة مكتبة <code>faker$</code> لتوليد كلمة <code>word</code> لإدراجها في حقل <code>widget_name</code>، نطلُب من المكتبة التأكد أن الكلمة وحيدة <code>uniq</code> لنوافق القيد الموجود على حقل الاسم في الجدول.
</p>

<p>
	بقيت لنا خطوة قبل بذر الجدول باستخدام أمر <code>artisan</code>. ننتقل إلى المجلّد <code>database/seeds</code>، نفتح الملف <code>DatabaseSeeder.php</code> ونعدّله ليصبح كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1032_9">
<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">Illuminate</span><span class="pln">\Database\Eloquent\Model</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">\Widget</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DatabaseSeeder</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="com">/**
    * Run the database seeds.
    *
    * @return void
    */</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </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="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="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>unguard</code> على تعطيل الحماية مؤقّتا على النموذج لحين إدراج التسجيلات، بينما تعيد دالة <code>reguard</code> تفعيلها. تعمل الدّالة <code>truncate</code> على حذف جميع التسجيلات في الجدول لتهيئة عمليّة البذر. نطلُب داخل دالة <code>factory</code> إدراج 50 تسجيلة في جدول النموذج المذكور <code>Widget</code>.
</p>

<p>
	نحن الآن جاهزون لتنفيذ أمر البذر:
</p>

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

<p>
	الأمر سهل للغاية. يمكنك إن أردت التراجع بنفس السهولة عن الأمر وحذف التسجيلات المدرجة بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1032_13">
<span class="pln">php artisan migrate</span><span class="pun">:</span><span class="pln">rollback</span></pre>

<h2 id="الطريقة-الثانية-استخدام-الاختبارات">
	الطريقة الثانية: استخدام الاختبارات
</h2>

<p>
	توجد طريقة أخرى غير السابقة لإدراج بيانات وهميّة في جدول بيانات. إن لم تكن لديك فكرة عن التّطوير الموجَّه بالاختبارات Test-driven development, TDD فيمكنك أخذ فكرة عن الأساسيات في مقال <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="">كيف تستخدم PHPUnit لاختبار تطبيقات Laravel</a>. سيكون من الجيّد لك التعوّد على استخدام الاختبارات في أعمال التطوير، خصوصا أن Laravel يسهّل الأمر كثيرا.
</p>

<p>
	نبدأ بالانتقال إلى ملفّ <code>tests/ExampleTest.php</code> ثم ننشئ نسخة منه باسم <code>WidgetTest.php</code> ونعدّلها لتصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1032_15">
<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">\Foundation\Testing\WithoutMiddleware</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\Testing\DatabaseMigrations</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\Testing\DatabaseTransactions</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">\Widget</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">WidgetTest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">TestCase</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">DatabaseTransactions</span><span class="pun">;</span><span class="pln">

</span><span class="com">/**
    * A basic functional test example.
    *
    * @return void
    */</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testWidgetFactory</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"> 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">
    dd</span><span class="pun">(</span><span class="pln">$widgets</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_1032_17">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">DatabaseTransactions</span><span class="pun">;</span></pre>

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

<p>
	يؤدي استخدام الدالة <code>dd</code> إلى طباعة محتوى النماذج في الطرفيّة عند نجاح الاختبار:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1032_19">
<span class="pln">dd</span><span class="pun">(</span><span class="pln">$widgets</span><span class="pun">);</span></pre>

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

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1032_21">
<span class="pln">php artisan migrate</span><span class="pun">:</span><span class="pln">rollback</span></pre>

<p>
	ثم نعيد تنفيذ التهجير لإنشاء الجدول من جديد:
</p>

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

<p>
	نحن الآن جاهزون لتنفيذ الاختبار: 
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1032_25">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">phpunit tests</span><span class="pun">/</span><span class="typ">WidgetTest</span><span class="pun">.</span><span class="pln">php </span></pre>

<p>
	أو إن كان مسار PHPUnit مختلفا كما ذكرنا في درس <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="">كيف تستخدم PHPUnit لاختبار تطبيقات Laravel</a>: 
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1032_27">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">phpunit</span><span class="pun">/</span><span class="pln">phpunit</span><span class="pun">/</span><span class="pln">phpunit tests</span><span class="pun">/</span><span class="typ">WidgetTest</span><span class="pun">.</span><span class="pln">php </span></pre>

<p>
	إن كنت ترغب في إبقاء بيانات الاختبار في الجدول فيمكنك تعليق استخدام الصنف التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1032_29">
<span class="com">// use DatabaseTransactions;</span></pre>

<p>
	يمكن أن تظهر أخطاء عند إعادة تنفيذ الاختبار بعد إبقاء بيانات الاختبار السابق في جدول البيانات. يعود السبب في ذلك إلى أن مكتبة Faker لا تعرف مالذي يوجد في جدول البيانات وبالتالي يمكن أن تولّد بيانات لا تحترم شرط عدم التكرار في محتوى الحقل <code>widget_name</code>. توجد خيارات عدّة لتجاوز هذا الأمر، إما بإرجاع التهجير لحذف الجدول ثم تنفيذ التهجير مرة أخرى لإنشاء الجدول من جديد وبعدها ينفَّذ الاختبار؛ أو استخدام دالة <code>truncate</code> لحذف التسجيلات من الجدول قبل توليد تسجيلات جديدة. في كلتا الحالتين تُفقَد البيانات السابقة على تنفيذ الاختبار.
</p>

<p>
	ترجمة -وبتصرّف- لمقال <a href="https://laraveltips.wordpress.com/2015/08/14/using-model-factory-to-make-test-data-in-laravel-5-1/" rel="external nofollow">Using Model Factory to make Test Data in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">298</guid><pubDate>Sun, 17 Apr 2016 09:27:25 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x646;&#x634;&#x626; &#x646;&#x645;&#x648;&#x630;&#x62C;&#x627; (Model) &#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%86%D9%85%D9%88%D8%B0%D8%AC%D8%A7-model-%D9%81%D9%8A-laravel-r297/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_04/laravel-models.png.429319dddb2caba1763b3690a89db12c.png" /></p>

<p>
	يقدّم هذا الدرس كيفية إنشاء نموذج Model قاعدي في Laravel ومن ثم استخدامه. النماذج هي الجزء من <a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218#%D8%A8%D9%86%D9%8A%D8%A9-mvc" rel="">بنية MVC</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#%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="">تثبيت Laravel وإعداده</a> مع قاعدة البيانات.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="15035" data-unique="tyqtsws0n" src="https://academy.hsoub.com/uploads/monthly_2016_04/laravel-models.png.78df19d49f51a6b428393bf89fd6f0eb.png" alt="laravel-models.png"></p>

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

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

<p>
	سمّينا النموذج بـ<code>Widget</code> وأضفنا خيار <code>m-</code> لإنشاء <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>

<p>
	ستجد بعد اكتمال تنفيذ الأمر ملفا باسم <code>Widget.php</code> في مجلّد <code>app</code> المتفرّع عن مجلّد المشروع، وملفًّا للتهجير في المجلّد <code>database/migrations</code>. يظهر اسما الملفّيْن في مخرجات تنفيذ الأمر السّابق. نفتح ملفّ <code>Widget.php</code> للنظر في محتواه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9742_9">
<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">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="pun">}</span></pre>

<p>
	هذا كلّ ما يوجد الملف! هيكل نموذج يمكننا الاستفادة منه لإنشاء ما نريد.
</p>

<p>
	بالانتقال إلى مجلّد <code>database/migrations</code> نجد ملفًّا يشبه التالي:
</p>

<pre class="ipsCode" id="ips_uid_9742_11">
2016_03_19_163722_create_widgets_table.php</pre>

<p>
	يظهر في بداية اسم الملف ختم زمني بتاريخ إنشائه. يفترض Laravel أن اسم النموذج كلمة مفردة (<code>Widget</code> مثلا) تبدأ بحرف كبير Uppercase، في حين يتوقّع أن يكون اسم الجدول Table جمعًا (<code>widgets</code>) يبدأ بحرف صغير. يمكن تفسير الأمر بأن النموذج يُرجِع نظيرا واحدا لتسجيلات الجدول.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9742_13">
<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">CreateWidgetsTable</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">'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="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">'widgets'</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>id</code> ويجعله يتقدّم تلقائيا فور إدراج تسجيلة جديدة في الجدول (<code>autoincrement</code>) وذلك باستخدام الدّالة <code>increments</code>. يضيف Laravel كذلك ختمين زمنيّين لتاريخَيْ إنشاء التسجيلة وتحديثها <code>timestamps</code>.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9742_15">
<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></pre>

<p>
	يضيف السّطر أعلاه عمودا جديدا للجدول باسم <code>widget_name</code> من نوع <code>string</code> ويقيّده بـ<code>unique</code> لكي لا توجد تسجيلتان في الجدول بنفس الاسم. تصبح دالّة <code>up</code> في ملف التهجير بعد إضافة العمود على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9742_17">
<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>
	ثم ننفّذ التهجير:
</p>

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

<p>
	ستلاحظ بعد تنفيذ الأمر إنشاءَ جدول جديد في قاعدة البيانات لديك.
</p>

<p>
	بما أننا نخطّط لإدراج تسجيلات إلى قاعدة البيانات بالتطبيق فيجب أن نضيف الخاصيّة التالية إلى النموذج <code>Widget</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4210_7">
<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">'widget_name'</span><span class="pun">];</span></pre>

<p>
	تخبر هذه التعليمة Laravel أن العمود <code>widget_name</code> يدعم الإسناد الشّامل Mass assignment (تحديد قيم معطياتٍ عدّةٍ مرة واحدة). إن لم نضف هذه التعليمة فلن يمكننا باستخدام التطبيق إدراجُ تسجيلات جديدة في الجدول.
</p>

<p>
	سنستخدم في الدرس التالي النموذج الذي أنشأناه أعلاه مع معمل النماذج Model factory في Laravel لملْء تسجيلات في جدول <code>widgets</code>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://laraveltips.wordpress.com/2015/08/14/how-to-make-a-model-in-laravel-5-1/" rel="external nofollow">How to Make a Model in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">297</guid><pubDate>Thu, 14 Apr 2016 23:25:06 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; PHPUnit &#x644;&#x627;&#x62E;&#x62A;&#x628;&#x627;&#x631; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; 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-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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_04/phpunit-laravel-tests.png.638e5b99f164a3dd161d417e1558bcb2.png" /></p>

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

<p style="text-align: center;">
	<img alt="phpunit-laravel-tests.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14879" data-unique="4pqo1hnai" src="https://academy.hsoub.com/uploads/monthly_2016_04/phpunit-laravel-tests.png.3449f224d69d6b738acb9a61f274b874.png"></p>

<p>
	يمكنك التأكّد من ذلك بالدخول إلى مجلّد المشروع ثم تنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_9">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">phpunit </span><span class="pun">--</span><span class="pln">version</span></pre>

<p>
	قد تظهر لك مشكلة في اعتمادات Composer إلا أنه يمكن تجاوزها بتنفيذ الأمر على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_12">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">phpunit</span><span class="pun">/</span><span class="pln">phpunit</span><span class="pun">/</span><span class="pln">phpunit </span><span class="pun">--</span><span class="pln">version </span></pre>

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

<pre class="ipsCode" id="ips_uid_5335_14">
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
</pre>

<p>
	استخدم الأمر الصحيح من بين الأمريْن أعلاه في بقية هذا الدرس.
</p>

<p>
	يأتي Laravel مبدئيّا بمثال لاختبار؛ سننظر في هذا المثال لنرى كيف تعمل اختبارات PHPUnit. افتح الملف <code>ExampleTest.php</code> الموجود في المجلّد <code>tests</code> المتفرّع عن مجلّد المشروع:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5335_16">
<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">\Foundation\Testing\WithoutMiddleware</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\Testing\DatabaseMigrations</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\Testing\DatabaseTransactions</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ExampleTest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">TestCase</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * A basic functional test example.
    *
    * @return void
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testBasicExample</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">visit</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">see</span><span class="pun">(</span><span class="str">'Laravel 5'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا تجربة الاختبار بتنفيذ الأمر التالي الذي ينفّذ جميع الاختبارات الموجودة في الملف <code>tests</code> المذكور أعلاه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_18">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">phpunit</span></pre>

<p>
	يبحث الاختبار أعلاه عن سلسلة المحارف <code>Laravel 5</code> في الصفحة الرئيسية للمشروع التي يشير إليها المسار <code>/</code>. إن كان مشروع Laravel الذي تعمل عليه جديدا فسيظهر سطران كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_5335_20">
Time: 118 ms, Memory: 12.00Mb

OK (1 test, 1 assertion)</pre>

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

<p>
	فلنجرّب إخفاق الاختبار. نستبدل <code>Laravel 6</code> بـ <code>Laravel 5</code> في ملف الاختبار ثم نعيد تنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_22">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">phpunit</span></pre>

<p>
	ستظهر الكثير من المُخرجات تحوي الرسائل التالية إضافة لشفرة الصفحة الرئيسية التي نختبرها:
</p>

<pre class="ipsCode" id="ips_uid_5335_24">
Time: 115 ms, Memory: 12.00Mb

There was 1 failure:

Couldn't find [Laravel 6] on the page. Check content above.

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.</pre>

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

<p>
	إن حصل خطأ في الشفرة المصدرية للاختبار نفسه (نسيت مثلا <code>;</code> في نهاية تعليمة) فلن يُنفَّذ الاختبار وستظهر رسالة بما حدث.
</p>

<h2 id="اختبار-استمارة-form-لتسجيل-مستخدم">
	اختبار استمارة Form تسجيل مستخدم
</h2>

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

<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="">Artisan</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> Views التسجيل، الدخول وإعادة تعيين كلمة السر بالإضافة إلى المتحكّمات Controllers و<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 الضرورية):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_26">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">auth</span></pre>

<p>
	ينشئ الأمر السابق عرضا على المسار <code>register/</code> به استمارة لتسجيل مستخدم جديد. سنستخدم PHPUnit لاختبار هذه الاستمارة. نستعين بأداة Artisan من جديد لإنشاء ملف للاختبار:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_28">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">test </span><span class="typ">RegistrationTest</span></pre>

<p>
	<strong>ملحوظة</strong>: تأكّد من <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%A5%D8%B9%D8%AF%D8%A7%D8%AF-%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" rel="">إعداد قاعدة البيانات</a> في مشروعك.
</p>

<p>
	ينشئ الأمر ملفا باسم <code>RegistrationTest.php</code> في المجلّد <code>tests</code>. نفتح الملف ونعدّله على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5335_30">
<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">\Foundation\Testing\WithoutMiddleware</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\Testing\DatabaseMigrations</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\Testing\DatabaseTransactions</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">RegistrationTest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">TestCase</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">DatabaseTransactions</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"> testNewUserRegistration</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">visit</span><span class="pun">(</span><span class="str">'/register'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">type</span><span class="pun">(</span><span class="str">'bob'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'name'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">type</span><span class="pun">(</span><span class="str">'hello1@in.com'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'email'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">type</span><span class="pun">(</span><span class="str">'hello1'</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">-&gt;</span><span class="pln">type</span><span class="pun">(</span><span class="str">'hello1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'password_confirmation'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">press</span><span class="pun">(</span><span class="str">'Register'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">seePageIs</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

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

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

<p>
	نستخدم الطّابع <code>DatabaseTransactions</code> Trait في الاختبار. يمكّننا هذا الطّابع من إلغاء إدراج تسجيلات جديدة في قاعدة البيانات حتى لا نملأها من غير جدوى. كما نستخدم الطّابع <code>DatabaseMigrations</code> للتراجع عن <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> Migrations وبالتالي حذف الجدول من قاعدة البيانات. الطابع الثالث المستخدم في الاختبار هو طابع <code>WithoutMiddleware </code>الذي يسمح بتخطّي بعض إجراءات الحماية لأغراض الاختبار.
</p>

<p>
	يمكننا الآن تنفيذ الاختبار كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5335_32">
<span class="pln">vendor</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">phpunit tests</span><span class="pun">/</span><span class="typ">RegistrationTest</span><span class="pun">.</span><span class="pln">php</span></pre>

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

<pre class="ipsCode" id="ips_uid_5335_34">
Time: 401 ms, Memory: 16.50Mb

OK (1 test, 5 assertions)</pre>

<p>
	يمكنك قراءة المزيد عن الاختبارات على موقع PHPUnit؛ فقط تذكّر أن الصنف الذي نمدّده في Laravel هو <code>TestCase</code> بدلا من <code>PHPUnit_Framework_TestCase</code> في تطبيقات PHP أخرى.
</p>

<p>
	ترجمة -وبتصرّف- لمقال <a href="https://laraveltips.wordpress.com/2015/06/12/how-use-phpunit-test-in-laravel-5-1/" rel="external nofollow">How Use PHPUnit Test in Laravel 5.1</a> لصاحبه Bill Keck.
</p>
]]></description><guid isPermaLink="false">296</guid><pubDate>Sat, 09 Apr 2016 22:42:00 +0000</pubDate></item><item><title>&#x62A;&#x633;&#x62C;&#x64A;&#x644; &#x627;&#x644;&#x62F;&#x62E;&#x648;&#x644; &#x639;&#x628;&#x631; &#x627;&#x644;&#x634;&#x628;&#x643;&#x627;&#x62A; &#x627;&#x644;&#x627;&#x62C;&#x62A;&#x645;&#x627;&#x639;&#x64A;&#x629; &#x641;&#x64A; Laravel &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Socialite</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AC%D8%AA%D9%85%D8%A7%D8%B9%D9%8A%D8%A9-%D9%81%D9%8A-laravel-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-socialite-r275/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_02/social-login-laravel.png.b793e35c7e422d58eda4326eccb7cbff.png" /></p>

<div id="wmd-preview-section-10">
	<p id="تسجيل-الدخول-عبر-الشبكات-الاجتماعية-في-laravel-باستخدام-socialite">
		في هذا الدرس سنتعرف على طريقة إضافة زر يسمح للمستخدم بالدخول إلى تطبيق الويب المكتوب بإطار العمل Laravel دون الحاجة للمرور بخطوة إنشاء حساب يدوياً.
	</p>

	<p style="text-align: center;">
		<img alt="social-login-laravel.png.b2b91d07dbfe69f" class="ipsImage ipsImage_thumbnailed" data-fileid="12699" data-unique="ixlhpjr4f" src="https://academy.hsoub.com/uploads/monthly_2016_02/social-login-laravel.png.b2b91d07dbfe69fa2af7c57808a60294.png"></p>

	<p>
		سنعتمد في شرحنا هذا على إطار العمل Laravel 5.2 وسوف نأخذ فيس بوك كمثال عن شبكة اجتماعية للسماح لمستخدمي تطبيقنا بالدخول عبرها. لكن يمكنك تطبيق الخطوات نفسها المشروحة في هذا الدرس لإنشاء زر دخول عبر تويتر أو GitHub أو Google أو Bitbucket أو LinkedIn.
	</p>

	<p>
		تم اختبار خطوات هذا الدرس على Laravel 5.1 وأيضاً 5.2.
	</p>
</div>

<div id="wmd-preview-section-11">
	<h2 id="مبدأ-الدخول-عبر-الشبكات-الاجتماعية">
		مبدأ الدخول عبر الشبكات الاجتماعية
	</h2>

	<p>
		الغالب أنك تعرف خطوات الدخول إلى المواقع باستخدام حسابك على فيس بوك أو تويتر، فالعديد من المواقع والتطبيقات توفر ميزة الدخول عبر الشبكات الاجتماعية لتسريع عملية الدخول إلى التطبيق بدلاً من الطلب من المستخدم إنشاء حساب جديد يدوياً. ومع ذلك دعنا نسرد هذه الخطوات سريعاً:
	</p>

	<ul><li>
			عندما تريد الدخول إلى موقع يحتاج لتسجيل الدخول يعرض لك استمارة الدخول؛
		</li>
		<li>
			تجد ضمن الاستمارة السابقة زر "دخول عبر فيس بوك" (أو شبكة اجتماعية أخرى)؛
		</li>
		<li>
			عند النقر على هذا الزر تنتقل إلى موقع فيس بوك (أو تفتح نافذة جديدة صغيرة للمتصفح ويفتح موقع فيس بوك داخلها)؛
		</li>
		<li>
			يطلب منك فيس بوك منح صلاحيات مُحدّدة للتطبيق الخاص بالموقع (مثلاً السماح للتطبيق بالاطلاع على معلوماتك الشخصية العامة أو بريدك الإلكتروني) بعد الموافقة يعاد توجيهك إلى الموقع الأصلي وتجد نفسك قد دخلت إلى الموقع وكأنك تملك حساب.
		</li>
	</ul><p>
		الفكرة هي أن فيس بوك يمرر للموقع الآخر معلومات معينة عن حسابك بحيث يتمكن هذا الموقع من إنشاء حساب لك دون الحاجة لتعبئة أي معلومات يدوياً، كما ويمكن استخدام هذه المعلومات في عمليات الدخول اللاحقة للتعرف عليك والسماح لك بالوصول إلى حسابك نفسه (وليس إنشاء حساب جديد مرة أخرى!) دون أن تكتب كلمة سر للدخول.
	</p>

	<p>
		تبادل المعلومات هذا بين المواقع له معايير. المعيار الأكثر شهرة والذي نعتمد عليه في هذا المقال هو معيار OAuth بنسختيه 1.0 و2.0.
	</p>
</div>

<div id="wmd-preview-section-12">
	<h2 id="بيئة-العمل">
		بيئة العمل
	</h2>

	<p>
		سنفترض أن لديك تطبيق Laravel 5.1 سابق، وتريد إضافة ميزة الدخول عبر الشبكات الاجتماعية إليه.
	</p>

	<p>
		إذا لم يكن إطار العمل Laravel مثبتاً لديك راجع درس تثبيت 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/">تثبيت Laravel وإعداده على ويندوز وأوبنتو</a>.
	</p>

	<p>
		بالنسبة لي أستخدم نظام ويندوز مع XAMPP للعمل، لكن يمكنك تطبيق الخطوات على لينكس أو أي نظام تشغيل آخر بالطبع. 
	</p>

	<p>
		سنحتاج أيضاً لتثبيت Socialite، وهي حزمة تسهل علينا عملية الاستيثاق عبر بروتوكول OAuth كثيراً. لتثبيت Socialite أضف السطر التالي إلى ملف <span style="font-family:courier new,courier,monospace;">composer.json</span> في مشروع Laravel الخاص بك:
	</p>
</div>

<div id="wmd-preview-section-13">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2661_7">
<span class="str">"require"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
    </span><span class="str">"laravel/socialite"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"~2.0"</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		أو بدلاً من ذلك يمكنك استخدام الأمر:
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9897_7">
<span class="pln">composer require laravel/socialite</span></pre>

	<p>
		بعد ذلك نفذ الأمر التالي لتنزيل الملفات المطلوبة:
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9897_9">
<span class="pln"> composer update </span></pre>

	<p>
		بعد انتهاء عملية التنزيل، عليك تعديل ملف الضبط <span style="font-family:courier new,courier,monospace;">config/app.php</span> وإضافة السطر التالي إلى مصفوفة Service Providers (اسمها <span style="font-family:courier new,courier,monospace;">providers</span> ضمن الملف):
	</p>
</div>

<div id="wmd-preview-section-14">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9897_11">
<span class="pln">Laravel\Socialite\SocialiteServiceProvider::class,</span></pre>

	<p>
		والسطر التالي إلى مصفوفة <span style="font-family:courier new,courier,monospace;">Aliases</span>:
	</p>
</div>

<div id="wmd-preview-section-15">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9897_13">
<span class="pln">'Socialite' =&gt; Laravel\Socialite\Facades\Socialite::class,</span></pre>

	<p>
		الآن أصبح موقعك جاهزًا للتعامل مع الشبكات الاجتماعية. كما ذكرنا في بداية هذا الدرس هذه الطريقة تعمل مع العديد من الشبكات الاجتماعية التي توفر ميزة الاستيثاق عبر OAuth، إذ أن حزمة Socialite تدعم ست شبكات اجتماعية حالياً (فيس بوك وتويتر ولينكدإن و Google وGitHub وBitbucket).
	</p>
</div>

<div id="wmd-preview-section-16">
	<h2 id="الخطوة-الأولى-إنشاء-مسارات-التوجيه">
		الخطوة الأولى: إنشاء مسارات التوجيه
	</h2>

	<p>
		سنحتاج في عملية الدخول هذه إلى استدعائين:
	</p>

	<ol><li>
			عندما يطلب المستخدم الدخول إلى الموقع، وهنا سوف نحوله إلى موقع فيس بوك للموافقة على منح الصلاحيات لتطبيقنا.
		</li>
		<li>
			بعد أن يوافق المستخدم على منح الصلاحيات للتطبيق سيقوم فيس بوك بإعادة توجيه المستخدم إلى موقعنا لإتمام عملية الدخول. 
		</li>
	</ol><p>
		بالنسبة لي فقد اخترت أن يكون هذان الاستدعائان على مسار واحد (ولكن يمكنك فصلهما إلى مسارين)، واخترت أن يكون المسار هو <span style="font-family:courier new,courier,monospace;">auth/facebook</span>. لقد أضفت السطر التالي إلى ملف <span style="font-family:courier new,courier,monospace;">routes.php</span> لدي:
	</p>
</div>

<div id="wmd-preview-section-17">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9897_15">
<span class="pln">Route::get('auth/facebook', 'SocialAuthController@facebookLogin');</span></pre>

	<p>
		كما تلاحظ فقد طلبت استخدام المتحكم <span style="font-family:courier new,courier,monospace;">SocialAuthController</span> لمعالجة الطلبات الواردة إلى هذا المسار. 
	</p>

	<p>
		هذا المتحكم عبارة عن مُتحكّم Controller عادي يرث من الصف<span style="font-family:courier new,courier,monospace;"> App\Http\Controllers\Controller</span>:
	</p>
</div>

<div id="wmd-preview-section-18">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9897_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">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SocialAuthController</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></pre>

	<p>
		الآن دعنا نعرف الدالة <span style="font-family:courier new,courier,monospace;">facebookLogin</span>. ما الذي نريد أن يحدث عندما يصل المستخدم إلى المسار<span style="font-family:courier new,courier,monospace;"> auth/facebook</span>؟ في الواقع نحن نريد إضافة زر دخول عبر فيس بوك، وهذا الزر سيوجه المستخدم إلى هذا المسار وهنا نريد أن ينتقل المستخدم إلى موقع فيس بوك ليمنح تطبيقنا الصلاحيات اللازمة.
	</p>

	<p>
		تعليمة توجيه المستخدم إلى فيس بوك هي التالية، فقط أضفها ضمن دالة <span style="font-family:courier new,courier,monospace;">facebookLogin</span>:
	</p>
</div>

<div id="wmd-preview-section-19">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9897_19">
<span class="kwd">return</span><span class="pln"> </span><span class="typ">Socialite</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'facebook'</span><span class="pun">)-&gt;</span><span class="pln">redirect</span><span class="pun">();</span></pre>

	<p>
		طبعاً ستحتاج عدد من التعديلات قبل أن تعمل هذه التعليمة عندك:
	</p>

	<ul><li>
			<p>
				عليك التأكد من تضمين Socialite في ترويسة الصف:
			</p>
		</li>
	</ul><pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9897_25">
<span class="pln">use Laravel\Socialite\Facades\Socialite;</span></pre>

	<ul><li>
			أين هو تطبيق الفيس بوك الخاص بك؟ عليك إنشاؤه الآن أو التوجه إلى صفحة إعدادات التطبيق الخاص بك إذا كنت تملك تطبيقاً بالفعل. لإنشاء تطبيق جديد أو إدارة تطبيقاتك السابقة على فيس بوك توجه إلى المسار التالي: <a href="https://developers.facebook.com/apps" rel="external nofollow">https://developers.facebook.com/apps</a> على موقع فيس بوك عليك العثور على خيار Callback Url واستخدام نفس المسار المحلي الذي اخترته، انظر كيف كانت القيمة لدي: 
		</li>
	</ul><p style="text-align: center;">
		<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_02/callback-url.png.83c09f0b0455b2fa205b3b01abbd9675.png"><img alt="callback-url.thumb.png.8492bec6a67a11a24" class="ipsImage ipsImage_thumbnailed" data-fileid="12700" data-unique="0lvwtqijw" src="https://academy.hsoub.com/uploads/monthly_2016_02/callback-url.thumb.png.8492bec6a67a11a24dadb94fb59afac9.png"></a>
	</p>

	<ul><li>
			من موقع فيس بوك عليك العثور على معلومات تطبيقك: نحتاج للحصول على معرف التطبيق (Client ID) وأيضاً الجملة السرية (Client Secret).
		</li>
		<li>
			الآن اذهب إلى <span style="font-family:courier new,courier,monospace;">config/services.php</span> وأضف ما يلي إلى الملف:
		</li>
	</ul></div>

<div id="wmd-preview-section-20">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9897_27">
<span class="str">'facebook'</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">'client_id'</span><span class="pln">     </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'معرف التطبيق الذي حصلت عليه من فيس بوك'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'client_secret'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'الجملة السرية الخاصة بتطبيقك على فيس بوك'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'redirect'</span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'رابط التحويل الذي سيتجه إليه المستخدم بعد منح الصلاحيات اللازمة على فيس بوك'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">],</span></pre>

	<blockquote>
		<p>
			<strong>تحذير:</strong> لا تستخدم الدالة المساعدة <span style="font-family:courier new,courier,monospace;">url</span> ضمن ملف <span style="font-family:courier new,courier,monospace;">services.php</span>. هذا يؤدي لتوقف أداة artisan عن العمل.
		</p>
	</blockquote>

	<p>
		يمكنك بدلاً من كتابة المتغيرات السابقة ضمن ملف services أن تستخدم السطور التالية وبعدها تعرف المتغيرات ضمن ملف <span style="font-family:courier new,courier,monospace;">env.</span> لديك:
	</p>
</div>

<div id="wmd-preview-section-21">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_41">
<span class="str">'facebook'</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">'client_id'</span><span class="pln">     </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'FACEBOOK_CLIENT_ID'</span><span class="pun">),</span><span class="pln">
    </span><span class="str">'client_secret'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'FACEBOOK_CLIENT_SECRET'</span><span class="pun">),</span><span class="pln">
    </span><span class="str">'redirect'</span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'FACEBOOK_REDIRECT_URL'</span><span class="pun">),</span><span class="pln">
</span><span class="pun">],</span></pre>

	<p>
		الميزة هنا هي أن ملف services يضاف غالباً إلى مستودع التّطبيق، بينما ملف.env يبقى على الجهاز المحلي وهذا يفيد إذا لم تكن تريد السماح للمطورين الآخرين بالإطلاع على هذه المعلومات لسبب ما.
	</p>

	<p>
		بالنسبة لي فقد اخترت أيضاً نقل قيمة <span style="font-family:courier new,courier,monospace;">redirect</span> إلى ملف <span style="font-family:courier new,courier,monospace;">env.</span> لأن هذا الرابط سيتغير حتماً ما بين بيئة التطوير وبيئة الإنتاج (Production)، وبالتالي من المفيد وضعه مع بقية الإعدادات الخاصة بكل بيئة.
	</p>

	<p>
		الآن إذا حاولت الوصول إلى الرابط <span style="font-family:courier new,courier,monospace;">auth/facebook</span> يجب أن تنتقل إلى موقع فيس بوك ويطلب منك الموافقة على منح الصلاحيات لتطبيقك هناك:
	</p>

	<p style="text-align: center;">
		<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_02/app-authorization.png.32742b9356868508b268002e212bc355.png"><img alt="app-authorization.thumb.png.fa2cadbc87f6" class="ipsImage ipsImage_thumbnailed" data-fileid="12701" data-unique="dykjk9wib" src="https://academy.hsoub.com/uploads/monthly_2016_02/app-authorization.thumb.png.fa2cadbc87f67193f2fa609663a3a752.png"></a>
	</p>

	<p>
		بعد الموافقة، ستجد غالباً أن متصفح الوب لديك سيعطيك خطأ ويشتكي أن الصفحة فيها مشكلة في إعادة التوجيه. 
	</p>

	<p>
		لا تقلق، أنت على الطريق الصحيح.
	</p>

	<p>
		ما الذي حدث؟ عندما طلب المستخدم المسار <span style="font-family:courier new,courier,monospace;">auth/facebook</span> تحول إلى موقع فيس بوك ووافق على منح الصلاحيات، بعدها أعاد فيس بوك توجيهه إلى موقعنا على نفس المسار ولكن هذه المرة هناك متغيرات مع الطلب.
	</p>

	<p>
		المشكلة هنا هي أن موقعنا لا يعالج عملية استقبال المستخدم بعد عودته من فيس بوك وإنما يعيد توجيهه إلى فيس بوك مرة أخرى والذي يعيد توجيهه إلى موقعنا وهكذا في حلقة لا نهائية. علينا الآن معالجة الحالة التي يصل فيها المستخدم إلى المسار <span style="font-family:courier new,courier,monospace;">auth/facebook</span> ومعه المتغيرات اللازمة للسماح له بالدخول.
	</p>
</div>

<div id="wmd-preview-section-22">
	<h2 id="الخطوة-الثانية-التعرف-على-المستخدم">
		الخطوة الثانية: التعرف على المستخدم
	</h2>

	<p>
		دعنا نعدل دالة <span style="font-family:courier new,courier,monospace;">facebookLogin</span> لتصبح كالتالي:
	</p>
</div>

<div id="wmd-preview-section-23">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_31">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> facebookLogin</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">if</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">has</span><span class="pun">(</span><span class="str">'code'</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">Socialite</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'facebook'</span><span class="pun">)-&gt;</span><span class="pln">redirect</span><span class="pun">();</span><span class="pln">

  </span><span class="com">// وإلا علينا التعرف على المستخدم وتسجيل دخوله إلى الموقع</span><span class="pln">
  $oauthUser </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Socialite</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'facebook'</span><span class="pun">)-&gt;</span><span class="pln">user</span><span class="pun">();</span><span class="pln">
  dd</span><span class="pun">(</span><span class="pln">$oauthUser</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

	<p>
		حالياً إذا نجحت في الخطوات السابقة يجب أن تطبع لديك كافة معلومات المستخدم الذي حصلنا عليها من فيس بوك. 
	</p>

	<p>
		تهانينا! لم يبق إلا البحث في قاعدة بيانات موقعنا لنرى إذا كان المستخدم موجوداً من قبل أم لا؛ فإذا عثرنا عليه سمحنا له بالدخول، وإلا فسوف ننشئ حساباً جديداً له ونسمح له بالدخول على حسابه الجديد.
	</p>

	<p>
		هناك حقول كثيرة يعطينا إياها فيس بوك، وهذه الحقول قد تختلف في الواقع بين شبكة اجتماعبة وأخرى، لكن هناك حقول ثابتة دوماً:
	</p>

	<ul><li>
			<strong>id:</strong> رقم تعريف المستخدم لدى فيس بوك. ثابت دوماً ولا يتغير ولذلك سنعتمد عليه في التعرف على المستخدم.
		</li>
		<li>
			<strong>name:</strong> اسم المستخدم الحقيقي (وليس username). قد يتغير إذا غيره المستخدم على موقع فيس بوك.
		</li>
		<li>
			<strong>nickname:</strong> لقب المستخدم. فيس بوك يعيد null هنا حسب ما لاحظت، ولكن تويتر يعطي قيمة username.
		</li>
		<li>
			<strong>avatar</strong> و<strong> avatar_original</strong>: رابط صورة حساب المستخدم. عادة تكون صورة original أكبر حجماً.
		</li>
		<li>
			<strong>email</strong>: البريد الإلكتروني للمستخدم. لاحظ أنه قد تحصل على قيمة البريد الإلكتروني للمستخدم وقد تحصل على قيمة null، ولذلك لا يمكنك الاعتماد على البريد الإلكتروني لمعرفة المستخدم إذا كان جديداً أو مستخدمًا سابقًا لموقعك. السبب هو أن بعض الشبكات الاجتماعية مثل فيس بوك تسمح للمستخدم بالتسجيل عبر رقم الهاتف وقد لا يملك فيس بوك عنوان البريد الإلكتروني للمستخدم، أو قد يختار المستخدم عدم الإفصاح عن عنوان بريده الإلكتروني لتطبيقك أثناء مرحلة اختيار الصلاحيات ومنحها للتطبيق.
		</li>
	</ul><p>
		عليك الآن التعديل على قاعدة البيانات الخاصة بالموقع وإضافة عمود اسمه<span style="font-family:courier new,courier,monospace;"> facebook_id</span> إلى جدول المستخدمين، سيكون الحقل unique ويسمح بقيم null (لأن هناك مستخدمين قد يستخدمون عملية التسجيل التقليدية للدخول وبالتالي لا يملك النظام معرف حسابهم على فيس بوك).
	</p>

	<p>
		الآن نعود إلى دالة <span style="font-family:courier new,courier,monospace;">facebookLogin</span> وبدلاً من تعليمة <span style="font-family:courier new,courier,monospace;">dd</span> سنضع السطور التالية:
	</p>
</div>

<div id="wmd-preview-section-24">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_35">
<span class="pln">$user </span><span class="pun">=</span><span class="pln">  $this</span><span class="pun">-&gt;</span><span class="pln">findOrCreateUser</span><span class="pun">(</span><span class="pln">$oauthUser</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Auth</span><span class="pun">::</span><span class="pln">login</span><span class="pun">(</span><span class="pln">$user</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">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'home'</span><span class="pun">);</span></pre>

	<p>
		ما فعلناه هو استدعاء دالة ضمن الصف نفسه هي دالة <span style="font-family:courier new,courier,monospace;">findOrCreateUser</span> تأخذ معلومات حساب المستخدم على فيس بوك وتعيد لنا كائنًا من نموذج User ‏(User Model)، الذي استدعينا عليه دالة<span style="font-family:courier new,courier,monospace;"> Auth::login</span> لتسجيل دخوله في الجلسة الحالية ومررنا قيمة true كمتغير ثان حتى نتذكر المستخدم (remember me).
	</p>

	<p>
		أما عن دالة <span style="font-family:courier new,courier,monospace;">findOrCreateUser</span> فهي كما يلي:
	</p>
</div>

<div id="wmd-preview-section-25">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_37">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> findOrCreateUser</span><span class="pun">(</span><span class="pln">$oauthUser</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">User</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'facebook_id'</span><span class="pun">,</span><span class="pln"> $oauthUser</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">)-&gt;</span><span class="pln">first</span><span class="pun">())</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $user</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</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"> $oauthUser</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"> $oauthUser</span><span class="pun">-&gt;</span><span class="pln">email</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'facebook_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $oauthUser</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>
		دالة بسيطة جدًا، تبحث عن المستخدم ضمن جدول المستخدمين اعتمادًا على رقم تعريف حسابه لدى فيس بوك، وإذا لم تعثر عليه تنشئ مستخدمًا جديدًا بالاعتماد على المعلومات التي حصلنا عليها من فيس بوك.
	</p>

	<p>
		لا تنس التعديل على<span style="font-family:courier new,courier,monospace;"> User.php</span> بما يناسب. إذا استخدمت دالة إنشاء المستخدم هذه ستحتاج إضافة الحقل<span style="font-family:courier new,courier,monospace;"> facebook_id</span> إلى مصفوفة <span style="font-family:courier new,courier,monospace;">fillable</span>.
	</p>

	<p>
		الآن، يمكنك اختبار العملية بشكل كامل: ضع رابطًا في مكان مناسب يشير إلىauth/facebook وانقر عليه وتابع خطوات عملية التسجيل، في نهاية العملية يجب أن يعاد توجيهك إلى صفحة homeبعد دخولك إلى الموقع.
	</p>
</div>

<div id="wmd-preview-section-26">
	<h2 id="ملاحظات">
		ملاحظات
	</h2>

	<ul><li>
			<p>
				إذا أردت تطبيق هذه الخطوات على تويتر أو أي شبكة أخرى فالعملية نفسها تماماً، عدا أن تويتر يعتمد بروتوكول OAuth 1.0 وليس 2، لذلك عليك فحص وجود متغير اسمه <span style="font-family:courier new,courier,monospace;">oauth_token</span> بدلاً من <span style="font-family:courier new,courier,monospace;">code</span>؛ أما الخطوات الأخرى فلا يوجد أي اختلافات.
			</p>
		</li>
		<li>
			<p>
				إذا أردت تذكّر الصفحة التي طلبها المستخدم قبل ظهور استمارة تسجيل الدخول وتوجيهه إليها بعد الدخول بدلاً من توجيهه إلى <span style="font-family:courier new,courier,monospace;">home</span> في كل مرة، فقط استبدل السطر التالي:
			</p>
		</li>
	</ul><pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_25">
<span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">intended</span><span class="pun">(</span><span class="str">'defaultpage'</span><span class="pun">);</span></pre>

	<p>
		بالسطر القديم:
	</p>

	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_27">
<span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'home'</span><span class="pun">);</span></pre>

	<ul><li>
			لا تقيد نفسك بالطريقة المذكورة هنا، يمكنك إعادة تنظيم الشيفرات السابقة بعدة أساليب. مثلاً يمكنك وضع الدوال السابقة ضمن  متحكم <span style="font-family:courier new,courier,monospace;">Auth\AuthController</span> بدلاً من إنشاء متحكم جديد، أو إنشاء خدمة (Service) ووضعها فيها، الخ.
		</li>
	</ul></div>

<div id="wmd-preview-section-27">
	<h2 id="أخطاء-واجهتني">
		أخطاء واجهتني
	</h2>

	<p>
		أثناء تطبيق هذه الخطوات واجهتني عدة أخطاء سأذكرها هنا مع حلولها.
	</p>
</div>

<div id="wmd-preview-section-28">
	<h3 id="المشكلة-0">
		المشكلة 0
	</h3>
</div>

<div id="wmd-preview-section-29">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1599_8">
<span class="pln">FatalErrorException in AbstractProvider.php line 134:
Call to a member function set() on null</span></pre>

	<p>
		هذه المشكلة ظهرت عندما حاولت تطبيق هذه الخطوات لأول مرة على Laravel 5.2 ولم أنتبه إلى أنني وضعت تعريف المسار <span style="font-family:courier new,courier,monospace;">auth/facebook</span> خارج middleware المسمى "web". هذا يعني أن Session غير متاحة في هذا النطاق، ولذلك واجهني هذا الخطأ.
	</p>

	<p>
		<strong>الحل</strong>: بكل بساطة نقلت تعليمة <span style="font-family:courier new,courier,monospace;">Route</span> إلى داخل مجموعة التوجيه الخاصة بـ web" middleware" كالتالي:
	</p>
</div>

<div id="wmd-preview-section-30">
	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_12">
<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="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">'/auth/facebook'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SocialAuthController@facebookLogin'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

	<h3>
		المشكلة 1
	</h3>
</div>

<div id="wmd-preview-section-32">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1599_14">
<span class="pln">RequestException in CurlFactory.php line 187:
cURL error 60: SSL certificate problem: unable to get local issuer certificate</span></pre>

	<p>
		ما الذي تقوله هذه الرسالة؟! لا يمكن التحقق من شهادة <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> الخاصة بموقع فيس بوك! يا للكارثة شهادة <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> لديهم فيها مشكلة… كيف يمكنني إخبارهم بهذا؟
	</p>

	<p>
		الواقع أنني استغربت ظهور هذه الرسالة عند محاولة الدخول عبر فيس بوك فقط ولم تظهر عند الدخول عبر تويتر. المشكلة هي أن إضافة cURL لدي ليس لديها  معلومات ناشري شهادات <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> حتى تتمكن من التحقق من صلاحية شهادة فيس بوك، وكان الحل بتنزيل هذه المعلومات وتعديل ملف<span style="font-family:courier new,courier,monospace;"> php.ini</span> بحيث تتمكن cURL من قراءة هذه المعلومات والتحقق من شهادة فيس بوك.
	</p>

	<p>
		هناك حل ثان وهو تعطيل خيار التحقق من شهادة <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>، ولكن هذا الحل لا ينصح به.
	</p>

	<p>
		قد لا تواجهك هذه المشكلة، فهي متعلقة بطريقة ضبط php لديك، على أي حال إذا كنت تستخدم XAMPP على ويندوز مثلي وواجهتك هذه المشكلة إليك الطريقة  التي استخدمتها لتجاوزها:
	</p>

	<p>
		أولاً حصلت على ملف <span style="font-family:courier new,courier,monospace;">cacert.pem</span> الذي يحوي معلومات CA (أي Certificate Authorities وهي الهيئات التي تصادق على شهادات <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr> لمواقع الوب) من هذا الرابط: <a href="http://curl.haxx.se/docs/caextract.html" rel="external nofollow">http://curl.haxx.se/docs/caextract.html</a>.
	</p>

	<p>
		بعد ذلك نسخته إلى مجلد <span style="font-family:courier new,courier,monospace;">xampp/php</span> وأخيراً عدلت ملف<span style="font-family:courier new,courier,monospace;"> php.ini</span> وأضفت ما يلي إليه:
	</p>
</div>

<div id="wmd-preview-section-33">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1599_16">
<span class="pln">[cURL] 
curl.cainfo="C:\xampp\php\cacert.pem"</span></pre>

	<p>
		تستخدم cURL هذا المتغير للبحث عن ملف معلومات CA وقراءته، بعد ذلك ستتمكن من التحقق من سلامة شهادة فيس بوك بنجاح وستختفي هذه المشكلة.
	</p>

	<p>
		<strong>تنبيه</strong>: يجب إعادة تشغيل خادوم الوب حتى تأخذ هذه التغييرات مفعولها.
	</p>
</div>

<div id="wmd-preview-section-34">
	<h3 id="المشكلة-2">
		المشكلة 2
	</h3>
</div>

<div id="wmd-preview-section-35">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1599_18">
<span class="pln">InvalidStateException in AbstractProvider.php line 191</span></pre>

	<p>
		وهذه نفسها تعطي أحيانًا رسالة Client Error.
	</p>

	<p>
		تظهر هذه المشكلة إذا استدعيت التعليمة التالية أكثر من مرة في تطبيقك لسبب أو لآخر:
	</p>

	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_20">
<span class="pln"> </span><span class="typ">Socialite</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'facebook'</span><span class="pun">)-&gt;</span><span class="pln">user</span><span class="pun">()</span><span class="pln"> </span></pre>

	<p>
		لا يمكنك استدعاء هذه التعليمة سوى مرة واحدة فقط بعد توجيه المستخدم إلى فيس بوك عبر تعليمة:
	</p>

	<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1599_23">
<span class="typ">Socialite</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'facebook'</span><span class="pun">)-&gt;</span><span class="pln">redirect</span><span class="pun">()</span></pre>

	<p>
		والحصول على كود الدخول.
	</p>

	<p>
		<strong>الحل</strong>: عليك الاحتفاظ بالكائن <span style="font-family:courier new,courier,monospace;">oauthUser$</span> الذي حصلت عليه من هذه التعليمة في متغير وتمريره إلى الدوال الأخرى إذا كنت تحتاجه بدلاً من طلبه كل مرة عبر Socialite.
	</p>
</div>

<div id="wmd-preview-section-36">
	<h3 id="المشكلة-3">
		المشكلة 3
	</h3>

	<p>
		عند إضافة زر "دخول عبر تويتر" استمرت الصفحة في الدخول في حلقة إعادة توجيه لا نهائية رغم فحص وجود المتغير <span style="font-family:courier new,courier,monospace;">code</span> في الطلب. تبين لي بعدها أن تويتر يستخدم النسخة 1.0 من بروتوكول OAuth ولذلك فهو يمرر متغيرات مختلفة.
	</p>

	<p>
		<strong>الحل</strong>: غيرت الشرط بحيث يفحص وجود المتغير <span style="font-family:courier new,courier,monospace;">oauth_token</span> بدلاً من <span style="font-family:courier new,courier,monospace;">code</span>.
	</p>
</div>

<div id="wmd-preview-section-37">
	<h2 id="الختام">
		الختام
	</h2>

	<p>
		في هذا الدرس اطلعنا على حزمة Socialite الخاصة بإطار Laravel التي تسمح بالاستيثاق من هوية المستخدمين بسهولة تامة عبر حساباتهم على الشبكات الاجتماعية.
	</p>

	<p>
		يمكنك تنزيل <a href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=12698">مشروع Laravel المستخدم في هذا الدرس</a> والاطلاع على الشفرة البرمجية فيه.
	</p>

	<p>
		إذا واجهتك مشكلة في تطبيق هذا الدرس فلا تتردد في طرح سؤالك في تعليق أو على <a href="https://academy.hsoub.com/questions/">منصة الأسئلة والأجوبة</a> التابعة لأكاديمية حسوب.
	</p>
</div>
]]></description><guid isPermaLink="false">275</guid><pubDate>Sat, 06 Feb 2016 13:16:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x645;&#x643;&#x62A;&#x628;&#x629; Faker &#x644;&#x62A;&#x648;&#x644;&#x64A;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x644;&#x644;&#x627;&#x62E;&#x62A;&#x628;&#x627;&#x631; &#x641;&#x64A; Laravel 5</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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-faker-lib.png.bd2d9e52c9804a4f44978249d71769c1.png" /></p>

<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/#%D8%A8%D8%B0%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">بذر قواعد البيانات</a> إحدى الميزات الجميلة التي يقدمها Laravel؛ إلا أن إضافة تسجيلات بيانات كثيرة، الواحدة تلو الأخرى أمر مملّ ويأخذ الكثير من الوقت الثمين. تأتي مكتبة Faker لتدارك هذا الأمر.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>. </li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li>استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصد الاختبار.<span style="line-height: 22.4px; text-align: right;"> </span><span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-faker-lib.png.4df5f4e759efd8e8a35fe26534c38a28.png"><img data-fileid="12222" class="ipsImage ipsImage_thumbnailed" alt="laravel5-faker-lib.thumb.png.bbf7ed4588b" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-faker-lib.thumb.png.bbf7ed4588b5da144161672e30a1154d.png"></a></p><p>تُستخدَم Faker، وهي مكتبة PHP، لتوليد بيانات وهمية لأغراض اختبار التطبيقات. ويمكنها توليد بيانات من أنواع متعدّدة.</p><p>يغطي هذا الدرس المواضيع التالية:</p><ul><li>كيفية تثبيت Faker في Laravel.</li><li>أساسيات استخدام Faker في Laravel.</li><li>بذر قواعد البيانات باستخدام Faker.</li></ul><h2 id="كيفية-تثبيت-faker-في-laravel">كيفية تثبيت Faker في Laravel</h2><p>يأتي Laravel مضمّنا بمكتبة Faker مبدئيا ولا تحتاج لتثبيتها يدويّا. المكتبة تصبح جاهزة للاستخدام فور تثبيت Laravel. يمكن استخدام Faker لتوليد بيانات من الأنواع التالية:</p><ul><li>الأعداد.</li><li>نصوص Lorem (نصوص لمَلء الفراغ في الصفحات).</li><li>بيانات الأشخاص مثل الألقاب، الأسماء، الجنس وغيرها.</li><li>العناوين.</li><li>أرقام الهواتف.</li><li>الشركات.</li><li>النصوص.</li><li>الوقت والزمن.</li><li>أسماء النطاقات، روابط URL، عناوين البريد الإلكتروني، … إلخ.</li><li>وكيل مستخدم User agent.</li><li>بطاقات الدفع الإلكتروني.</li><li>الألوان.</li><li>الملفات.</li><li>الصور.</li><li>الرموز الشريطية Barcodes.</li></ul><p>وأنواع متفرقة أخرى.</p><h2 id="أساسيات-استخدام-faker">أساسيات استخدام Faker</h2><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-angularjs-%D9%88%D8%A7%D8%AC%D9%87%D8%A9%D9%8B-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Frontend لتطبيق Laravel 5</a> لتجربة عمل مكتبة Faker. يمكنك إن أردت إنشاء مشروع خاص للتجربة عبره، درس <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/">تثبيت Laravel 5 وإعداده على Windows وUbuntu</a> يشرح الكيفية.</p><p>نفتح ملف المسارات <code>routes.php</code> ونضيف الشفرة التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/customers',function(){
    $faker = Faker\Factory::create();

    $limit = 10;

    for ($i = 0; $i &lt; $limit; $i++) {
        echo $faker-&gt;name . ', Email Address: ' . $faker-&gt;unique()-&gt;email . ', Contact No' . $faker-&gt;phoneNumber . '&lt;br&gt;';
    }
});</pre><p>ننشئ كائنا من صنف <code>Faker</code> بالتعليمة</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$faker = Faker\Factory::create();</pre><p>ثم نضع حدّا لعدد التسجيلات التي نريد إنشاءها <code>limit$</code>، يُستخدَم هذا الحد في الحلقة التكرارية <code>for</code> لإنشاء عدد التسجيلات التي نريد (عشرة في حالتنا). نستخدم كائن <code>faker$</code> داخل الحلقة التكرارية لتوليد بيانات أشخاص (الاسم <code>name</code>، البريد الإلكتروني <code>email</code> ورقم الهاتف <code>phoneNumber</code>). بالنسبة للبريد الإلكتروني فقد اخترنا أن يكون فريدا لكل شخص (لا يوجد اثنان في الجدول لديهما نفس العنوان البريدي). ثم نعرض هذه البيانات في المتصفّح.</p><p>افتح الرابط <code>customers/</code> في المتصفح ولاحظ النتيجة.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Prof. Aiden Ebert, Email Address: Katharina69@hotmail.com, Contact No398-903-1148x26227
Candido Franecki, Email Address: Carlos.Dach@Gleichner.com, Contact No1-892-092-4346x13604
Isaiah Hand, Email Address: Bode.Claudie@Dickinson.biz, Contact No1-622-989-4414x2096
Faustino Hammes, Email Address: Emmerich.Anika@Hickle.net, Contact No(466)750-0869
Mrs. Deborah Weissnat Jr., Email Address: qHoppe@gmail.com, Contact No+39(0)3577406367
Ms. Harmony Homenick I, Email Address: Crist.Makenna@Monahan.com, Contact No04666426522
Delmer Hackett DDS, Email Address: hHilpert@Buckridge.info, Contact No210.397.7833x719
Hayley Hegmann PhD, Email Address: Genoveva14@hotmail.com, Contact No(780)054-8492x5869
Jarvis Tremblay, Email Address: pLakin@gmail.com, Contact No037.786.6464
Cecelia Rice, Email Address: Willms.Darrell@gmail.com, Contact No587-993-1770</pre><p>رأينا كيف تعمل Faker؛ سنرى الآن كيف نزاوج بينها وبذر قاعدة البيانات.</p><h2 id="بذر-قاعدة-البيانات-باستخدام-faker">بذر قاعدة البيانات باستخدام Faker</h2><p>ننشئ الآن جدول قاعدة بيانات عبر التهجيرات ثم نملأها ببيانات تولّدها مكتبة Faker.</p><p>ننشئ ملف التهجيرات:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration customers</pre><p>افتح ملف التهجيرات الذي أنشأناه للتو وعدّله ليصبح على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Customers extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('customers', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name');
            $table-&gt;string('email')-&gt;unique();
            $table-&gt;string('contact_number');
            $table-&gt;timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::drop('customers');
    }
}</pre><p>ثم ننفذ التهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>إن فحصت قاعدة البيانات فستجد أن جدولا جديدا باسم <code>customers</code> قد أضيف إلى القاعدة.</p><p>ننتقل إلى الخطوة التالية وهي إنشاء ملف للبذر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:seeder CustomersTableSeeder</pre><p>ثم نفتح ملف البذر <code>CustomersTableSeeder.php</code> الذي أنشأناه للتو ونعدّل عليه ليصبح كالتالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class CustomersTableSeeder extends Seeder
{
    /**
    * Run the database seeds.
    *
    * @return void
    */
    public function run()
    {
        $faker = Faker\Factory::create();

        $limit = 33;

        for ($i = 0; $i &lt; $limit; $i++) {
            DB::table('customers')-&gt;insert([ //,
                'name' =&gt; $faker-&gt;name,
                'email' =&gt; $faker-&gt;unique()-&gt;email,
                'contact_number' =&gt; $faker-&gt;phoneNumber,
            ]);
        }
    }
}</pre><p>تُدرج الشفرة أعلاه 33 تسجيلة جديدة في جدول البيانات <code>customers</code> باستخدام البيانات التي ولّدتها مكتبة Faker.</p><p>ثم ننفذ أمر البذر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan db:seed --class=CustomersTableSeeder</pre><p>يدل عدم ظهور رسائل في سطر الأوامر أن الأمر نُفّذ دون مشاكل.</p><p>إن تحققت من قاعدة البيانات فستجد أن الجدول <code>customers</code> يحوي الآن 33 تسجيلة.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/01_faker_seed.png.68f97039ea3e3fd5e8ca2bd17099ea8d.png"><img data-fileid="10958" class="ipsImage ipsImage_thumbnailed" alt="01_faker_seed.thumb.png.f6298b0bacde20ce" src="https://academy.hsoub.com/uploads/monthly_2016_01/01_faker_seed.thumb.png.f6298b0bacde20cec0fd878fd1d64df6.png"></a></p><p>لاحظ الحقول المولّدة؛ مثلا في حقل البريد الإلكتروني توجد عناوين بريدية صالحة من حيث الصيغة.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-faker-tutorial">Laravel 5 Faker Tutorial</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">237</guid><pubDate>Sat, 30 Jan 2016 20:04:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x645;&#x633;&#x627;&#x639;&#x62F;&#x629; &#x627;&#x644;&#x645;&#x62E;&#x635;&#x635;&#x629; Custom Helpers &#x641;&#x64A; Laravel 5</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-custom-helpers.png.bb7d9bc785b312092cec6a6cf5abf089.png" /></p>

<p>يأتي Laravel مضمّنا مبدئيًّا بالكثير من المهام الشائعة في تطوير تطبيقات الويب؛ إلا أن المطوّر يحتاج لإضافة ميزات خاصّة لإطار العمل لاستخدامها في مشروعه، وهو ما يمكن فعله في Laravel عبر الدوّال المساعِدة المخصّصة.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>. </li><li>الدوّال المساعدة المخصّصة في Laravel. <span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-custom-helpers.png.999d98166ec9867321415566bec65571.png"><img data-fileid="12083" class="ipsImage ipsImage_thumbnailed" alt="laravel5-custom-helpers.thumb.png.2fd554" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-custom-helpers.thumb.png.2fd55403f7b75432051466019132646f.png"></a></p><p>عند استخدام الدالة <code>asset</code> في قالب Blade فأنت تستدعي دالة مساعِدة مضمّنة في Laravel. الدوال المساعدة هي دوال مبنية لتأدية أعمال اعتيادية ويمكن غالبا استخدامها في أي ملف من إطار العمل أو التطبيق. سنشرح في هذا الدرس كيفية بناء دوال مساعدة مخصّصة.</p><p>يغطي الدرس المواضيع التالية:</p><ul><li>مجلّد الدوال المساعِدة.</li><li>تعريف صنف مساعِد.</li><li>مزود الخدمة الخاص بالصنف المساعِد.</li><li>كنية الصنف المساعد.</li></ul><p>سنستخدم نفس المشروع الذي أنشأناه في <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%88%D8%A7%D8%AC%D9%87%D8%A9%D9%8B-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">الدرس السابق</a> لإيضاح المفاهيم الواردة في هذا الدرس.</p><h2 id="مجلد-الدوال-المساعدة">مجلد الدوال المساعدة</h2><p>سننشئ مجلّدا خاصّا بالأصناف التي ستعرّف الدوال المساعدة داخل مجلد التطبيق <code>app</code>، نعطيه اسم <code>Helpers</code>. داخل مجلد الدوال المساعدة <code>app/Helpers</code> ننشئ ملفا باسم <code>MyFuncs.php</code> لتعريف الصنف <code>MyFuncs</code> ونضيف إليه الشفرة المصدرية التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App\Helpers;

class MyFuncs {

    public static function full_name($first_name,$last_name) {
        return $first_name . ', '. $last_name;   
    }
}</pre><p>تنشئ الشفرة أعلاه صنفا لتعريف الدالة المساعدة <code>full_name</code>. نبدأ بتعريف فضاء أسماء لأصناف المساعدات داخل فضاء أسماء التطبيق:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">namespace App\Helpers;</pre><p>ثم نعرّف الصنف <code>MyFuncs</code> الذي توجد داخله الدالة المساعدة <code>full_name</code>. الدالة المساعدة <code>full_name</code> هي دالة ثابتة <code>static</code> تقبل سلسلتي محارف Strings ثم تلمّهما Concatenate.</p><h2 id="صنف-مزود-الخدمة-الخاص-بالمساعدات">صنف مزود الخدمة الخاص بالمساعِدات</h2><p>تستخدَم مزودات الخدمة للتحميل التلقائي للأصناف كما أشرنا في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel 5</a>؛ سنعرّف مزود خدمة لتحميل جميع الأصناف الموجودة في المجلّد <code>app/Helpers</code>.</p><p>سنستخدم Artisan لإنشاء مزود خدمة كما فعلنا مع <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/">النماذج</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/">التهجيرات</a>، نفذ الأمر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:provider HelperServiceProvider</pre><p>ينشئ الأمر السابق ملفا باسم <code>HelperServiceProvider</code> على المسار <code>/app/Providers</code>؛ نفتحه لتحريره. عدّل الملف ليصبح كالتالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php 

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider {

/**
    * Bootstrap the application services.
    *
    * @return void
    */
public function boot()
{
    //
}

/**
    * Register the application services.
    *
    * @return void
    */
public function register()
{
        foreach (glob(app_path().'/Helpers/*.php') as $filename){
            require_once($filename);
        }
}
}</pre><p>نعرّف فضاء الأسماء الذي ينتمي إليه الصنف <code>App\Providers</code> ثم نستدعي صنف مزود الخدمة <code>Illuminate\Support\ServiceProvider</code> وهو صنف يمدده مزود الخدمة الذي نحن بصدد تعريفه.</p><p>تمهّد الدالة <code>boot</code> خدمات التطبيق Bootstrapping، أي تحميل الأصناف التي تعرّف الخدمات أثناء بدء التطبيق العمل. ثم يأتي دور الدالة <code>register</code> التي تحمّل محتويات المجلد <code>Helpers</code> بسبر ملفاته وتحميلها الواحد تلو الآخر.</p><h2 id="إعداد-مزود-خدمة-المساعدات-وكنية-صنف-المساعدات">إعداد مزود خدمة المساعدات وكنية صنف المساعدات</h2><p>نحتاج لإعلام إطار العمل Laravel بوجود مزوّد الخدمة الذي أنشأناه. لذا سنفتح ملف إعداد التطبيق <code>config/app.php</code> ونضيف عنصرا جديدا إلى مصفوفة <code>providers</code> على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">App\Providers\HelperServiceProvider::class,</pre><p>ثم ننتقل إلى مصفوفة الكنى <code>aliases</code> لإضافة كنية لصنف <code>MyFuncs</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'MyFuncs' =&gt; App\Helpers\MyFuncs::class,</pre><p>احفظ التعديلات.</p><h2 id="استخدام-المساعدات-الخصصة">استخدام المساعِدات المخصصة</h2><p>ننشئ في ملف المسارات <code>routes.php</code> مسارا خاصّا لتجربة الدالة المساعدة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/func', function () {
    return MyFuncs::full_name("Hsoub","Academy");
});</pre><p>نستدعي الدالة <code>MyFuncs::full_name</code> مع تمرير المعطيين الضروريين إليها.</p><p>افتح المسار <code><a rel="external nofollow" href="http://angulara.dev/func">http://angulara.dev/func</a></code> لتجربة عمل الدالة المساعدة. ستحصل على النتيجة التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Hsoub, Academy</pre><h2 id="خاتمة">خاتمة</h2><p>تستخدَم الدوال المساعدة لتنفيذ مهام يكثُر استعمالها في تطبيقات الويب. يمكنك إنشاء دوال مساعدة مخصّصة وإضافتها إلى التطبيق. تفيد الدوال المساعدة كثيرا في تهيئة المخرجات وصياغتها ضمن قوالب Blade والاستغناء بالتالي عن معالجة البيانات داخل القوالب.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-custom-helper">Laravel 5 Custom Helper</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">236</guid><pubDate>Fri, 29 Jan 2016 10:43:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; AngularJS &#x644;&#x628;&#x646;&#x627;&#x621; &#x648;&#x627;&#x62C;&#x647;&#x629; &#x623;&#x645;&#x627;&#x645;&#x64A;&#x629; Frontend &#x644;&#x62A;&#x637;&#x628;&#x64A;&#x642; Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-angularjs-frontend.png.eee37c38ec81c13ea62904677b66dc92.png" /></p>

<p>يهدف هذا الدرس إلى بناء تطبيق CRUD (إدراج بيانات في قاعدة بيانات، القراءة منها، تحديثها وحذفها؛ اختصار لـUpdate، Read، Create وDelete). التطبيق عبارة عن واجهة لإدارة لائحة من الموظفين: إضافة موظّف، تحرير بياناته أو حذفها. سنستخدم Laravel 5 للنهاية الخلفية Backend و AngularJS للنهاية الأمامية Frontend. سنستخدم أيضا Bootstrap لإضافة لمسة جمالية إلى التطبيق.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li>استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel.<span style="line-height: 22.4px; text-align: right;"> (هذا الدرس)</span></li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-angularjs-frontend.png.a38952ce696659ecb8eb980f416a2a02.png"><img data-fileid="12040" class="ipsImage ipsImage_thumbnailed" alt="laravel5-angularjs-frontend.thumb.png.1e" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-angularjs-frontend.thumb.png.1e837158a96d80a7e2a31b68457c4f4d.png"></a></p><p>AngularJS هو إطار عمل جافاسكريبت قويّ وفعّال، يتبنى مبدأ النموذج-العرض-المتحكم MVC ويعمل لدى العميل (المتصفّح). للاطلاع على المزيد عن AngularJS تابع سلسلة دروس <a href="https://academy.hsoub.com/search/?tags=%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA+angularjs">مدخل إلى تعلم AngularJS</a> .</p><p>يفترض هذا الدرس معرفة أساسيات Laravel 5، تثبيت كلّ من PHP، MySQL، ِApache وComposer.</p><p>يغطي الدرس المواضيع التالية:</p><ul><li>إنشاء نهاية خلفية في Laravel 5، ستكون عبارة عن واجهة برمجية <abbr title="واجهة برمجية | Application Programming Interface">API</abbr>.</li><li>بنية تطبيق AngularJS.</li></ul><h2 id="واجهة-برمجية-باستخدام-laravel-5">واجهة برمجية باستخدام Laravel 5</h2><p>ننشئ في هذه الفقرة النهاية الخلفية للتطبيق الذي نعمل عليه. سيتولى Laravel هذه المهمة. نبدأ بإنشاء تطبيق Laravel ثم نعدّه لتوفير الواجهة البرمجية.</p><h3 id="الخطوة-الأولى-إنشاء-تطبيق-laravel">الخطوة الأولى: إنشاء تطبيق Laravel</h3><p>ننفذ الأمر التالي في أصل المستند Document root لإنشاء مشروع Laravel باسم <code>angulara</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">composer create-project laravel/laravel angulara</pre><p>راجع درس <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/">تثبيت Laravel 5 وإعداده على Windows وUbuntu</a> للمزيد حول تثبيت Laravel وإعداده. سنفترض في بقية هذا الدرس تثبيت Laravel على المنصة المفضلة لديك وإنشاء مضيف افتراضي باسم <code>angulara.dev</code>.</p><p>الخطوة التالية هي إعداد تهجير قاعدة البيانات.</p><h3 id="الخطوة-الثانية-إعداد-قاعدة-البيانات">الخطوة الثانية: إعداد قاعدة البيانات</h3><p>ستحتاج لقاعدة بيانات للعمل مع التطبيق. استخدم برنامج إدارة قاعدة البيانات المفضل لديك أو نفذ الأمر التالي في سطر أوامر MySQL لإنشاء قاعدة بيانات للمشروع:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">CREATE DATABASE `angulara`;</pre><p>ننتقل الآن لإعداد Laravel لكي يعمل مع قاعدة البيانات. افتح ملف <code>env.</code> في مجلد تطبيق Laravel وعدل القيم التالية بما يناسب:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">DB_HOST=localhost
// اسم قاعدة البيانات
DB_DATABASE=angulara
// اسم مستخدم في MySQL لديه صلاحيات الكتابة والقراءة في القاعدة أعلاه
DB_USERNAME=root
// كلمة سر المستخدم
DB_PASSWORD=melody</pre><p>احفظ التعديلات.</p><p>نستغل أداة Artisan لإنشاء ملف تهجير خاص بجدول يحوي بيانات الموظفين <code>employees</code>.</p><p>نفذ الأمر التالي لإنشاء ملف التهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration create_employees_table</pre><p>ستحصُل على الرسالة التالية التي تعرض اسم الملف المنشأ:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Created Migration: 2016_01_05_203637_create_employees_table</pre><p>ينشئ الأمر ملفا في المجلد <code>database/migrations</code>، نفتحه للتعديل عليه. عدّل المحتوى كالتالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEmployeesTable extends Migration {

    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up() {
        Schema::create('employees', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name')-&gt;unique();
            $table-&gt;string('email')-&gt;unique();
            $table-&gt;string('contact_number');
            $table-&gt;string('position');
            $table-&gt;timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down() {
        Schema::drop('employees');
    }

}</pre><p>احفظ التعديلات ثم نفذ أمر ِArtisan التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>ينفذ الأمر التهجيرات وينشئ جدول بيانات الموظفين. تظهر الرسائل التالية بعد تنفيذ الأمر:<code> </code></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2016_01_05_203637_create_employees_table</pre><p>تحقق من قاعدة بيانات MySQL، ستجد أن جدولا جديدا أُدرِج في القاعدة.</p><h3 id="الخطوة-الثالثة-إنشاء-واجهة-برمجية">الخطوة الثالثة: إنشاء واجهة برمجية</h3><p>ننشئ متحكما Controller للتطبيق، سنسميه <code>Employees</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:controller Employees</pre><p>ثم يأتي دور النموذج Model:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:model Employee</pre><p>سنضيف مصفوفة في النموذج لتفعيل الإسناد الشامل؛ افتح ملف النموذج وعدّله على النحو التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{
    protected $fillable = array('id', 'name', 'email','contact_number','position');
}</pre><p>احفظ التعديلات.</p><p>ننتقل للتعديل على المتحكم. افتح ملف المتحكم <code>Employees</code> وعدله ليصبح كالتالي</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

namespace App\Http\Controllers;

use App\Employee;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class Employees extends Controller {

    /**
    * Display a listing of the resource.
    *
    * @return Response
    */
    public function index($id = null) {
        if ($id == null) {
            return Employee::orderBy('id', 'asc')-&gt;get();
        } else {
            return $this-&gt;show($id);
        }
    }

    /**
    * Store a newly created resource in storage.
    *
    * @param  Request  $request
    * @return Response
    */
    public function store(Request $request) {
        $employee = new Employee;

        $employee-&gt;name = $request-&gt;input('name');
        $employee-&gt;email = $request-&gt;input('email');
        $employee-&gt;contact_number = $request-&gt;input('contact_number');
        $employee-&gt;position = $request-&gt;input('position');
        $employee-&gt;save();

        return 'Employee record successfully created with id ' . $employee-&gt;id;
    }

    /**
    * Display the specified resource.
    *
    * @param  int  $id
    * @return Response
    */
    public function show($id) {
        return Employee::find($id);
    }

    /**
    * Update the specified resource in storage.
    *
    * @param  Request  $request
    * @param  int  $id
    * @return Response
    */
    public function update(Request $request, $id) {
        $employee = Employee::find($id);

        $employee-&gt;name = $request-&gt;input('name');
        $employee-&gt;email = $request-&gt;input('email');
        $employee-&gt;contact_number = $request-&gt;input('contact_number');
        $employee-&gt;position = $request-&gt;input('position');
        $employee-&gt;save();

        return "Sucess updating user #" . $employee-&gt;id;
    }

    /**
    * Remove the specified resource from storage.
    *
    * @param  int  $id
    * @return Response
    */
    public function destroy($id = null) {
            if ($id == null) {
            }
            else {
                $employee = Employee::find($id);

                $employee-&gt;delete();

                return "Employee record successfully deleted #" . $id;
            }
    }
}</pre><p>يعرِّف المتحكم الدوالّ <code>index</code> لسرد قائمة بالموظفين، <code>store</code> لإضافة موظف جديد، <code>show</code> لعرض موظف بناء على معرّفه، <code>update</code> لتحديث بيانات موظّف و<code>destroy</code> لحذف موظّف.</p><p>تبقى لنا إعداد المسارات Routes في Laravel. افتح ملف المسارات <code>routes.php</code> وعدله كالتالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/', function () {
    return view('index');
});

Route::get('/api/v1/employees/{id?}', 'Employees@index');
Route::post('/api/v1/employees', 'Employees@store');
Route::post('/api/v1/employees/{id}', 'Employees@update');
Route::delete('/api/v1/employees/{id}', 'Employees@destroy');</pre><p>لاحظ استخدام إجراءات HTTP وفقا للمبدأ المشروح في درس <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة برمجية <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel 5</a>. يختلف التعامل مع المسار <code><abbr title="واجهة برمجية | Application Programming Interface">api</abbr>/v1/employees</code> حسب إجراء HTTP المستخدم: <code>get</code> يُستخدم للحصول على معلومات موظف أو قائمة بالموظفين، <code>post</code> لإضافة موظف جديد، <code>put</code> لتحديث بيانات موظّف و<code>delete</code> لحذف موظّف.</p><p>أكملنا الآن جانب النهاية الخلفية بإنشاء واجهة برمجية. ننتقل للواجهة الأمامية التي ستستخدم الواجهة البرمجية للحصول على بيانات الموظفين وتنسيقها قبل عرضها في المتصفح.</p><h2 id="بنية-تطبيق-angularjs">بنية تطبيق AngularJS</h2><p>سيأخذ مجلد <code>public</code> (الواجهة الأمامية لتطبيق Laravel) الشكل التالي:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/01_laravel_angular.png.43311b32c30e14efb140755a000a2c5d.png"><img data-fileid="10891" class="ipsImage ipsImage_thumbnailed" alt="01_laravel_angular.thumb.png.79e4a8beb3e" src="https://academy.hsoub.com/uploads/monthly_2016_01/01_laravel_angular.thumb.png.79e4a8beb3e59dfedcafd97471b134b4.png"></a></p><ul><li>يحوي المجلّد الفرعي <code>app</code> ملفات جافاسكريبت التابعة لـAngularJS.</li><li>توجد متحكمات AngularJS في المجلّد <code>app/controllers</code>.</li><li>توجد ملفات نواة AngularJS في المجلّد <code>app/lib</code>. توجد أيضا إمكانية استخدام شبكة توصيل محتوى Content delivery network, CDN.</li><li>توجد ملفات CSS في المجلد <code>css</code>.</li><li>ملفات جافاسكريبت غير التابعة لـAngularJS توجد في المجلد <code>js</code>.</li></ul><p>توجد ملفات الواجهة الأمامية في <a class="ipsAttachLink" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=10894">الملف المرفق</a>، سنشرح ما يحتاج لشرح منها.</p><h3 id="الملف-appjs">الملف app.js</h3><p>سنستخدم الملف <code>public/app/app.js</code> لتعريف التطبيق الخاص بنا:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">var app = angular.module('employeeRecords', [])
        .constant('API_URL', 'http://angulara.dev/api/v1/');</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">ننشئ وحدة Module في AngularJS ونسند الكائن إلى المتغير </span><code style="line-height: 1.6;">app</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">. سيُستخدم هذا المتغير في جميع ملفات AngularJS؛ ثم نعرّف ثابتا Constant لرابط الواجهة البرمجية </span><code style="line-height: 1.6;">API_URL</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">.</span></p><p><strong>ملحوظة:</strong> إن كنت اخترت اسما مختلفا للمضيف فضعه مكان <code>angulara.dev</code>.</p><h3 id="المتحكم-employeesjs">المتحكم Employees.js</h3><p>سيكون هذا الملف مسؤولا عن التفاعل مع عروض تطبيق AngularJS:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">app.controller('employeesController', function($scope, $http, API_URL) {
    // الحصول على لائحة الموظفين 
    $http.get(API_URL + "employees")
            .success(function(response) {
                $scope.employees = response;
            });

    // عرض نافذة منبثقة
    $scope.toggle = function(modalstate, id) {
        $scope.modalstate = modalstate;

        switch (modalstate) {
            case 'add':
                $scope.form_title = "Add New Employee";
                break;
            case 'edit':
                $scope.form_title = "Employee Detail";
                $scope.id = id;
                $http.get(API_URL + 'employees/' + id)
                        .success(function(response) {
                            console.log(response);
                            $scope.employee = response;
                        });
                break;
            default:
                break;
        }
        console.log(id);
        $('#myModal').modal('show');
    }

    //save new record / update existing record
    $scope.save = function(modalstate, id) {
        var url = API_URL + "employees";
        var request_method = 'POST';

        //append employee id to the URL if the form is in edit mode
        if (modalstate === 'edit'){
            url += "/" + id;
            request_method = 'PUT';
        }

        $http({
            method: request_method,
            url: url,
            data: $.param($scope.employee),
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        }).success(function(response) {
            console.log(response);
            location.reload();
        }).error(function(response) {
            console.log(response);
            alert('This is embarassing. An error has occured. Please check the log for details');
        });
    }

    //delete record
    $scope.confirmDelete = function(id) {
        var isConfirmDelete = confirm('Are you sure you want this record?');
        if (isConfirmDelete) {
            $http({
                method: 'DELETE',
                url: API_URL + 'employees/' + id
            }).
                    success(function(data) {
                        console.log(data);
                        location.reload();
                    }).
                    error(function(data) {
                        console.log(data);
                        alert('Unable to delete');
                    });
        } else {
            return false;
        }
    }
});</pre><p>نعرِّف متحكما باسم <code>employeesController</code> في المتغيّر <code>app</code> الذي أنشأناه في الملف <code>app.js</code>. حدّدنا الاعتماديات بـ <code>$http</code>، <code>scope$</code> و<code>API_URL</code>.</p><p>نستدعي خدمة <code>http$</code> في AngularJS لإرسال طلب إلى الواجهة البرمجية، مع تمرير المعطى <code>API_URL + "employees"</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$http.get(API_URL + "employees").success(function(response) {$scope.employees = response;});</pre><p>عند نجاح الطلب نُسنِد الإجابة إلى المتغير <code>scope.employees$</code> الذي سيصبح متاحا في العرض View لإظهار محتواه.</p><p>تعرض الدالة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$scope.toggle = function(modalstate, id) {…}</pre><p>نافذة منبثقة تحوي استمارة لإضافة موظّف جديد أو تعديل بيانات موظّف موجود حسب الحالة.</p><p>نستخدم الدالة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$scope.save = function(modalstate, id){…}</pre><p>في حالتيْ الإضافة والتعديل. بالنسبة لإضافة موظّف نستخدم إجراء <code>POST</code>؛ وفي حالة التعديل نستخدم الإجراء <code>PUT</code>.</p><p>تحذف الدالة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$scope.confirmDelete = function(id){…}</pre><p>بيانات موظّف من جدول الموظفين.</p><h3 id="عرض-البيانات-المتحصل-عليها-من-الواجهة-البرمجية-بـangularjs">عرض البيانات المتحصل عليها من الواجهة البرمجية بـAngularJS</h3><p>سننشئ عرضا لإظهار البيانات التي نتحصل عليها من الواجهة البرمجية؛ يستخدم كل من angularJS وBlade الحاضنات المزدوجة <code>{{}}</code> لعرض البيانات، لذا لن نحفظ عرض AngularJS بلاحقة <code>blade.php</code> حتى لا يعدّ نظام Blade العرض موجها له.</p><p>محتوى العرض هو التالي، نحفظ الملف <code>index.php</code> في ملف العروض <code>resources/views</code> حتى يُحمّل عند طلبه من المسار <code>/</code> (الصفحة الرئيسية للموقع):</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;!DOCTYPE html&gt;
&lt;html lang="en-US" ng-app="employeeRecords"&gt;
    &lt;head&gt;
        &lt;title&gt;Laravel 5 AngularJS CRUD Example&lt;/title&gt;

        &lt;!-- Load Bootstrap CSS --&gt;
        &lt;link href="&lt;?= asset('css/bootstrap.min.css') ?&gt;" rel="stylesheet"&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h2&gt;Employees Database&lt;/h2&gt;
        &lt;div  ng-controller="employeesController"&gt;

            &lt;!-- Table-to-load-the-data Part --&gt;
            &lt;table class="table"&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th&gt;ID&lt;/th&gt;
                        &lt;th&gt;Name&lt;/th&gt;
                        &lt;th&gt;Email&lt;/th&gt;
                        &lt;th&gt;Contact No&lt;/th&gt;
                        &lt;th&gt;Position&lt;/th&gt;
                        &lt;th&gt;&lt;button id="btn-add" class="btn btn-primary btn-xs" ng-click="toggle('add', 0)"&gt;Add New Employee&lt;/button&gt;&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    &lt;tr ng-repeat="employee in employees"&gt;
                        &lt;td&gt;{{  employee.id }}&lt;/td&gt;
                        &lt;td&gt;{{ employee.name }}&lt;/td&gt;
                        &lt;td&gt;{{ employee.email }}&lt;/td&gt;
                        &lt;td&gt;{{ employee.contact_number }}&lt;/td&gt;
                        &lt;td&gt;{{ employee.position }}&lt;/td&gt;
                        &lt;td&gt;
                            &lt;button class="btn btn-default btn-xs btn-detail" ng-click="toggle('edit', employee.id)"&gt;Edit&lt;/button&gt;
                            &lt;button class="btn btn-danger btn-xs btn-delete" ng-click="confirmDelete(employee.id)"&gt;Delete&lt;/button&gt;
                        &lt;/td&gt;
                    &lt;/tr&gt;
                &lt;/tbody&gt;
            &lt;/table&gt;
            &lt;!-- End of Table-to-load-the-data Part --&gt;
            &lt;!-- Modal (Pop up when detail button clicked) --&gt;
            &lt;div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"&gt;
                &lt;div class="modal-dialog"&gt;
                    &lt;div class="modal-content"&gt;
                        &lt;div class="modal-header"&gt;
                            &lt;button type="button" class="close" data-dismiss="modal" aria-label="Close"&gt;&lt;span aria-hidden="true"&gt;×&lt;/span&gt;&lt;/button&gt;
                            &lt;h4 class="modal-title" id="myModalLabel"&gt;{{form_title}}&lt;/h4&gt;
                        &lt;/div&gt;
                        &lt;div class="modal-body"&gt;
                            &lt;form name="frmEmployees" class="form-horizontal" novalidate=""&gt;

                                &lt;div class="form-group error"&gt;
                                    &lt;label for="inputEmail3" class="col-sm-3 control-label"&gt;Name&lt;/label&gt;
                                    &lt;div class="col-sm-9"&gt;
                                        &lt;input type="text" class="form-control has-error" id="name" name="name" placeholder="Fullname" value="{{name}}" 
                                        ng-model="employee.name" ng-required="true"&gt;
                                        &lt;span class="help-inline" 
                                        ng-show="frmEmployees.name.$invalid &amp;&amp; frmEmployees.name.$touched"&gt;Name field is required&lt;/span&gt;
                                    &lt;/div&gt;
                                &lt;/div&gt;

                                &lt;div class="form-group"&gt;
                                    &lt;label for="inputEmail3" class="col-sm-3 control-label"&gt;Email&lt;/label&gt;
                                    &lt;div class="col-sm-9"&gt;
                                        &lt;input type="email" class="form-control" id="email" name="email" placeholder="Email Address" value="{{email}}" 
                                        ng-model="employee.email" ng-required="true"&gt;
                                        &lt;span class="help-inline" 
                                        ng-show="frmEmployees.email.$invalid &amp;&amp; frmEmployees.email.$touched"&gt;Valid Email field is required&lt;/span&gt;
                                    &lt;/div&gt;
                                &lt;/div&gt;

                                &lt;div class="form-group"&gt;
                                    &lt;label for="inputEmail3" class="col-sm-3 control-label"&gt;Contact Number&lt;/label&gt;
                                    &lt;div class="col-sm-9"&gt;
                                        &lt;input type="text" class="form-control" id="contact_number" name="contact_number" placeholder="Contact Number" value="{{contact_number}}" 
                                        ng-model="employee.contact_number" ng-required="true"&gt;
                                    &lt;span class="help-inline" 
                                        ng-show="frmEmployees.contact_number.$invalid &amp;&amp; frmEmployees.contact_number.$touched"&gt;Contact number field is required&lt;/span&gt;
                                    &lt;/div&gt;
                                &lt;/div&gt;

                                &lt;div class="form-group"&gt;
                                    &lt;label for="inputEmail3" class="col-sm-3 control-label"&gt;Position&lt;/label&gt;
                                    &lt;div class="col-sm-9"&gt;
                                        &lt;input type="text" class="form-control" id="position" name="position" placeholder="Position" value="{{position}}" 
                                        ng-model="employee.position" ng-required="true"&gt;
                                    &lt;span class="help-inline" 
                                        ng-show="frmEmployees.position.$invalid &amp;&amp; frmEmployees.position.$touched"&gt;Position field is required&lt;/span&gt;
                                    &lt;/div&gt;
                                &lt;/div&gt;

                            &lt;/form&gt;
                        &lt;/div&gt;
                        &lt;div class="modal-footer"&gt;
                            &lt;button type="button" class="btn btn-primary" id="btn-save" ng-click="save(modalstate, id)" ng-disabled="frmEmployees.$invalid"&gt;Save changes&lt;/button&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;!-- Load Javascript Libraries (AngularJS, JQuery, Bootstrap) --&gt;
        &lt;script src="&lt;?= asset('app/lib/angular/angular.min.js') ?&gt;"&gt;&lt;/script&gt;
        &lt;script src="&lt;?= asset('js/jquery.min.js') ?&gt;"&gt;&lt;/script&gt;
        &lt;script src="&lt;?= asset('js/bootstrap.min.js') ?&gt;"&gt;&lt;/script&gt;

        &lt;!-- AngularJS Application Scripts --&gt;
        &lt;script src="&lt;?= asset('app/app.js') ?&gt;"&gt;&lt;/script&gt;
        &lt;script src="&lt;?= asset('app/controllers/employees.js') ?&gt;"&gt;&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre><p>نربط تطبيق AngularJS بوسم <code>html</code> حتى يكون له كامل التحكّم في العناصر الموجودة في الصفحة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;html lang="en-US" ng-app="employeeRecords"&gt; </pre><p>نفس الشيء بالنسبة للمتحكم <code>employeesController</code> الذي نربطه بعنصر <code>div</code> حتى نجعل جميع دوال المتحكم متاحة في هذا العنصر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;div ng-controller="employeesController"&gt;</pre><p>نستخدم تعليمة <code>ng-repeat</code> للمرو على جميع عناصر المجموعة <code>employees</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;tr ng-repeat="employee in employees"&gt;</pre><p>تعمل <code>ng-repeat</code> بطريقة مشابهة لعمل الحلقة التكرارية <code>foreach</code>.</p><h3 id="التحقق-من-بيانات-استمارات-angularjs">التحقق من بيانات استمارات AngularJS</h3><p>استخدمنا في استمارات الموظفين طرقا للتحقق من المُدخلات. اعثر على الشفرات التالية في ملف العرض <code>index.php</code> ولاحظ استخدامها:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;form name="frmEmployees" class="form-horizontal" novalidate=""&gt;</pre><p>تعرّف هذه الشفرة استمارة باسم <code>frmEmployees</code> وتضيف إليها خاصيّة <code>novalidate</code> للطلب من HTML 5 الامتناع عن تدقيق الاستمارة، سنتولى الأمر.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;input type… ng-model="employee.name" ng-required="true"&gt;</pre><p>تستخدم تعليمة <code>ng-model</code> لربط حقول الاستمارة ببيانات النموذج <code>Employee</code>. ربطنا الحقل أعلاه بخاصية <code>name</code> في النموذج. بهذه الطريقة يكون محتوى الحقل متاحا للنموذج، والعكس أيضا. تدل التعليمة <code>ng-required</code> أن الحقل مطلوب. إن لم تذكر قيمة لهذا الحقل فلن يمكن إرسال الاستمارة.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;span class="help-inline" ng-show="frmEmployees.name.$invalid &amp;&amp; frmEmployees.name.$touched"&gt;</pre><p>لا يظهر هذا العنصُر إلا إذا أخفق التحقق من حقل <code>name</code> قبله. تظهر رسالة تفيد أن قيمة الحقل مطلوبة.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">ng-disabled="frmEmployees.$invalid" </pre><p>تعطّل هذه التعليمة إمكانية إرسال الاستمارة عند إخفاق التحقق من أحد الحقول المطلوبة.</p><p>حان الآن وقت تجربة ما عملناه في الخطوات السابقة، افتح الموقع (بالنسبة لي اخترتُ إنشاء مضيف افتراضي <code>angulara.dev</code>):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">http://angulara.dev/</pre><p>ستحصُل، إن اتبعت الخطوات السابقة، على الواجهة التالية:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/02_laravel_angular.png.011a0bf581fd3cca4530442a868613d0.png"><img data-fileid="10892" class="ipsImage ipsImage_thumbnailed" alt="02_laravel_angular.thumb.png.08f8db0c1bb" src="https://academy.hsoub.com/uploads/monthly_2016_01/02_laravel_angular.thumb.png.08f8db0c1bb9bd5240fd53d9acd2fbbc.png"></a></p><p>اضغط على زر<strong> <code>Add New Employee</code></strong> لإضافة موظّف. ستظهر نافذة منبثقة لإضافة بيانات الموظّف.</p><p>تصبح الواجهة بعد إضافة موظفين على النحو التالي:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/03_laravel_angular.png.e50cfb84223e604b020fbe7a1a9519d1.png"><img data-fileid="10893" class="ipsImage ipsImage_thumbnailed" alt="03_laravel_angular.thumb.png.ce2e3e1cbe0" src="https://academy.hsoub.com/uploads/monthly_2016_01/03_laravel_angular.thumb.png.ce2e3e1cbe05e9889fd82271bef89d26.png"></a></p><p>تمكّن الأزرار <strong><code>edit</code></strong> و <strong><code>delete</code></strong> الموجودة في كل سطر تحديثَ أو حذف بيانات موظّف.</p><p>الملف المرفق:  <a class="ipsAttachLink" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=10894">مجلد public</a>.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-angularjs-tutorial">Laravel 5 AngularJS Tutorial</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">234</guid><pubDate>Wed, 27 Jan 2016 19:21:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x645;&#x62F;&#x648;&#x646;&#x629; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-blog.png.b69f00fea2ebeedf08fc20c9d2d8cf8a.png" /></p>

<p>تحتاج أغلب الشركات العاملة على الشبكة للانطلاق في <a href="https://academy.hsoub.com/marketing/inbound-marketing/%D8%A7%D9%84%D8%AA%D8%B3%D9%88%D9%8A%D9%82-%D8%A8%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89%D8%8C-%D9%85%D8%B9%D9%86%D8%A7%D9%87-%D9%88%D8%A3%D9%87%D9%85%D9%8A%D8%AA%D9%87-r72/">التسويق بالمحتوى</a>. يُعرَّف التسويق بالمحتوى بأنه "مقاربة تسويق ترتكز على إنتاج محتوى جيد، مناسب وذي قيمة ثم توزيعه من أجل جذب فئة محدّدة بدقة والحفاظ عليها، وفي آخر المطاف الحصول على إجراء ذي مردود ربحي من الزبون".</p><p id="مقدمة">هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>. </li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>. </li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>. </li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li>إنشاء مدوّنة باستخدام Laravel. <span style="line-height: 22.4px; text-align: right;"> </span><span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-blog.png.86c5b45551305789250219a9ad5792d8.png"><img data-fileid="11860" class="ipsImage ipsImage_thumbnailed" alt="laravel5-blog.thumb.png.3f1af7f8e2791040" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-blog.thumb.png.3f1af7f8e27910407e3decdd5bc8e6dc.png"></a></p><p>نفرض مثلا أنك طورت مشروع Larashop لبيع الملابس على الشبكة. يقوم مبدأ التسويق عبر المحتوى على التأسيس لنفسك بوصفك خبيرا في المجال، فتكتُب - مثلا - عن الملابس وكيفية اختيارها والحفاظ عليها وتقدم نصائح لزوار موقعك؛ مما يرفع من احتمالات الشراء من متجرك، وهو ما يمثل قيمة تجارية للموقع.</p><p>تعمل مدونات المؤسسات على تنفيذ هذا المبدأ فتنشر محتوى مناسبا لجمهورها مما يكون له الأثر الإيجابي على المؤسسة أو الشركة. لا يقتصر المحتوى المنشور في المدونة على المحتوى الكتابي بل يتعداه للمرئي مثل مقاطع الفيديو، الصوتيات والصور.</p><p>يغطي الدرس المواضيع التالية:</p><ul><li>أهم خاصيات المدونة<ul><li>المنشور</li><li>التصنيفات</li><li>الوسوم Tags</li></ul></li><li>عوامل التحسين لمحركات البحث<ul><li>عنوان المنشور</li><li>وصف Meta</li><li>دور الشبكات الاجتماعية</li></ul></li><li>تهجيرات قاعدة البيانات الخاصة بمدونة Larashop.</li></ul><h2 id="خاصيات-المدونة">خصائص المدونة</h2><p>نذكر في هذه الفقرة الخصائص التي نريد تواجدها في مدونتنا.</p><h3 id="المنشورات-posts">المنشورات Posts</h3><p>يتمثل المحتوى الأساسي للمدونة في المنشورات، إذ تحوي المعلومات التي نريد نشرها. سنحصُل على المنشورات من قاعدة البيانات وسنستخدم HTML لتهيئتها.</p><h3 id="التصنيفات">التصنيفات</h3><p>تُستخدَم التصنيفات لتجميع المنشورات ذات القاسم المشترك. مثلا يمكن أن تنشئ تصنيفا لملابس الرجال، آخر للملابس النسائية وثالث لملابس الأطفال وهكذا.</p><h3 id="الوسوم">الوسوم</h3><p>تشبه الوسوم التصنيفات، إلا أنها أكثر تخصيصا. يمكنك مثلا إنشاء وسم للملابس الشتوية ثم وضعه على جميع المنشورات بغض النظر عن تصنيفها. يمكن للمنشور الواحد أن يرتبط بأكثر من وسم؛ يمكن أن تضيف للمنشور وسما بنوعية القماش المستخدم، وآخر للفصل المناسب لارتدائه.</p><h2 id="عوامل-التحسين-لمحركات-البحث">عوامل التحسين لمحركات البحث</h2><p>لا نريد لمنشوراتنا أن تظهر في آخر صفحة من مليون نتيجة في محركات البحث، سيكون جيدا أن نظهر في الصفحة الأولى لذا يجب الاهتمام بالتحسين لمحركات البحث، راجع مقال <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel 5</a>.</p><p>بالنسبة لمدونتنا فسنهتم بالعاملين:</p><ul><li>عنوان المنشور، وهو العنوان الذي سيظهر في محركات البحث، يُستحسن ألا يتعدى 56 محرفا.</li><li>وصف Meta، يظهر تحت العنوان في نتيجة محركات البحث. من الأفضل ألا يتعدى 160 محرفا.</li></ul><h2 id="التهجيرات-الخاصة-بمنشورات-مدونة-larashop">التهجيرات الخاصة بمنشورات مدونة Larashop</h2><p>حان الآن وقت التنفيذ. في ما يلي جداول قاعدة البيانات التي نحتاج لإنشائها للمدونة.</p><p>الحقول التالية مشتركة بين جميع الجداول</p><table><tbody><tr><th>التسلسل   </th><th>الحقل                 </th><th>نوع البيانات     </th><th>الوصف</th></tr><tr><td>1</td><td>created_at</td><td>Timestamp</td><td>ختم زمني لوقت إنشاء التسجيلة</td></tr><tr><td>2</td><td>updated_at</td><td>Timestamp</td><td>ختم زمني لوقت تحديث التسجيلة</td></tr></tbody></table><ul><li>جدول تصنيفات المدونة</li></ul><table><tbody><tr><th>التسلسل   </th><th>الحقل           </th><th>نوع البيانات       </th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>INT</td><td>معرّف التصنيف، مفتاح رئيس</td></tr><tr><td>2</td><td>category</td><td>VARCHAR</td><td>اسم التصنيف</td></tr></tbody></table><ul><li>جدول وسوم المدونة</li></ul><table><tbody><tr><th>التسلسل    </th><th>الحقل   </th><th>نوع البيانات     </th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>INT</td><td>معرّف الوسم مفتاح رئيس</td></tr><tr><td>2</td><td>tag</td><td>VARCHAR</td><td>اسم الوسم</td></tr></tbody></table><ul><li>جدول الوسوم والمنشورات: بما أنه يمكن أن يكون للمنشور أكثر من وسم، فيجب إنشاء جدول خاص للربط بين الوسم والمنشور.</li></ul><table><tbody><tr><th>التسلسل     </th><th>الحقل        </th><th>نوع البيانات   </th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>INT</td><td>معرّف الحقل، مفتاح رئيس</td></tr><tr><td>2</td><td>post_id</td><td>INT</td><td>مفتاح خارجي إلى معرّف المنشور</td></tr><tr><td>3</td><td>tag_id</td><td>INT</td><td>مفتاح خارجي إلى معرّف الوسم</td></tr></tbody></table><ul><li>جدول المنشورات</li></ul><table><tbody><tr><th>التسلسل   </th><th>الحقل               </th><th>نوع البيانات          </th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>INT</td><td>معرّف المنشور، مفتاح رئيس</td></tr><tr><td>2</td><td>url</td><td>Varchar(255)</td><td>رابط المنشور</td></tr><tr><td>3</td><td>title</td><td>Varchar(140)</td><td>عنوان المنشور</td></tr><tr><td>4</td><td>description</td><td>Varchar(170)</td><td>وصف المنشور</td></tr><tr><td>5</td><td>content</td><td>Text</td><td>محتوى المنشور</td></tr><tr><td>6</td><td>blog</td><td>Tinyint(1)</td><td>يحدد طبيعة المنشور</td></tr><tr><td>7</td><td>category_id</td><td>INT</td><td>معرّف تصنيف المنشور، مفتاح خارجي</td></tr><tr><td>8</td><td>image</td><td>Varchar(255)</td><td>رابط صورة المنشور</td></tr></tbody></table><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%8Alaravel-5-r224/">تهجير قواعد البيانات فيLaravel 5</a> ملف التهجير الخاص بالمنشورات إلا أننا لم نضف معرف التصنيف <code>category_id</code> ولا صورة المنشور <code>image</code>؛ سننشئ في هذا الدرس ملف تهجير لإضافة هذين الحقلين. نفذ الأمر التالي في مجلد التطبيق:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration add_category_id_image_to_posts --table=posts</pre><p>افتح ملف التهجير المنشأ بالأمر السابق وعدله ليصبح كالتالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddCategoryIdImageToPosts extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table-&gt;string('image')-&gt;nullable()-&gt;after('content');            
            $table-&gt;unsignedInteger('category_id')-&gt;nullable()-&gt;after('blog');
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table-&gt;dropColumn('image');
            $table-&gt;dropColumn('category_id');
        });
    }
}
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">نضيف حقلا جديدا لصورة المنشور، يُضاف الحقل بعد حقل المحتوى </span><code style="line-height: 1.6;">content</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> ويمكن أن يكون فارغا:</span></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$table-&gt;string('image')-&gt;nullable()-&gt;after('content');</pre><p>نضيف أيضا حقلا لمعرِّف التصنيف بعد حقل <code>blog</code> </p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$table-&gt;unsignedInteger('category_id')-&gt;nullable()-&gt;after('blog');</pre><p>نفذ الأمر التالي لشغيل ملف التهجير وإضافة الحقول:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><h3 id="ملف-التهجير-الخاص-بتصنيفات-المدونة">ملف التهجير الخاص بتصنيفات المدونة</h3><p>ننتقل الآن لملف التهجير الذي سيتولى إنشاء جدول تصنيفات المنشورات. سنستخدم هذا الملف أيضا لإدراج تسجيلات في الجدول، كل تسجيلة تمثل تصنيفا:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration blog_categories</pre><p>عدل ملف التهجير كالتالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BlogCategories extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('blog_categories', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('category')-&gt;unique();
            $table-&gt;timestamps();
        });

        DB::table('blog_categories')-&gt;insert([
            'category' =&gt; "WOMEN"
        ]);

        DB::table('blog_categories')-&gt;insert([
            'category' =&gt; "MEN"
        ]);

        DB::table('blog_categories')-&gt;insert([
            'category' =&gt; "KIDS"
        ]);
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::drop('blog_categories');
    }
}<code>
</code></pre><h3 id="ملف-التهجير-الخاص-بالوسوم">ملف التهجير الخاص بالوسوم</h3><p>الخطوة التالية هي إنشاء تهجير لوسوم المدونة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan make:migration blog_tags</pre><p>عدل ملف التهجير كالتالي:<code> </code></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BlogTags extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('blog_tags', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('tag')-&gt;unique();
            $table-&gt;timestamps();
        });

        DB::table('blog_tags')-&gt;insert([
            'tag' =&gt; "Pink"
            ]);

        DB::table('blog_tags')-&gt;insert([
            'tag' =&gt; "T-Shirt"
            ]);
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::drop('blog_tags');
    }
}</pre><h3 id="ملف-التهجير-الخاص-بربط-المنشورات-والوسوم">ملف التهجير الخاص بربط المنشورات والوسوم</h3><p>آخر ملف من ملفات التهجير هو الملف الخاص بجدول الوسوم-المنشورات. ننشئه بالأمر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration blog_post_tags</pre><p>عدّل الملف على النحو التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BlogPostTags extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('blog_post_tags', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;unsignedInteger('post_id');
            $table-&gt;unsignedInteger('tag_id');
            $table-&gt;timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::drop('blog_post_tags');
    }
}</pre><p>أنشأنا ملفات التهجير، ننفذ أمر <code>migrate</code> لتطبيق التهجيرات:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p><strong>ملحوظة:</strong> يجب دائما البدء بتهجيرات الجداول التي لا تحتاج لجداول أخرى، بمعنى أنه لا توجد بها مفاتيح خارجية Foreign keys. لتهجير جدول به مفتاح خارجي لجدول آخر يجب أن يكون هذا الجدول الأخير قد تم إنشاؤه.</p><h3 id="بذر-جدول-منشورات-المدونة">بذر جدول منشورات المدونة</h3><p>سنستخدم مكتبة <code>Faker</code> لإضافة منشورات وهمية نختبر بها مدونتنا. نفذ الأمر التالي لإنشاء ملف بذر لمنشورات المدونة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:seeder BlogPostsTableSeeder</pre><p>افتح الملف <code>database/seeds/BlogPostsTableSeeder.php</code> وعدله ليصبح كما يلي:<code> </code></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class BlogPostsTableSeeder extends Seeder
{
    /**
    * Run the database seeds.
    *
    * @return void
    */
    public function run()
    {
        $faker = Faker\Factory::create();

        for ($i = 0; $i &lt; 10; $i++){
            DB::table('posts')-&gt;insert([ //,
                'url' =&gt; $faker-&gt;unique()-&gt;word,
                'title' =&gt; $faker-&gt;unique()-&gt;sentence($nbWords = 6),
                'description' =&gt; $faker-&gt;paragraph($nbSentences = 3),
                'content' =&gt; $faker-&gt;text,
                'image' =&gt; $faker-&gt;randomElement($array = array ('blog-one.jpg','blog-two.jpg','blog-three.jpg')),
                'blog' =&gt; '1',
                'category_id' =&gt; $faker-&gt;numberBetween($min = 1, $max = 3),
            ]);
        }
    }
}</pre><p>نولد كلمة عشوائية فريدة لاستخدامها عنوانا للمنشور:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'url' =&gt; $faker-&gt;unique()-&gt;word</pre><p>نختار صورة عشوائية من بين ثلاث صور لاستخدامها صورة للمنشور:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'image' =&gt; $faker-&gt;randomElement($array = array ('blog-one.jpg','blog-two.jpg','blog-three.jpg'))</pre><p>أنشأنا في تهجير تصنيفات المدونة ثلاثة تصنيفات، لذا سيقتصر اختيار معرفات التصنيفات على المجال [1,3]:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'category_id' =&gt; $faker-&gt;numberBetween($min = 1, $max = 3),</pre><p>سنستخدم الحقل <code>created_at</code> لعرض تاريخ المنشور في المدونة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'created_at' =&gt; $faker-&gt;dateTime($max = 'now'),</pre><p>نفذ أمر <code>artisan</code> التالي لتطبيق البذر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan db:seed --class=BlogPostsTableSeeder</pre><h3 id="بذر-جدول-الوسوم-المنشورات">بذر جدول الوسوم-المنشورات</h3><p>ننتقل الآن لبذر الجدول <code>blog_post_tags</code> الذي يُستخدَم لربط المنشورات بالوسوم.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:seeder BlogPostTagsTableSeeder</pre><p>افتح ملف البذر وعدله كالتالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class BlogPostTagsTableSeeder extends Seeder
{
    /**
    * Run the database seeds.
    *
    * @return void
    */
    public function run()
    {
        $faker = Faker\Factory::create();

        for ($i = 1; $i &lt; 11; $i++){
            DB::table('blog_post_tags')-&gt;insert([ //,
                'post_id' =&gt; $i,
                'tag_id' =&gt; $faker-&gt;numberBetween($min = 1, $max = 2),
            ]);
        }
    }
}</pre><p>أدرجنا عند بذر جدول الوسوم <code>BlogPostsTableSeeder.php</code> عشر تسجيلات فقط، لذا حرصنا ألا تتعدى قيمة معرف المنشور <code>post_id</code> في جدول الوسوم-المنشورات هذا الحد:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">for ($i = 1; $i &lt; 11; $i++)</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">بالنسبة لمعرّف الوسوم فقد حددنا المجال بـ[1,2] لأننا أثناء تهجير الوسوم أضفنا وسمين في جدول قاعدة البيانات.</span></p><p>نفذ الأمر التالي لتطبيق بذر جدول الوسوم-المنشورات:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan db:seed --class=BlogPostTagsTableSeeder</pre><h2 id="نماذج-المدونة">نماذج المدونة</h2><p>ننتقل بعد تنفيذ التهجيرات إلى إنشاء نماذج المدونة. سننشئ النماذج التالية:</p><ul><li>نموذج المنشور <code>Post</code> وسيكون مسؤولا عن التفاعل مع جدول المنشورات <code>posts</code>.</li><li>نموذج تصنيف المدونة <code>BlogCategory</code> وهو مسؤول عن التفاعل مع جدول تصنيفات المدونة <code>blog_categories</code>.</li><li>نموذج وسم المدونة <code>BlogTag</code> ويُعنى بالتخاطب مع جدول وسوم المدونة <code>blog_tags</code>.</li><li>نموذج وسم منشورات المدونة <code>BlogPostTag</code> ويتفاعل مع جدول وسوم منشورات المدونة <code>blog_post_tags</code>.</li></ul><p>نفذ الأوامر التالية لإنشاء النماذج:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:model Post
php artisan make:model BlogCategory
php artisan make:model BlogTag
php artisan make:model BlogPostTag</pre><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-r227/">درس Eloquent</a> من هذه السلسة.</p><p>نبدأ بالتعديل على النماذج.</p><h3 id="نموذج-منشور-المدونة">نموذج منشور المدونة</h3><p>سنضيف إلى مدونتنا إمكانية الانتقال إلى المنشور السابق أو التالي؛ نستخدم معرّف المنشور لتحديد المنشور السابق و التالي. ننشئ دالتين لهذا الغرض: <code>prevBlogPostURL</code> (المنشور السابق) و<code>nextBlogPostURL</code> (المنشور التالي).</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">   &lt;?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $primaryKey = 'id';
    protected $table = 'posts';
    protected $fillable = array('url', 'title', 'description','content','blog','created_at_ip', 'updated_at_ip');

    public static function prevBlogPostUrl($id) {
        $blog = static::where('id', '&lt;', $id)-&gt;orderBy('id', 'desc')-&gt;first();

        return $blog ? $blog-&gt;url : '#';
    }

    public static function nextBlogPostUrl($id) {
        $blog = static::where('id', '&gt;', $id)-&gt;orderBy('id', 'asc')-&gt;first();

        return $blog ? $blog-&gt;url : '#';
    }

    public function tags() {
        return $this-&gt;belongsToMany('App\BlogTag','blog_post_tags','post_id','tag_id');
    }

}</pre><p>استخدمنا دالتي <code>where</code> و<code>first</code>، وهما دالّتان توفرهما نماذج Eloquent، للحصول على معرّفيْ المنشورين السابق والتالي. بالنسبة لـ<code>where</code> في دالة <code>prevBlogPostUrl</code> استخدمنا عامل المقارنة <code>&gt;</code> (أصغر من) للحصول على المنشورات ذات المعرف الأصغر من معرف المنشور الحالي ثم رتبناها تنازليا (معطى <code>desc</code> في <code>orderBy</code>) وأخذنا العنصر الأول <code>first</code>.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$blog = static::where('id', '&lt;', $id)-&gt;orderBy('id', 'desc')-&gt;first();</pre><p>نفس المبدأ في دالة <code>nextBlogPostUrl</code> مع استخدام عامل المقارنة أكبر من <code>&lt;</code> والترتيب التصاعدي <code>asc</code>.</p><p>إن أردنا ترجمة التعليمة باستعلامات SQL فسنحصُل على التالي (مثال مع منشور ذي معرّف <code>3</code>):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">SELECT * FROM posts where id &lt; 3 ORDER BY id LIMIT 1;</pre><p>العلاقة بين الوسوم والمنشورات هي من النوع متعدّد إلى متعدّد Many to many: يمكن أن يوجد أكثر من وسم على المنشور، كما يمكن لوسم أن يوجد على أكثر من منشور. تُنفّذ هذه العلاقة بإدخال جدول وسيط للربط بين الجدولين <code>posts</code> و<code>blog_tags</code>.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/01_eloquent_belongstomany.png.a057f30054837b690ad49c90f7bb9519.png"><img data-fileid="10750" class="ipsImage ipsImage_thumbnailed" alt="01_eloquent_belongstomany.thumb.png.ec63" src="https://academy.hsoub.com/uploads/monthly_2016_01/01_eloquent_belongstomany.thumb.png.ec6338d2c9f52b3ffc9f4c5b8b3f1388.png"></a></p><p>استخدمنا دالة <code>belongsToMany</code> في Eloquent لتعريف علاقة من هذا النوع:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$this-&gt;belongsToMany('App\BlogTag','blog_post_tags','post_id','tag_id');</pre><p>تأخذ الدالة أربعة معطيات. الأول اسم النموذج الذي يرتبط بالنموذج الحالي بهذه العلاقة (<code>BlogTag</code>)، الثاني اسم الجدول الوسيط (<code>blog_post_tags</code>)، الثالث المفتاح الخارجي في الجدول المصدر (جدول المنشورات إذا كنا في نموذج المنشور) والرابع المفتاح الخارجي للجدول الوجهة (أي جدول الوسوم).</p><p>تعريف الدالة <code>()tags</code> واستخدام <code>belongsToMany</code> داخلها بالطريقة السالفة الذكر يجعل الحصول على وسوم منشور بسهولة كتابة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$tags = $post-&gt;tags
</pre><p>استخدام هذه الدالة يكافئ تنفيذ استعلام SQL التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">SELECT `blog_tags`.*, `blog_post_tags`.`post_id` AS `pivot_post_id`, `blog_post_tags`.`tag_id` AS `pivot_tag_id` FROM `blog_tags` INNER JOIN `blog_post_tags` ON `blog_tags`.`id` = `blog_post_tags`.`tag_id` WHERE `blog_post_tags`.`post_id` = ? ;
</pre><p>قد يقنعك النظر في الاستعلام أعلاه بجدوى استخدام نماذج Eloquent.</p><h3 id="نموذج-تصنيف-المدونة">نموذج تصنيف المدونة</h3><p>نموذج التصنيفات سهل ولا يحتاج لأي شيء خاص:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class BlogCategory extends Model
{
    protected $fillable = array('category');
}</pre><h3 id="نموذج-وسم-المدونة">نموذج وسم المدونة</h3><p>تنطبق على نموذج الوسم علاقة متعدّد إلى متعدّد التي تنطبق على نموذج المنشور، لذا سنضيف دالة <code>posts</code> إلى النموذج لتعريف العلاقة بين جدولي الوسوم والمنشورات.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class BlogTag extends Model {

    protected $fillable = array('tag');

    public function posts() {
        return $this-&gt;belongsToMany('App\Post','blog_post_tags','post_id','tag_id');
    }
}</pre><p>لاحظ استخدام <code>belongsToMany</code> بنفس طريقة استخدامها في نموذج المنشور.</p><h3 id="نموذج-وسم-منشورات-المدونة">نموذج وسم منشورات المدونة</h3><p>يمثل هذا النموذج الجدول الوسيط <code>blog_post_tags</code>.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App;

class BlogPostTag extends Model {
    protected $fillable = array('post_id', 'tag_id');
}</pre><h2 id="دوال-المتحكم-الخاصة-بالمدونة">دوال المتحكم الخاصة بالمدونة</h2><p>توجد في المتحكم <code>Front</code> دالتان تختصان بالمدونة: <code>blog</code> و<code>blog_post</code>.</p><p>أضف السطر التالي لاستيراد نوذج المنشور <code>Post</code> إلى المتحكم:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">use App\Post;</pre><h3 id="دالة-blog">دالة Blog</h3><p>تُستخدَم هذه الدالة لعرض صفحة المدونة وإظهار جميع منشوراته. إذا كان عدد المنشورات كبيرا فسيكون من العبث عرضُها دفعةَ واحدة، لذا سنستخدم التّصفيح Pagination (عرض عدد محدود من المنشورات في كل صفحة). يدعم Eloquent إعداد الصفحات:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">public function blog() {

    $posts = Post::where('id', '&gt;', 0)-&gt;paginate(3);
    $posts-&gt;setPath('blog');

    $data['posts'] = $posts;

    return view('blog', array('data' =&gt; $data, 'title' =&gt; 'Latest Blog Posts', 'description' =&gt; '', 'page' =&gt; 'blog', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}</pre><p>نبحث عن منشورات المدونة ثم نُعِدّ صفحاتها، نحدّد عدد المنشورات في كل صفحة بثلاثة منشورات:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$posts = Post::where('id', '&gt;', 0)-&gt;paginate(3);</pre><p>نحدّد الرابط الخاص بإعداد الصفحات، اخترنا الرابط <code><a rel="external nofollow" href="http://larashop.dev/blog">http://larashop.dev/blog</a></code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$posts-&gt;setPath('blog');</pre><p>ثم نحتفظ بالنتائج في المصفوفة <code>data</code> التي سنمررها إلى العرض.</p><h3 id="دالة-blogpost">دالة Blog_post</h3><p>تتلقى هذه الدالة رابطا ثم تعثر على منشور اعتمادا على الرابط الممرّر إليها:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public function blog_post($url) {
    $post = Post::where('url', '=' , $url)-&gt;first();

        $previous_url = Post::prevBlogPostUrl($post-&gt;id);
        $next_url = Post::nextBlogPostUrl($post-&gt;id);

        $data['tags'] = $post-&gt;tags;
        $data['title'] = $post-&gt;title;
        $data['description'] = $post-&gt;description;
        $data['content'] = $post-&gt;content;
        $data['blog'] = $post-&gt;blog;
        $data['created_at'] = $post-&gt;created_at;
        $data['image'] = $post-&gt;image;
        $data['previous_url'] = $previous_url;
        $data['next_url'] = $next_url;


    return view('blog_post', array('data' =&gt; $data, 'page' =&gt; 'blog'));</pre><p>لاحظ استخدام الدالة <code>tags</code> التي عرفناها في النموذج <code>Post</code>.</p><h2 id="عروض-المدونة">عروض المدونة</h2><p>توجد عروض المدونة في <a class="ipsAttachLink" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=10752">الملف المرفق</a>. يتعلق الأمر بالعرضين <code>blog.blade.php</code> و <code>blog_post.blade.php</code> الذي عُدّل عليهما لعرض البيانات الممرّرة. لا توجد تعليمات جديدة علينا في العرضين سوى التعليمة</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">{!! $data['posts']-&gt;render() !!}</pre><p>تعمل هذه التعليمة على ترقيم الصفحات لتسهيل تصفح منشورات المدونة.</p><p>تذكر أننا في الدالة <code>blog</code> كتبنا التعليمة التالية</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$posts = Post::where('id', '&gt;', 0)-&gt;paginate(3);</pre><p>لإعداد الصفحات بحيث تُنشَر كل ثلاثة منشورات دفعة واحدة مع إتاحة التنقل إلى بقية المنشورات. تنشئ الدالة <code>render</code> في قالب Blade روابط من شكل <code><a rel="external nofollow" href="http://laravel.dev/blog?page=X">http://laravel.dev/blog?page=X</a></code> حيث <code>X</code> رقم الصفحة.</p><p>بما أننا بذرنا عشرة منشورات فسيكون لدينا أربع صفحات (3 منشورات في كل من الصفحات 1 إلى 3، ومنشور واحد في الصفحة الرابعة، الأخيرة).</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/02_laravel_blog_pagination.png.242e3bfa7d961d3e7480b0735c4ac6b5.png"><img data-fileid="10751" class="ipsImage ipsImage_thumbnailed" alt="02_laravel_blog_pagination.thumb.png.1de" src="https://academy.hsoub.com/uploads/monthly_2016_01/02_laravel_blog_pagination.thumb.png.1de50ee0a0578433e7833a3579719f50.png"></a></p><p>الملف المرفق:  <a class="ipsAttachLink" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=10752">عروض المدونة</a>.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-blog-tutorial">Laravel 5 Blog Tutorial</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">231</guid><pubDate>Tue, 26 Jan 2016 19:07:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x648;&#x627;&#x62C;&#x647;&#x629; &#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; API &#x641;&#x64A; Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-api.png.b6685ff3b07e5a63e9e4692081044274.png" /></p>

<p>توفر الكثير من المواقع واجهات برمجية Application Programming Interface ،<abbr title="واجهة برمجية | Application Programming Interface">API</abbr> بهدف إتاحة موارد الموقع لتطبيقات خارجية؛ قد تكون تطبيقات ٍللجوال، أجهزةً لوحية، أو أجهزةً مكتبية. قد نود مثلا إنشاء تطبيق للجوال نعرض فيه منتجات الموقع. نستخدم لغة البرمجة المناسبة للتطبيق (جافا مثلا لتطبيقات أندرويد) الذي يرسل طلبات لواجهتنا البرمجية يحصُل بموجبها على بيانات يتولى هو طريقة عرضها. نقول إن تطبيق الجوال في هذه الحالة يستهلك Consume الواجهة البرمجية.</p><p id="مقدمة">هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>. </li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>. </li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>. </li><li>إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel. <span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-api.png.9dad3ddc37646c0981c402ca4b4f3d19.png"><img data-fileid="11837" class="ipsImage ipsImage_thumbnailed" alt="laravel5-api.thumb.png.f2b399e93f114fb8d" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-api.thumb.png.f2b399e93f114fb8d7ce95e587bb3dd3.png"></a></p><p>نغطي في هذا الدرس المواضيع التالية:</p><ul><li>ماهي واجهات REST البرمجية؟</li><li>الممارسات المنصوح بها في واجهات REST البرمجية.</li><li>إنشاء واجهة برمجية لمشروع Larashop.</li></ul><h2 id="ماهي-واجهات-rest-البرمجية">ماهي واجهات REST البرمجية؟</h2><p>توصف الكثير من الواجهات البرمجية بأنها RESTful، فما المقصود بهذا الوصف؟</p><p>تختصر REST العبارة Representational State Transition (النقل التمثيلي للحالة) وهي طريقة لتصميم البرمجيات تعرِّف معاييرَ يجب على خدمات الويب اتباعها من أجل أداء أعلى وصيانة أسهل. تعتمد بنية التطبيقات REST على بروتوكول HTTP لإرسال الطلبات والحصول على إجابات؛ ومن أهم القيود التي يجب الالتزام بها في تطبيقات REST: العمل حسب مبدأ خادوم-عميل Server-Client، انعدام الحالة Stateless وتوحيد الواجهات (إضافة لقيود أخرى).</p><ul><li><strong>مبدأ خادوم-عميل</strong>: يجب التفريق بين واجهة المستخدم والخادوم الذي يخزن البيانات ويطبق العمليات عليها.</li><li><strong>انعدام الحالة</strong>: يجب أن يحوي الطلب الموجّه من العميل إلى الخادوم كل المعلومات الضرورية ليستطيع الخادوم فهمه والإجابة عليه؛ دون الحاجة لسياق محفوظ على الخادوم (لفهم الطلب).</li><li><strong>توحيد الواجهات</strong> بمعنى أن كل مورد على الخادوم يمكن تعريفه فرديا واستغلاله عبر بيانات تمثله يحتفظ بها العميل. يجب أن تكون الطلبات واضحة يمكن فهمها والإجابة عنها دون الحاجة لمعلومات خارجة عنها. يدخل ضمن توحيد الواجهات أيضا افتراضُ العميل أن أي إجراء Action غيرُ متوفر على الخادوم، ما لم يصّرح هذا الأخير بتوفره.</li></ul><p>تساهم هذه القيود (والقيود الأخرى التي تعرفها بنية REST) في تسهيل عمل الواجهات، الرفع من أدائها، تيسير الصيانة وقابلية التمدد Scalability. سنرى في الفقرة التالية توصيات لبناء واجهات برمجية تساعد في احترام مبادئ REST.</p><p><strong>ملحوظة:</strong> يكثُر وصف الواجهات البرمجية بأنها RESTful (تلتزم بقيود REST) دون أن تلتزم بكامل القيود التي تعرِّفها بنية REST، وهو ما يجعلها أقرب لواجهات شبيهة لـREST منها لواجهات RESTful.</p><h2 id="الممارسات-المنصوح-بها-في-واجهات-rest-البرمجية">الممارسات المنصوح بها في واجهات REST البرمجية</h2><p>يُساعد الالتزام بالممارسات التالية في بناء واجهة تطبيقات برمجية ذات أداء عال وقابلية كبيرة للتمدد والصيانة.</p><ul><li><strong>استخدام إجراءات HTTP لتحديد العمل الذي سيؤديه الخادوم</strong>: GET للحصول على مورد، POST لإنشاء مورد جديد، PUT لتحديث مورد وDELETE لحذفه.</li><li><strong>أَصْدَرَة Versioning الواجهة</strong>: يساعد استخدام إصدارات في عدم كسر التطبيقات التي تستهلك الواجهة البرمجية. يحدّد العميل إصدار واجهة التطبيق الذي يود العمل عليه مما يسمح بإحداث تغييرات على الخادوم تضمَّن في إصدار جديد دون أن يتوقف عملاء الواجهة البرمجية.</li><li>من المتعارف عليه <strong>استخدام أسماء جموع لوصف الموارد</strong>، <code><abbr title="واجهة برمجية | Application Programming Interface">api</abbr>.mysite/v1/products</code> مثلا للمنتجات. ليس واجبا اتباع هذا العرف لكن الأهم هو تناسق تسمية الموارد: لا تخلط بين أسماء مفردة للموارد وجموع.</li><li><strong>استخدام الإجابات الجزئية</strong>: طلب العميل اسم المنتج؟ أرسل اسم المنتج فقط، وليس كامل بيانات المنتج، في الإجابة.</li><li><strong>استخدام رموز الحالة</strong>: تسهّل رموز الحالة في HTTP التخاطب مع العميل. عولج الطلب على النحو الأمثل؟ أرسِل الرمز <code>200</code> في الإجابة. طلب العميل إنشاء مورد وتم الأمر؟ أرسل الرمز <code>201</code> في الإجابة؛ وهكذا. راجع <a href="https://academy.hsoub.com/programming/general/%D8%B1%D9%85%D9%88%D8%B2-%D8%A7%D9%84%D8%A5%D8%AC%D8%A7%D8%A8%D8%A9-%D9%81%D9%8A-http-r75/">هذا الرابط</a> للمزيد من رموز الحالة في HTTP.</li><li><strong>ضع حدًّا أقصى لعدد الطلبات القادمة من نفس عنوان IP في الواجهات المفتوحة للجميع</strong>. يساعد هذا الأمر في التصدي للعملاء الذي يفرطون في استخدام واجهة تطبيقاتك البرمجية. ينصح أيضا بحظر عناوين IP ذات السلوك المشبوه حتى لا يؤثر على بقية المستخدمين.</li><li>قد يُختلف حول هذه التوصية، إلا أنه <strong>يُنصح باستخدام صيغة <code>JSON</code> لإرسال البيانات في الإجابة عن الطلب</strong>، ما لم يحدّد العميل عكس ذلك.</li><li><strong>خبِّئ Cache نتائج طلبات <code>GET</code> التي لا تتغير كثيرا</strong>. ربما تكون قائمة العلامات التجارية في مواقع التسوق مثالا جيدا للبيانات التي يجب تخبئتها (قد تمضي أشهر دون الحاجة لإضافة علامة تجارية جديدة).</li></ul><h2 id="واجهة-larashop-البرمجية">واجهة Larashop البرمجية</h2><p>سننشئ في هذه الفقرة واجهة تطبيقات برمجية لمشروع Larashop. تشتمل الواجهة على المسارات أدناه. تستخدم جميع المسارات إجراء <code>GET</code> للحصول على المورد.</p><table><tbody><tr><th>التسلسل   </th><th>المورد           </th><th>الرابط                            </th><th>الوصف                                        </th><th>رمز الحالة</th></tr><tr><td>1</td><td>Product</td><td>/<abbr title="واجهة برمجية | Application Programming Interface">api</abbr>/v1/products</td><td>سرد لائحة بالمنتجات وخاصياتها</td><td>200</td></tr><tr><td>2</td><td>Product</td><td>/<abbr title="واجهة برمجية | Application Programming Interface">api</abbr>/v1/products/1</td><td>سرد خاصيات المنتج رقم 1</td><td>200</td></tr><tr><td>3</td><td>Category</td><td>/<abbr title="واجهة برمجية | Application Programming Interface">api</abbr>/v1/categories</td><td>سرد لائحة بتصنيفات المنتجات</td><td>200</td></tr><tr><td>4</td><td>Category</td><td>/<abbr title="واجهة برمجية | Application Programming Interface">api</abbr>/v1/categories/1</td><td>التصنيف ذو المعرّف 1</td><td>200</td></tr></tbody></table><p>لاحظ أننا لم نتح إمكانية التعديل على الموارد عبر الواجهة. تشير <code>v1</code> في المسارات إلى رقم الإصدار <code>1</code>.</p><p>نفتح ملف المسارات <code>routes.php</code> ونعدّله بإضافة المسارات التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">// API routes...
Route::get('/api/v1/products/{id?}', ['middleware' =&gt; 'auth.basic', function($id = null) {
if ($id == null) {
    $products = App\Product::all(array('id', 'name', 'price'));
} else {
    $products = App\Product::find($id, array('id', 'name', 'price'));
}
return Response::json(array(
            'error' =&gt; false,
            'products' =&gt; $products,
            'status_code' =&gt; 200
        ));
}]);

Route::get('/api/v1/categories/{id?}', ['middleware' =&gt; 'auth.basic', function($id = null) {
if ($id == null) {
    $categories = App\Category::all(array('id', 'name'));
} else {
    $categories = App\Category::find($id, array('id', 'name'));
}
return Response::json(array(
            'error' =&gt; false,
            'user' =&gt; $categories,
            'status_code' =&gt; 200
        ));
}]);</pre><p>يعرف المسار</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/api/v1/products/{id?}', ['middleware' =&gt; 'auth.basic', function($id = null)</pre><p>رابطًا يطلب المنتجات مع معرّف اختياري <code>id</code>. يُستخدم المعرف لطلب منتج واحد وفي حال عدم ذكره ترجِع واجهة التطبيقات جميع المنتجات. نحمي المورد بالتعليمة <code>'middleware' =&gt; 'auth.basic'</code> التي تستوثق من العميل. حددنا نمط الاستيثاق بـ<code>auth.basic</code> لاستخدام بريد المستخدِم (حقل <code>email</code> في جدول <code>users</code>) مع كلمة السر.<br>يستدعي كل مسار النموذج المناسب للعثور على البيانات في القاعدة ثم نرسل الإجابة بصيغة <code>JSON</code> بالتعليمة <code>Response::json</code>.</p><p>عند طلب الرابط <code><a rel="external nofollow" href="http://larashop.dev/api/v1/products">http://larashop.dev/<abbr title="واجهة برمجية | Application Programming Interface">api</abbr>/v1/products</a></code> ستظهر نافذة تطلب إدخال بريد المستخدم وكلمة سره.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/01_api_rest_authentication.png.581c8d712154e8f0fd67dbb9456019f5.png"><img data-fileid="10757" class="ipsImage ipsImage_thumbnailed" alt="01_api_rest_authentication.thumb.png.909" src="https://academy.hsoub.com/uploads/monthly_2016_01/01_api_rest_authentication.thumb.png.90999921f9d3fad570c85f815ef297d2.png"></a></p><p>استخدم الحساب الذي أنشأته في درس الاستيثاق وستظهر النتيجة التالية في المتصفح (بعد التنسيق)</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">{
"error":false,
"products":
    [
        {
            "id":"1",
            "name":"Mini skirt black edition",
            "price":"35"
        },
        {
            "id":"2",
            "name":"T-shirt blue edition",
            "price":"64"
        },
        {
            "id":"3",
            "name":"Sleeveless Colorblock Scuba",
            "price":"13"
        }
    ],
    "status_code":200
}</pre><p>حصلنا على إجابة بصيغة <code>JSON</code> للطلب الذي أرسلناه من أجل الحصول على منتجات الموقع. يشير الرمز <code>200</code> إلى أن معالجة الطلب تمّت دون مشاكل. يمكن للعميل الآن تنسيق الإجابة لعرضها بطريقة مناسبة.</p><h2 id="خاتمة">خاتمة</h2><p>وضعنا في هذا الدرس أساسا يمكن البناء عليه لإنشاء واجهات برمجية أكثر تطورا. يتلخص إنشاء واجهات برمجية في Laravel في تعريف المسارات، استخدام النماذج للحصول على البيانات المطلوبة ثم تهيئة الإجابة بصيغة <code>JSON</code> ثم إرسالها.</p><p>ترجمة -وبتصرّف- للمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-rest-api">Laravel 5 REST <abbr title="واجهة برمجية | Application Programming Interface">API</abbr></a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">232</guid><pubDate>Sun, 24 Jan 2016 16:45:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x64A;&#x62B;&#x627;&#x642; &#x627;&#x644;&#x645;&#x633;&#x62A;&#x62E;&#x62F;&#x645;&#x64A;&#x646;  (User Authentication) &#x641;&#x64A; Laravel 5</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-user-auth.png.1c2f1b566c9fc517674e903505062149.png" /></p>

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

<p id="مقدمة">
	هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:
</p>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/" rel="">مدخل إلى Laravel 5</a>.
	</li>
	<li>
		<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="">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.
	</li>
	<li>
		<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</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/" rel="">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.
	</li>
	<li>
		<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>.
	</li>
	<li>
		<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="">تهجير قواعد البيانات في Laravel</a>. 
	</li>
	<li>
		<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 لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>. 
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/" rel="">إنشاء سلة مشتريات في Laravel</a>.
	</li>
	<li>
		الاستيثاق في Laravel. <span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/" rel="">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> في Laravel</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/" rel="">إنشاء مدوّنة باستخدام Laravel</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/" rel="">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.
	</li>
	<li>
		<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="">الدوّال المساعدة المخصّصة في Laravel</a>.
	</li>
	<li>
		<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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/" rel="">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-user-auth.png.be2011a82e96a590f138c099f686682a.png" data-fileid="11591" rel=""><img alt="laravel5-user-auth.png" class="ipsImage ipsImage_thumbnailed" data-fileid="11591" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-user-auth.thumb.png.a7cf371fda8a81a29f29e868e6e13873.png"></a>
</p>

<p>
	يغطي الدرس المواضيع التالية:
</p>

<ul>
<li>
		إعداد الاستيثاق في Laravel 5.
	</li>
	<li>
		أساسيات الاستيثاق في Laravel 5.
	</li>
	<li>
		تغيير رابط تسجيل الدخول المبدئي.
	</li>
</ul>
<h2 id="إعدادات-الاستيثاق-في-laravel-5">
	إعدادات الاستيثاق في Laravel 5
</h2>

<p>
	يوجد ملف إعداد الاستيثاق على المسار <code>config/auth.php</code>. في ما يلي جزء من الملف:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
'model' =&gt; App\User::class,
'table' =&gt; 'users',
'password' =&gt; [
        'email' =&gt; 'emails.password',
        'table' =&gt; 'password_resets',
        'expire' =&gt; 60,
    ],</pre>

<p>
	يحدّد الملف:
</p>

<ul>
<li>
		اسم نموذج الاستيثاق.
	</li>
	<li>
		اسم جدول المستخدمين.
	</li>
	<li>
		خيارات إعادة تعيين كلمة السر.
	</li>
</ul>
<p>
	سنستخدم النموذج <code>User</code> لاستيثاق المستخدمين. افتح الملف <code>User.php</code> وعدّله على النحو التالي:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
&lt;?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class User extends Model implements AuthenticatableContract

{
    use Authenticatable;

    /**
    * The database table used by the model.
    *
    * @var string
    */
    protected $table = 'users';

    /**
    * The attributes that are mass assignable.
    *
    * @var array
    */
    protected $fillable = ['name', 'email', 'password'];

    /**
    * The attributes excluded from the model's JSON form.
    *
    * @var array
    */
    protected $hidden = ['password', 'remember_token'];
}</pre>

<p>
	فلنعرّج قليلا على الأصناف الجديدة علينا:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;</pre>

<p>
	توجد في Laravel أصناف يطلق عليها اسم العقود Contracts. العقود هي مجموعة واجهات Interfaces تعرّف خدمات يوفّرها إطار العمل. تعرّف العقود دوال يحتاجها إطار العمل لتأدية الخدمة. يستورد السطر أعلاه العقد <code>Authenticatable</code> وهي واجهة تعرّف الدوال الضرورية لاستيثاق المستخدمين. عند استيراد الواجهة أعطيناها الاسم <code>AuthenticatableContract</code> حتى لا تختلط مع السمة Trait الذي يحمل نفس الاسم (نستعمله في نموذج المستخدم كما سنرى لاحقا).
</p>

<p>
	يجب على الكائن الذي يستوثق من المستخدمين (نموذج المستخدم في حالتنا) أن ينجز Implement هذه الواجهة:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
class User extends Model implements AuthenticatableContract</pre>

<p>
	لإنجاز دوال الواجهة (تعرّف واجهة <code>Authenticatable</code> الدوال دون أن تنجزها) نستخدم السمة <code>Illuminate\Auth\Authenticatable</code>.
</p>

<p>
	نستورده أولا:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
use Illuminate\Auth\Authenticatable;</pre>

<p>
	ثم نستخدمه:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
use Authenticatable;</pre>

<ul>
<li>
		يحدّد النموذج جدول البيانات المستخدم لتخزين بيانات المسجَّلين، ويفعّل الإسناد الشامل لبعض الحقول.
	</li>
	<li>
		تعيّن مصفوفة <code>hidden$</code> بيانات المستخدم التي لا نودّ عرضها عند الإجابة على طلب عبر واجهة تطبيقات برمجية <abbr title="واجهة برمجية | Application Programming Interface"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> (يجب إخفاء كلمة سر المستخدم <code>password</code> ورمز الأمان <code>remember_token</code> عن الخارج).
	</li>
</ul>
<p>
	يأتي مع Laravel مبدئيا ملف تهجير لإنشاء جدول المستخدمين. افتح ملف التهجير <code>2014_10_12_000000_create_users_table.php</code> (قد يختلف الختم الزمني في اسم الملف حسب إصدار Laravel):
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name');
            $table-&gt;string('email')-&gt;unique();
            $table-&gt;string('password', 60);
            $table-&gt;rememberToken();
            $table-&gt;timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::drop('users');
    }
}</pre>

<p>
	يعرّف ملف التهجير حقول جدول المستخدمين. تعيّن الدالة <code>rememberToken</code> رمز حماية لتأمين المستخدمين ضدّ هجمات تزوير الطلب عبر الموقع CSRF.
</p>

<h2 id="استمارات-التسجيل-والولوج-login">
	استمارات التسجيل والولوج Login
</h2>

<p>
	يوجد في عرض الدخول <code>login.blade.php</code> استمارتان، واحدة لتسجيل المستخدمين Registration والأخرى لدخولهم Login. افتح ملف العرض <code>login</code> وحدّثه على النحو التالي:
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
@extends('layouts.layout')

@section('content')       
    &lt;section id="form"&gt;&lt;!--form--&gt;
            &lt;div class="container"&gt;
                &lt;div class="row"&gt;
                    &lt;div class="col-sm-4 col-sm-offset-1"&gt;
                        &lt;div class="login-form"&gt;&lt;!--login form--&gt;
                            &lt;h2&gt;Login to your account&lt;/h2&gt;
                            &lt;form method="POST" action="{{url('auth/login')}}"&gt;
                                {!! csrf_field() !!}
                                &lt;input type="email" name="email" id="email" placeholder="Email Address" /&gt;
                                &lt;input type="password" name="password" id="password" placeholder="Password" /&gt;
                                &lt;span&gt;
                                    &lt;input name="remember" id="remember" type="checkbox" class="checkbox"&gt; 
                                    Keep me signed in
                                &lt;/span&gt;
                                &lt;button type="submit" class="btn btn-default"&gt;Login&lt;/button&gt;
                            &lt;/form&gt;
                        &lt;/div&gt;&lt;!--/login form--&gt;
                    &lt;/div&gt;
                    &lt;div class="col-sm-1"&gt;
                        &lt;h2 class="or"&gt;OR&lt;/h2&gt;
                    &lt;/div&gt;
                    &lt;div class="col-sm-4"&gt;
                        &lt;div class="signup-form"&gt;&lt;!--sign up form--&gt;
                            &lt;h2&gt;New User Signup!&lt;/h2&gt;
                            &lt;form method="POST" action="{{url('register')}}"&gt;
                                {!! csrf_field() !!}
                                &lt;input type="text" name="name" id="name"  placeholder="Name"&gt;
                                &lt;input type="email" name="email" placeholder="Email Address"/&gt;
                                &lt;input type="password" name="password" placeholder="Password"&gt;
                                &lt;button type="submit" class="btn btn-default"&gt;Signup&lt;/button&gt;
                            &lt;/form&gt;
                        &lt;/div&gt;&lt;!--/sign up form--&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/section&gt;&lt;!--/form--&gt;
@endsection
</pre>

<pre>
<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">التغييرات الأساسية هنا هي:</span>
</pre>

<ul>
<li>
		تعريف رابط مناسب لاستمارتي التسجيل والدخول مع تحديد أن البيانات تُرسَل بإجراء <code>POST</code>:
	</li>
</ul>
<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
// دخول المستخدمين

&lt;form method="POST" action="{{url('auth/login')}}"&gt; 

// تسجيل المستخدمين 
&lt;form method="POST" action="{{url('register')}}"&gt;

</pre>

<p>
	<span style="line-height: 1.6;">تُرسل بيانات الدخول إلى الرابط </span><code style="line-height: 1.6;">larashop.dev/auth/login</code><span style="line-height: 1.6;"> وبيانات التسجيل إلى الرابط </span><code style="line-height: 1.6;">larashop.dev/register</code><span style="line-height: 1.6;">.</span>
</p>

<ul>
<li>
		تضيف التعليمة <code>()csrf_field</code> حقلا أمنيا في الاستمارتين للحيلولة دون هجمات CSRF.
	</li>
</ul>
<h2 id="مسارات-الدخول-الخروج-والتسجيل">
	مسارات الدخول، الخروج والتسجيل
</h2>

<p>
	نضيف الآن المسارات الخاصة بالاستيثاق. افتح ملف المسارات <code>routes.php</code> وأضف المسارات التالية:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
// مسارات الدخول والخروج
Route::get('auth/login', 'Front@login');
Route::post('auth/login', 'Front@authenticate');
Route::get('auth/logout', 'Front@logout');

// مسار التسجيل
Route::post('/register', 'Front@register');</pre>

<p>
	نعرّف المسار الذي يعرض استمارتي التسجيل والدخول:<code> </code>
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
Route::get('auth/login', 'Front@login');</pre>

<p>
	نعرّف إجراء <code>HTTP POST</code> الذي يوثّق المستخدمين:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
Route::post('auth/login', 'Front@authenticate');</pre>

<p>
	نعرّف مسار خروج المستخدم:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
Route::get('auth/logout', 'Front@logout');</pre>

<p>
	نعرف مسار تسجيل المستخدمين الجدد (إجراء <code>HTTP POST</code>):
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
Route::post('/register', 'Front@register'); </pre>

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

<p>
	مسار محمي هو مسار يطلُب من الزائر الدخول قبل الوصول إليه. سنحمي في هذه الفقرة الرابط <code><a href="http://larashop.dev/checkout" rel="external nofollow">http://larashop.dev/checkout</a></code>. يعني هذا أن المستخدمين المسجّلين فقط يمكنهم رؤية صفحة الدفع.
</p>

<p>
	عدّل مسار <code>checkout/</code> في ملف المسارات ليصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint" data-pbcklang="" data-pbcktabsize="">
Route::get('/checkout', [
    'middleware' =&gt; 'auth',
    'uses' =&gt; 'Front@checkout'
]);</pre>

<p>
	تُنفّذ التعليمة
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
'middleware' =&gt; 'auth', </pre>

<p>
	<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">قبل دالة </span><code style="line-height: 1.6;">Front@checkout</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">؛ وتتحقق من دخول الزائر. فإن لم يكن سجّل دخوله توجّهه إلى الرابط </span><code style="line-height: 1.6;">auth/login/</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">، وتعرض له صفحة الدفع بعد الدخول.</span>
</p>

<h2 id="دوال-التسجيل-والاستيثاق">
	دوال التسجيل والاستيثاق
</h2>

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

<p>
	نبدأ باستيراد فضاءات الأسماء التي نحتاجها:
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
use App\User;
use Illuminate\Support\Facades\Auth;</pre>

<p>
	استوردنا نموذج المستخدم <code>User</code> وفضاء الأسماء الخاص بالاستيثاق <code>Auth</code>. توجد في فضاء الأسماء <code>Auth</code> الدوال والكائنات التي نحتاجها للاستيثاق من المستخدمين.
</p>

<h3 id="تسجيل-مستخدم-جديد">
	تسجيل مستخدم جديد
</h3>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
public function register() {
    if (Request::isMethod('post')) {
        User::create([
                    'name' =&gt; Request::get('name'),
                    'email' =&gt; Request::get('email'),
                    'password' =&gt; bcrypt(Request::get('password')),
        ]);
    } 

    return Redirect::away('login');
}</pre>

<p>
	تستخدم دالة التسجيل المعلومات المذكورة في استمارة التسجيل <code>New User Signup!</code> لإنشاء مستخدم جديد عبر طلب الدالة <code>User::create</code> (تعرّفنا على هذه الدالة خلال درس <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-r227/#%D8%A5%D8%AF%D8%B1%D8%A7%D8%AC-%D8%AA%D8%B3%D8%AC%D9%8A%D9%84%D8%A9" rel="">Eloquent ORM</a>). ثم نوجّه الزائر بعد إلى صفحة الدخول. لاحظ استخدام الدالة <code>bcrypt</code> أثناء تسجيل المستخدم. تعمّي هذه الدالة كلمة السر قبل تخزينها في جدول البيانات.
</p>

<p>
	الاستيثاق من المستخدمين
</p>

<p>
	تستوثق الدالة التالية من المستخدمين:
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
public function authenticate() {
    if (Auth::attempt(['email' =&gt; Request::get('email'), 'password' =&gt; Request::get('password')])) {
        return redirect()-&gt;intended('checkout');
    } else {
        return view('login', array('title' =&gt; 'Welcome', 'description' =&gt; '', 'page' =&gt; 'home'));
    }
}</pre>

<p>
	ستوثق الدالة <code>Auth::attempt</code> من المستخدم بناء على عنوان البريد <code>email</code> وكلمة السر <code>password</code> الذين أرسلتهما استمارة الدخول. في حال نجاح دخول المستخدم يُعاد توجيهه إلى صفحة الدفع <code>checkout</code> عبر الدالة <code>()redirect</code>.
</p>

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

<p>
	يؤدي طلب الدالة <code>Auth::logout</code> إلى تسجيل خروج المستخدمين بعد دخولهم عبر الدالة السابقة. عدّل دالة <code>logout</code> الموجودة في ملف المتحكم لتصبح كالتالي:
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
public function logout() {
    Auth::logout();

    return Redirect::away('auth/login');
}</pre>

<p>
	تخرج الدالة المستخدم وتوجهه إلى صفحة الدخول.
</p>

<h2 id="إظهار-بيانات-الدخول-في-العرض">
	إظهار بيانات الدخول في العرض
</h2>

<p>
	نحتاج، قبل اختبار التسجيل والدخول، إجراء تغيير أخير. تُظهر الصورة التالية الشريط العلوي الأيمن من الموقع:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_before_login.png.7de65414ead57c444a5c1ff41b2a7631.png" data-fileid="10521" rel=""><img alt="01_before_login.png" class="ipsImage ipsImage_thumbnailed" data-fileid="10521" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_before_login.thumb.png.af4ea838c754c9833e67068a3943f0ff.png"></a>
</p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_after_login.png.e1452a92c6eb0ae826f0da7a1f22c468.png" data-fileid="10522" rel=""><img alt="02_after_login.png" class="ipsImage ipsImage_thumbnailed" data-fileid="10522" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_after_login.thumb.png.607d8e15bce850be2c6c6063c80c9ce9.png"></a>
</p>

<p>
	نريد أن يظهر اسم المستخدم بعد الدخول، وإبدال رابط <code>Login</code> بـ<code>Logout</code>.
</p>

<p>
	افتح ملف العرض <code>layout.blade.php</code> للتعديل عليه. تذكر أن هذا هو العرض الرئيس الذي تمدّده بقية العروض. نغيّر جزئية الترويسة (<code>header</code>) من ملف العرض لتصبح كالتالي:<code> </code>
</p>

<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
&lt;header id="header"&gt;&lt;!--header--&gt;
        &lt;div class="header_top"&gt;&lt;!--header_top--&gt;
            &lt;div class="container"&gt;
                &lt;div class="row"&gt;
                    &lt;div class="col-sm-6"&gt;
                        &lt;div class="contactinfo"&gt;
                            &lt;ul class="nav nav-pills"&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-phone"&gt;&lt;/i&gt; +2 95 01 88 821&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-envelope"&gt;&lt;/i&gt; info@domain.com&lt;/a&gt;&lt;/li&gt;
                            &lt;/ul&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class="col-sm-6"&gt;
                        &lt;div class="social-icons pull-right"&gt;
                            &lt;ul class="nav navbar-nav"&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-facebook"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-twitter"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-linkedin"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-dribbble"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-google-plus"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;
                            &lt;/ul&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;&lt;!--/header_top--&gt;

        &lt;div class="header-middle"&gt;&lt;!--header-middle--&gt;
            &lt;div class="container"&gt;
                &lt;div class="row"&gt;
                    &lt;div class="col-sm-4"&gt;
                        &lt;div class="logo pull-left"&gt;
                            &lt;a href="{{url('')}}"&gt;&lt;img src="{{asset('images/home/logo.png')}}" alt="" /&gt;&lt;/a&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class="col-sm-8"&gt;
                        &lt;div class="shop-menu pull-right"&gt;
                            &lt;ul class="nav navbar-nav"&gt;
                                &lt;li&gt;&lt;a href="#"&gt;&lt;i class="fa fa-user"&gt;&lt;/i&gt; {{Auth::check() ? Auth::user()-&gt;name : 'Account'}}&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="{{url('checkout')}}"&gt;&lt;i class="fa fa-crosshairs"&gt;&lt;/i&gt; Checkout&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="{{url('cart')}}"&gt;&lt;i class="fa fa-shopping-cart"&gt;&lt;/i&gt; Cart&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="{{Auth::check() ? url('auth/logout') : url('auth/login')}}"&gt;&lt;i class="fa fa-lock"&gt;&lt;/i&gt; {{Auth::check() ? 'Logout' : 'Login'}}&lt;/a&gt;&lt;/li&gt;
                            &lt;/ul&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;&lt;!--/header-middle--&gt;

        &lt;div class="header-bottom"&gt;&lt;!--header-bottom--&gt;
            &lt;div class="container"&gt;
                &lt;div class="row"&gt;
                    &lt;div class="col-sm-9"&gt;
                        &lt;div class="navbar-header"&gt;
                            &lt;button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"&gt;
                                &lt;span class="sr-only"&gt;Toggle navigation&lt;/span&gt;
                                &lt;span class="icon-bar"&gt;&lt;/span&gt;
                                &lt;span class="icon-bar"&gt;&lt;/span&gt;
                                &lt;span class="icon-bar"&gt;&lt;/span&gt;
                            &lt;/button&gt;
                        &lt;/div&gt;
                        &lt;div class="mainmenu pull-left"&gt;
                            &lt;ul class="nav navbar-nav collapse navbar-collapse"&gt;
                                &lt;li&gt;&lt;a href="{{url('')}}" {{$page == 'home' ? 'class=active' : ''}}&gt;Home&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="{{url('products')}}" {{$page == 'products' ? 'class=active' : ''}}&gt;Products&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="{{url('blog')}}" {{$page == 'blog' ? 'class=active' : ''}}&gt;Blog&lt;/a&gt;&lt;/li&gt;
                                &lt;li&gt;&lt;a href="{{url('contact-us')}}" {{$page == 'contact_us' ? 'class=active' : ''}}&gt;Contact Us&lt;/a&gt;&lt;/li&gt;
                            &lt;/ul&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class="col-sm-3"&gt;
                        &lt;div class="search_box pull-right"&gt;
                            &lt;input type="text" placeholder="Search"/&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;&lt;!--/header-bottom--&gt;
    &lt;/header&gt;&lt;!--/header--&gt;</pre>

<p>
	أضفنا التغييرين التاليين على ترويسة العرض:
</p>

<ol>
<li>
		<p>
			إبدال <code>Account</code> بالتعليمة:
		</p>

		<pre class="html ipsCode prettyprint" data-pbcklang="html" data-pbcktabsize="4">
{{Auth::check() ? Auth::user()-&gt;name : ‘Account’}}</pre>

		<p>
			نستعمل الدالة <code>Auth::check</code> للتحقق من دخول المستخدم؛ في حال الإيجاب نظهر اسمه بالدالة <code>Auth::user</code> وإلا نبقي على عبارة <code>Account</code>.
		</p>
	</li>
	<li>
		نفس المبدأ مع عبارة <code>Login</code> التي تصبح بعد الدخول <code>Logout</code>، وتغيير الرابط بما يُناسب (<code>larashop.dev/auth/login</code> للدخول و<code>larashop.dev/logout</code> للخروج).
	</li>
</ol>
<p>
	افتح الرابط <code><a href="http://larashop.dev/auth/login" rel="external nofollow">http://larashop.dev/auth/login</a></code> وسجل مستخدما جديد عبر الاستمارة <code>New User Signup</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/03_register_user.png.053ad0a4368c809ffb43cd6151c12189.png" data-fileid="10523" rel=""><img alt="03_register_user.png" class="ipsImage ipsImage_thumbnailed" data-fileid="10523" src="https://academy.hsoub.com/uploads/monthly_2015_12/03_register_user.thumb.png.48f1d53740ced8755eda7bc2f73e59ba.png"></a>
</p>

<p>
	بالضغط على زر <code>Signup</code> تستدعي المسار <code><a href="http://laravel.dev/register" rel="external nofollow">http://laravel.dev/register</a></code> مع الإجراء <code>POST</code>. تتولى دالة <code>register</code> في المتحكم تلقي الطلب واستدعاء النموذج الذي ينشئ تسجيلة جديدة في جدول البيانات ثم تعيد الدالة توجيه المستخدم إلى صفحة الدخول. يمكنك التأكد من إنشاء المستخدم في الجدول <code>users</code> ضمن قاعدة البيانات.
</p>

<p>
	نجرّب الدخول بالمستخدم الجديد بإدخال عنوانه البريدي وكلمة السر في استمارة التسجيل.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/04_login_user.png.8172d02e536c626c64ef40b60e8200f5.png" data-fileid="10520" rel=""><img alt="04_login_user.png" class="ipsImage ipsImage_thumbnailed" data-fileid="10520" src="https://academy.hsoub.com/uploads/monthly_2015_12/04_login_user.thumb.png.da39ec8dda8f302ffa30100c61aeb6b6.png"></a>
</p>

<p>
	إن أدخل بيانات مستخدم صالحة فستُنقل إلى صفحة الدفع. لاحظ أن اسم المستخدم وعبارة <code>Logout</code> يظهران في الشريط العلوي.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_after_login.png.e1452a92c6eb0ae826f0da7a1f22c468.png" data-fileid="10522" rel=""><img alt="02_after_login.png" class="ipsImage ipsImage_thumbnailed" data-fileid="10522" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_after_login.thumb.png.607d8e15bce850be2c6c6063c80c9ce9.png"></a>
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://www.tutorials.kode-blog.com/laravel-5-authentication" rel="external nofollow">Laravel 5 Authentication</a> لصاحبه Rodrick Kazembe.
</p>
]]></description><guid isPermaLink="false">229</guid><pubDate>Wed, 20 Jan 2016 22:01:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x633;&#x644;&#x629; &#x645;&#x634;&#x62A;&#x631;&#x64A;&#x627;&#x62A; &#x641;&#x64A; Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-shopping-cart.png.072d2e2031d99766d94ddfa79c5fc0c1.png" /></p>

<p id="مقدمة">هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>. </li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>. </li><li>إنشاء سلة مشتريات في Laravel. <span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-shopping-cart.png.571237a1c17fcf30f3612190cd165cf5.png"><img data-fileid="11510" class="ipsImage ipsImage_thumbnailed" alt="laravel5-shopping-cart.thumb.png.c4b4027" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-shopping-cart.thumb.png.c4b4027092fe203be0a1c4d330cc7114.png"></a></p><p id="مقدمة">نكمل بناء متجرنا الإلكتروني بإضافة خاصية سلة المشتريات. سنستخدم حزمة Laravel ShoppingCart لإضافة هذه الخاصية إلى المشروع. يغطي الدرس المواضيع التالية:</p><ul><li><p>تثبيت حزمة Laravel Shopping Cart بـComposer.</p></li><li>إعداد Laravel 5 لاستخدام الحزمة.</li><li>إضافة عناصر إلى سلة المشتريات.</li><li>العثور على العناصر الموجودة في سلة المشتريات.</li><li>تحديث عنصر في سلة المشتريات.</li><li>حذف عنصر من سلة المشتريات.</li></ul><h2 id="استخدام-composer-لتثبيت-laravel-shopping-cart">استخدام Composer لتثبيت Laravel Shopping Cart</h2><p>نفتح ملف <code>composer.json</code> لإضافة اعتمادية جديدة للمشروع.</p><p>نبحث عن فقرة <code>require</code>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">"require": {
        "php": "&gt;=5.5.9",
        "laravel/framework": "5.2.*",
        "doctrine/dbal": "v2.4.2"
    },</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">نضيف حزمة </span><code style="line-height: 1.6;">ShoppingCart</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> على النحو التالي:</span></p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">"require": {
        "php": "&gt;=5.5.9",
        "laravel/framework": "5.2.*",
        "doctrine/dbal": "v2.4.2",
        "gloudemans/shoppingcart": "~1.3"
    },</pre><p><strong>ملحوظة:</strong> انتبه للفواصل في نهاية الأسطر.</p><p>نعلم Composer أننا نريد تثبيت الإصدار 1.3 من الحزمة <code>gloudemans/shoppingcart</code>؛ ثم نحدّث المشروع بتنفيذ الأمر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">composer update</pre><h2 id="إعداد-laravel-لاستخدام-حزمة-shoppingcart">إعداد Laravel لاستخدام حزمة ShoppingCart</h2><p>نحتاج بعد تثبيت حزمة ShoppingCart لإعداد Laravel للعمل معها. نفتح ملف الإعداد <code>config/app.php</code> ونضيف السطر التالي إلى مصفوفة <code>providers</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Gloudemans\Shoppingcart\ShoppingcartServiceProvider::class,</pre><p>يسجل الإعداد أعلاه مزوّد خدمة Provider لسلة المشتريات.</p><p><strong>ملحوظة:</strong> يتيح مزود الخدمة Service Provider في Laravel تحميل صنف (في الذاكرة) مع بدء عمل التطبيق، كما أنه يمكِّن من إضافة عناصر جديدة إلى حاويات الخدمة Service container وهي أداة تدير الاعتمادات بين مختلف الأصناف في إطار العمل.</p><p>سنضيف الآن كنية Alias لصنف سلة المشتريات. افتح ملف الإعداد <code>config/app.php</code> وأضف العنصر التالي إلى مصفوفة <code>aliases</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'Cart'    =&gt; Gloudemans\Shoppingcart\Facades\Cart::class,</pre><p><strong>ملحوظة:</strong> الكنى Aliases هي أسماء مختصرة للأصناف تُكتب بدلا من الاسم الكامل للصنف. يسجّل التطبيقُ عند بدئه هذه الأصنافَ لكنه لا يحملها إلا عند الحاجة.</p><h2 id="إضافة-عناصر-لسلة-المشتريات">إضافة عناصر لسلة المشتريات</h2><p>سنضيف في هذه الفقرة إمكانية إضافة عنصر إلى سلة المشتريات في صفحة المنتج. تُجرى العملية على ثلاث خطوات:</p><ul><li>إنشاء مسار لإجراء <code>HTTP POST</code> الذي يضيف العناصر إلى سلة المشتريات.</li><li>التعديل على القالب <code>products.blade.php</code> من أجل تضمين استمارة لإرسال البيانات مع معرّف المنتَج.</li><li>التعديل على المتحكم <code>Front.php</code> لكي يتبقى بيانات الاستمارة ويضيفها إلى السلة.</li></ul><h3 id="مسار-إجراء-http-post">مسار إجراء HTTP POST</h3><p>افتح ملف المسارات <code>routes.php</code> وأضف المسار التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::post('/cart', 'Front@cart');</pre><p>يعرف السطر السابق مسارات لتلقي إجراءات <code>POST</code> على رابط سلة المشتريات. سيُستخدَم هذا المسار لإضافة عناصر إلى سلة المشتريات.</p><h3 id="استمارة-صفحة-المنتج">استمارة صفحة المنتج</h3><p>الخطوة التالية هي التعديل على قالب صفحة المنتج وإضافة استمارة <code>form</code> لإرسال معرّف المنتج إلى سلة المشتريات من أجل إضافته إليها. افتح ملف العرض <code>products.blade.php</code> وعدّله ليصبح محتواه التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@extends('layouts.layout')

@section('content')       
&lt;section id="advertisement"&gt;
    &lt;div class="container"&gt;
        &lt;img src="{{asset('images/shop/advertisement.jpg')}}" alt="" /&gt;
    &lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;div class="container"&gt;
        &lt;div class="row"&gt;
            &lt;div class="col-sm-3"&gt;
                &lt;div class="left-sidebar"&gt;
                    @include('shared.sidebar')
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class="col-sm-9 padding-right"&gt;
                &lt;div class="features_items"&gt;&lt;!--features_items--&gt;
                    &lt;h2 class="title text-center"&gt;Features Items&lt;/h2&gt;
                    @foreach ($products as $product)
                    &lt;div class="col-sm-4"&gt;
                        &lt;div class="product-image-wrapper"&gt;
                            &lt;div class="single-products"&gt;
                                &lt;div class="productinfo text-center"&gt;
                                    &lt;img src="{{asset('images/shop/product9.jpg')}}" alt="" /&gt;
                                    &lt;h2&gt;${{$product-&gt;price}}&lt;/h2&gt;
                                    &lt;p&gt;{{$product-&gt;name}}&lt;/p&gt;
                                    &lt;a href="{{url('cart')}}" class="btn btn-default add-to-cart"&gt;&lt;i class="fa fa-shopping-cart"&gt;&lt;/i&gt;Add to cart&lt;/a&gt;
                                    &lt;a href='{{url("products/details/$product-&gt;id")}}' class="btn btn-default add-to-cart"&gt;&lt;i class="fa fa-info"&gt;&lt;/i&gt;View Details&lt;/a&gt;
                                &lt;/div&gt;
                                &lt;div class="product-overlay"&gt;
                                    &lt;div class="overlay-content"&gt;
                                        &lt;h2&gt;${{$product-&gt;price}}&lt;/h2&gt;
                                        &lt;p&gt;${{$product-&gt;name}}&lt;/p&gt;
                                        &lt;form method="POST" action="{{url('cart')}}"&gt;
                                            &lt;input type="hidden" name="product_id" value="{{$product-&gt;id}}"&gt;
                                            &lt;input type="hidden" name="_token" value="{{ csrf_token() }}"&gt;
                                            &lt;button type="submit" class="btn btn-fefault add-to-cart"&gt;
                                                &lt;i class="fa fa-shopping-cart"&gt;&lt;/i&gt;
                                                Add to cart
                                            &lt;/button&gt;
                                        &lt;/form&gt;
                                        &lt;a href='{{url("products/details/$product-&gt;id")}}' class="btn btn-default add-to-cart"&gt;&lt;i class="fa fa-info"&gt;&lt;/i&gt;View Details&lt;/a&gt;
                                    &lt;/div&gt;
                                &lt;/div&gt;
                            &lt;/div&gt;
                            &lt;div class="choose"&gt;
                                &lt;ul class="nav nav-pills nav-justified"&gt;
                                    &lt;li&gt;&lt;a href=""&gt;&lt;i class="fa fa-plus-square"&gt;&lt;/i&gt;Add to wishlist&lt;/a&gt;&lt;/li&gt;
                                    &lt;li&gt;&lt;a href=""&gt;&lt;i class="fa fa-plus-square"&gt;&lt;/i&gt;Add to compare&lt;/a&gt;&lt;/li&gt;
                                &lt;/ul&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    @endforeach
                    &lt;ul class="pagination"&gt;
                        &lt;li class="active"&gt;&lt;a href=""&gt;1&lt;/a&gt;&lt;/li&gt;
                        &lt;li&gt;&lt;a href=""&gt;2&lt;/a&gt;&lt;/li&gt;
                        &lt;li&gt;&lt;a href=""&gt;3&lt;/a&gt;&lt;/li&gt;
                        &lt;li&gt;&lt;a href=""&gt;»&lt;/a&gt;&lt;/li&gt;
                    &lt;/ul&gt;
                &lt;/div&gt;&lt;!--features_items--&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/section&gt;
@endsection
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">التغيير الأساسي هنا هو إضافة استمارة </span><code style="line-height: 1.6;">form</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> مع إجراء </span><code style="line-height: 1.6;">post</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">:</span></p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;form method="POST" action="{{url('cart')}}"&gt;...&lt;/form&gt;</pre><p>تُرسل الاستمارة معرف المنتج إلى سلة المشتريات الذي يعرفه حقل <code>product_id</code>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;input type="hidden" name="product_id" value="{{$product-&gt;id}}"&gt;</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">تحتوي الاستمارة أيضا على عنصر أمني هو:</span></p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;input type="hidden" name="token" value="{{ csrftoken() }}"&gt;</pre><p>الذي يعرف رمز أمان Security token للحماية ضد هجمات تزوير الطلب عبر الموقع Cross-site request forgery (تُكتب <span style="line-height: 22.4px;">CSRF أو XCRF اختصارا).</span></p><p>احفظ التعديلات.</p><p><strong>ملحوظة:</strong> تقوم هجمات تزوير الطلب عبر الموقع على البحث عن روابط تمكن إعادة استخدامها لتنفيذ إجراءات معينة تحتاج لصلاحيات خاصة، تتوفر عادة عند المستخدمين المسجلين، ثم الاحتيال عليهم لكي يفتحوا هذه الروابط - غالبا دون علمهم - وتنفيذ الإجراءات الطلوبة. تحمي رموز الأمان المستخدمين من هذه الهجمات.</p><h3 id="التعديل-على-المتحكم-front">التعديل على المتحكم Front</h3><p>نحتاج، ليمكن لنا استخدام سلة المشتريات، التعديل على دالة <code>cart</code> لاستيرد فضاء الأسماء <code>Cart</code>. افتح ملف المتحكم <code>Front.php</code> وأضف الأسطر التالية لاستيراد فضاءات الأسماء <code>Redirect</code>، <code>Request</code> و<code>Cart</code> على التوالي:</p><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">يُستخدَم </span><code style="line-height: 1.6;">Request</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> للوصول إلى بيانات إجراءات HTTP.</span></p><ul><li>يُستخدَم <code>Redirect</code> لتوجيه المستخدم بعد تنفيذ عملية لا تحتاج لإظهار بيانات في الصفحة.</li><li>للوصول إلى عناصر سلة المشتريات نستخدم <code>Cart</code>.</li></ul><p>اعثُر على الدالة <code>cart</code> في المتحكم <code>Front.php</code> وحدّثها كالتالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">public function cart() {
    if (Request::isMethod('post')) {
        $product_id = Request::get('product_id');
        $product = Product::find($product_id);
        Cart::add(array('id' =&gt; $product_id, 'name' =&gt; $product-&gt;name, 'qty' =&gt; 1, 'price' =&gt; $product-&gt;price));
    }

    $cart = Cart::content();

    return view('cart', array('cart' =&gt; $cart, 'title' =&gt; 'Welcome', 'description' =&gt; '', 'page' =&gt; 'home'));
}</pre><p>نفحص أولا نوع إجراء HTTP الذي أتى منه الطلب إلى الدالة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">if if (Request::isMethod(‘</pre><p>فإن كان الإجراء من نوع <code>POST</code> ننفذ الشفرة الموالية.</p><p>نعثر علي معرف المنتج المُرسَل في الطلب:<code> </code></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$productid = Request::get('productid');</pre><p>دالة <code>Request::get</code> لا تتعلق بنوعية إجراء HTTP ويتساوى عندها <code>POST</code> و<code>GET</code>. تُستخدَم هذه الدالة للعثور على متغيرات مرسلة في الطلب.</p><p>نستخدم نموذج المنتج <code>Product</code> للعثور على المنتج في قاعدة البيانات:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$product = Product::find($product_id);</pre><p>نستخدم كائن المنتج في التعليمة السابقة للحصول على بيانات المنتج وإضافتها إلى سلة المشتريات بإرسال نداء إلى الدالة <code>Cart::add</code>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">Cart::add(array('id' =&gt; $product_id, 'name' =&gt; $product-&gt;name, 'qty' =&gt; 1, 'price' =&gt; $product-&gt;price));</pre><p>ننادي الدالة <code>Cart::content</code> للحصول على محتوى سلة المشتريات ونضيفه إلى المتغيرات الممررة إلى العرض <code>cart.blade.php</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$cart = Cart::content();
return view('cart', array('cart' =&gt; $cart, 'title' =&gt; 'Welcome', 'description' =&gt; '', 'page' =&gt; 'home'));</pre><h2 id="العثور-على-العناصر-الموجودة-في-سلة-المشتريات">العثور على العناصر الموجودة في سلة المشتريات</h2><p>بقيت لنا خطوة واحدة قبل أن نستطيع تجربة سلة المشتريات. نحتاج لتعديل العرض <code>cart</code> لكي يُظهر محتويات السلة. نفتح ملف العرض <code>cart.blade.php</code> لتحريره. نعدّل الملف على النحو التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@extends('layouts.layout')

@section('content')       
&lt;section id="cart_items"&gt;
    &lt;div class="container"&gt;
        &lt;div class="breadcrumbs"&gt;
            &lt;ol class="breadcrumb"&gt;
                &lt;li&gt;&lt;a href="#"&gt;Home&lt;/a&gt;&lt;/li&gt;
                &lt;li class="active"&gt;Shopping Cart&lt;/li&gt;
            &lt;/ol&gt;
        &lt;/div&gt;
        &lt;div class="table-responsive cart_info"&gt;
            @if(count($cart))
            &lt;table class="table table-condensed"&gt;
                &lt;thead&gt;
                    &lt;tr class="cart_menu"&gt;
                        &lt;td class="image"&gt;Item&lt;/td&gt;
                        &lt;td class="description"&gt;&lt;/td&gt;
                        &lt;td class="price"&gt;Price&lt;/td&gt;
                        &lt;td class="quantity"&gt;Quantity&lt;/td&gt;
                        &lt;td class="total"&gt;Total&lt;/td&gt;
                        &lt;td&gt;&lt;/td&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    @foreach($cart as $item)
                    &lt;tr&gt;
                        &lt;td class="cart_product"&gt;
                            &lt;a href=""&gt;&lt;img src="images/cart/one.png" alt=""&gt;&lt;/a&gt;
                        &lt;/td&gt;
                        &lt;td class="cart_description"&gt;
                            &lt;h4&gt;&lt;a href=""&gt;{{$item-&gt;name}}&lt;/a&gt;&lt;/h4&gt;
                            &lt;p&gt;Web ID: {{$item-&gt;id}}&lt;/p&gt;
                        &lt;/td&gt;
                        &lt;td class="cart_price"&gt;
                            &lt;p&gt;${{$item-&gt;price}}&lt;/p&gt;
                        &lt;/td&gt;
                        &lt;td class="cart_quantity"&gt;
                            &lt;div class="cart_quantity_button"&gt;
                                &lt;a class="cart_quantity_up" href=""&gt; + &lt;/a&gt;
                                &lt;input class="cart_quantity_input" type="text" name="quantity" value="{{$item-&gt;qty}}" autocomplete="off" size="2"&gt;
                                &lt;a class="cart_quantity_down" href=""&gt; - &lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/td&gt;
                        &lt;td class="cart_total"&gt;
                            &lt;p class="cart_total_price"&gt;${{$item-&gt;subtotal}}&lt;/p&gt;
                        &lt;/td&gt;
                        &lt;td class="cart_delete"&gt;
                            &lt;a class="cart_quantity_delete" href=""&gt;&lt;i class="fa fa-times"&gt;&lt;/i&gt;&lt;/a&gt;
                        &lt;/td&gt;
                    &lt;/tr&gt;
                    @endforeach
                    @else
                &lt;p&gt;You have no items in the shopping cart&lt;/p&gt;
                @endif
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/section&gt; &lt;!--/#cart_items--&gt;

&lt;section id="do_action"&gt;
    &lt;div class="container"&gt;
        &lt;div class="heading"&gt;
            &lt;h3&gt;What would you like to do next?&lt;/h3&gt;
            &lt;p&gt;Choose if you have a discount code or reward points you want to use or would like to estimate your delivery cost.&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class="row"&gt;
            &lt;div class="col-sm-6"&gt;
                &lt;div class="chose_area"&gt;
                    &lt;ul class="user_option"&gt;
                        &lt;li&gt;
                            &lt;input type="checkbox"&gt;
                            &lt;label&gt;Use Coupon Code&lt;/label&gt;
                        &lt;/li&gt;
                        &lt;li&gt;
                            &lt;input type="checkbox"&gt;
                            &lt;label&gt;Use Gift Voucher&lt;/label&gt;
                        &lt;/li&gt;
                        &lt;li&gt;
                            &lt;input type="checkbox"&gt;
                            &lt;label&gt;Estimate Shipping &amp; Taxes&lt;/label&gt;
                        &lt;/li&gt;
                    &lt;/ul&gt;
                    &lt;ul class="user_info"&gt;
                        &lt;li class="single_field"&gt;
                            &lt;label&gt;Country:&lt;/label&gt;
                            &lt;select&gt;
                                &lt;option&gt;United States&lt;/option&gt;
                                &lt;option&gt;Bangladesh&lt;/option&gt;
                                &lt;option&gt;UK&lt;/option&gt;
                                &lt;option&gt;India&lt;/option&gt;
                                &lt;option&gt;Pakistan&lt;/option&gt;
                                &lt;option&gt;Ucrane&lt;/option&gt;
                                &lt;option&gt;Canada&lt;/option&gt;
                                &lt;option&gt;Dubai&lt;/option&gt;
                            &lt;/select&gt;

                        &lt;/li&gt;
                        &lt;li class="single_field"&gt;
                            &lt;label&gt;Region / State:&lt;/label&gt;
                            &lt;select&gt;
                                &lt;option&gt;Select&lt;/option&gt;
                                &lt;option&gt;Dhaka&lt;/option&gt;
                                &lt;option&gt;London&lt;/option&gt;
                                &lt;option&gt;Dillih&lt;/option&gt;
                                &lt;option&gt;Lahore&lt;/option&gt;
                                &lt;option&gt;Alaska&lt;/option&gt;
                                &lt;option&gt;Canada&lt;/option&gt;
                                &lt;option&gt;Dubai&lt;/option&gt;
                            &lt;/select&gt;

                        &lt;/li&gt;
                        &lt;li class="single_field zip-field"&gt;
                            &lt;label&gt;Zip Code:&lt;/label&gt;
                            &lt;input type="text"&gt;
                        &lt;/li&gt;
                    &lt;/ul&gt;
                    &lt;a class="btn btn-default update" href=""&gt;Get Quotes&lt;/a&gt;
                    &lt;a class="btn btn-default check_out" href=""&gt;Continue&lt;/a&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class="col-sm-6"&gt;
                &lt;div class="total_area"&gt;
                    &lt;ul&gt;
                        &lt;li&gt;Cart Sub Total &lt;span&gt;$59&lt;/span&gt;&lt;/li&gt;
                        &lt;li&gt;Eco Tax &lt;span&gt;$2&lt;/span&gt;&lt;/li&gt;
                        &lt;li&gt;Shipping Cost &lt;span&gt;Free&lt;/span&gt;&lt;/li&gt;
                        &lt;li&gt;Total &lt;span&gt;${{Cart::total()}}&lt;/span&gt;&lt;/li&gt;
                    &lt;/ul&gt;
                    &lt;a class="btn btn-default update" href="{{url('clear-cart')}}"&gt;Clear Cart&lt;/a&gt;
                    &lt;a class="btn btn-default check_out" href="{{url('checkout')}}"&gt;Check Out&lt;/a&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/section&gt;&lt;!--/#do_action--&gt;
@endsection
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">نستخدم الدالة </span><code style="line-height: 1.6;">count</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> لتحديد ما إذا كان المتغير </span><code style="line-height: 1.6;">cart</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> يحوي أي عناصر، فإن كان أنشأنا جدولا لعرض عناصر سلة المشتريات ديناميكيا:</span></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@if(count($cart))
                &lt;table class="table table-condensed"&gt;</pre><p>نستخدم الحلقة التكرارية <code>foreach</code> لعدّ عناصر سلة المشتريات:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@foreach(item)
</pre><p><span style="line-height: 1.6;">لكل منتج في سلة المشتريات نعرض اسم المنتج، معرّفه، ثمنه ومجموعا فرعيا Subtotal لتكلفة المنتج على التوالي:</span></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{{$item-&gt;name}}
{{$item-&gt;id}}
{{$item-&gt;price}}
{{$item-&gt;subtotal}}</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">المجموع الفرعي هو حاصل ضرب ثمن المنتج بكميّته. في الأسفل نعرض الثمن الكلي للمنتجات الموجودة في سلة المشتريات:</span></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{{Cart::total()}}</pre><h2 id="تحديث-العناصر-الموجودة-في-سلة-المشتريات">تحديث العناصر الموجودة في سلة المشتريات</h2><p>نضيف في هذه الفقرة إمكانية تحديث كمية المنتج في سلة المشتريات بالنقر على زر الزيادة <code>+</code> أو النقصان <code>-</code> بجانب الكمية. سنستخدم لهذا الغرض الاستعلام عن طريق رابط URL.</p><p>افتح ملف العرض <code>cart.blade.php</code> واعثر على السطرين:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;a class="cart_quantity_up" href=""&gt; + &lt;/a&gt;
&lt;a class="cart_quantity_down" href=""&gt; - &lt;/a&gt;</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">حدّث الشفرة المصدرية لكل منهما حتى تصبح على النحو التالي:</span></p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;a class="cart_quantity_up" href='{{url("cart?product_id=$item-&gt;id&amp;increment=1")}}'&gt; + &lt;/a&gt;
&lt;a class="cart_quantity_down" href='{{url("cart?product_id=$item-&gt;id&amp;decrease=1")}}'&gt; - &lt;/a&gt;</pre><p>تولد الشفرة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{{url("cart?productid=$item-&gt;id&amp;increment=1")}}</pre><p>رابطا بالهيئة <code><a rel="external nofollow" href="http://larashop.dev/cart?productid=1&amp;increment=1">http://larashop.dev/cart?productid=1&amp;increment=1</a></code>. يعيّن الرابط معرّف المنتج الذي نريد تحديث كميته واتجاه التحديث. إذا كان المتسوق يريد زيادة الكمية (نقر على <code>+</code>) نعطي القيمة <code>1</code> للمعطى <code>increment</code>؛ أما إذا كان المتسوق يريد نقص الكمية (نقر على <code>-</code>) فنعطي القيمة <code>1</code> للمتغير <code>decrease</code>.</p><p>يجب الآن تعديل المتحكم للتعاطي مع رغبة المتسوق في تحديث الكمية. نعدل الدالة <code>cart</code> لتصبح على النحو التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">public function cart() {
    // إضافة منتج جديد إلى سلة المشتريات
    if (Request::isMethod('post')) {
        $product_id = Request::get('product_id');
        $product = Product::find($product_id);
        Cart::add(array('id' =&gt; $product_id, 'name' =&gt; $product-&gt;name, 'qty' =&gt; 1, 'price' =&gt; $product-&gt;price));
    }


    // زيادة كمية منتج في سلة المشتريات
    if (Request::get('product_id') &amp;&amp; (Request::get('increment')) == 1) {
        $rowId = Cart::search(array('id' =&gt; Request::get('product_id')));
        $item = Cart::get($rowId[0]);

        Cart::update($rowId[0], $item-&gt;qty + 1);
    }

            // نقص كمية منتج في سلة المشتريات
    if (Request::get('product_id') &amp;&amp; (Request::get('decrease')) == 1) {
        $rowId = Cart::search(array('id' =&gt; Request::get('product_id')));
        $item = Cart::get($rowId[0]);

        Cart::update($rowId[0], $item-&gt;qty - 1);
    }

    $cart = Cart::content();

    return view('cart', array('cart' =&gt; $cart, 'title' =&gt; 'Welcome', 'description' =&gt; '', 'page' =&gt; 'home'));
}
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">في الشيفرة أعلاه نتحقق من تعيين المتغيّرين </span><code style="line-height: 1.6;">product_id</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> و</span><code style="line-height: 1.6;">increment</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">.</span><code> </code></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">if (Request::get('product_id') &amp;&amp; (Request::get('increment')) == 1)</pre><p>إذا كان المتغيران معيَّنيْن وقيمة المتغيّر <code>increment</code> تساوي <code>1</code> فهذا يعني أن المتسوق أراد زيادة الكمية.</p><p>يستخدم السطر الموالي معرّف المنتج <code>product_id</code> للبحث بين عناصر سلة المشتريات ويرجع مصفوفة بمعرّفات أسطُر <code>rowId</code> موافقة للبحث:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$rowId = Cart::search(array('id' =&gt; Request::get('product_id')));</pre><p>معرّف السطر هو معرّف وحيد لعنصُر في السلة يُولّد تلقائيا، ويُستخدَم لتحديث العناصر في السلة. نستخدم معرف العنصر للعثور على كائن يمثل المنتج في سلة المشتريات:<code> </code></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$item = Cart::get($rowId[0]);</pre><p>نحتفظ بالعنصر الأول من المصفوفة التي ترجعها الدالة <code>Cart::get</code>، في حالتنا لا يوجد سوى عنصر واحد. نبحث عن كائن المنتج لمعرفة الكمية الموجودة في السلة وبالتالي يمكن لنا زيادتها أو نقصها.</p><p>نستدعي الدالة <code>Cart::update</code> ونمرر لها معرف المنتج ونزيد الكمية بـ<code>1</code>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">Cart::update($rowId[0], $item-&gt;qty + 1); </pre><p>السطر الموالي يتحقق من تعيين المتغيرين <code>product_id</code> و<code>decrease</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">if (Request::get('productid') &amp;&amp; (Request::get('decrease')) == 1)</pre><p>وفي حال كانت الإجابة نعم يفحص قيمة المتغير <code>decrease</code> وإذا كانت <code>1</code> ينقص كمية المنتج بـ<code>1</code> في سلة المشتريات:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Cart::update($rowId[0], $item-&gt;qty 1); </pre><p>افتح رابط صفحة المنتجات <code><a rel="external nofollow" href="http://larashop.dev/products">http://larashop.dev/products</a></code>، اختر أحدها بتمرير المؤشر فوقه وأضفه إلى سلة المشتريات بالنقر على زر <strong>Add to cart</strong>.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_shopping_cart.png.a83ad0d3947588e7bc4fdea2b9d9790b.png"><img data-fileid="10517" class="ipsImage ipsImage_thumbnailed" alt="01_shopping_cart.thumb.png.f0667aed8f7e8" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_shopping_cart.thumb.png.f0667aed8f7e87e8650c6feaa6c4c5db.png"></a></p><p>ستحصل على النتيجة التالية (تتغير النتيجة حسب المنتج الذي اخترته في الخطوة السابقة).</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_shopping_cart.png.017ffb7eca5de7136784ca88d8ab845b.png"><img data-fileid="10518" class="ipsImage ipsImage_thumbnailed" alt="02_shopping_cart.thumb.png.d5d56d92ca58e" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_shopping_cart.thumb.png.d5d56d92ca58e33b667047232aa55d2d.png"></a></p><p>اضغط على الزر <strong><code>+</code> </strong>لزيادة كمية منتج في سلة المشتريات. لاحظ تغير المجموع الفرعي مع تغير الكمية.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/03_shopping_cart.png.047b799ad2d85fcba3706a13f2660470.png"><img data-fileid="10519" class="ipsImage ipsImage_thumbnailed" alt="03_shopping_cart.thumb.png.6c6516f03eb08" src="https://academy.hsoub.com/uploads/monthly_2015_12/03_shopping_cart.thumb.png.6c6516f03eb08db292bb79897e84b65a.png"></a></p><h2 id="حذف-عناصر-من-سلة-المشتريات">حذف عناصر من سلة المشتريات</h2><p>حذفُ عنصُر من سلة المشتريات مشابه لتحديثه:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$rowId = Cart::search(array('id' =&gt; Request::get('product_id')));
Cart::remove($rowId[0]);
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">تحذف الدالة </span><code style="line-height: 1.6;">Cart::remove</code><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;"> عنصرا من سلة المشتريات اعتمادا على معرف السطر الممرَّر إليها.</span></p><p>لحذف جميع عناصر سلة المشتريات دفعة واحدة نستخدم الدالة <code>Cart::destroy</code>.</p><h2 id="خاتمة">خاتمة</h2><p>كان الهدف من هذا الدرس شرح كيفية تثبيت حزمة Laravel ShoppingCart واستخدامها في مشروع Laravel الخاص بك للحصول على ميزة سلة مشتريات. استعملنا خلال هذا الدرس الحزمة في صفحة المنتج، يمكنك التوسع في استخدام الحزمة في صفحات الموقع الأخرى إن أردت.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-shopping-cart">Laravel 5 Shopping Cart</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">228</guid><pubDate>Mon, 18 Jan 2016 21:48:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Eloquent ORM &#x644;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x641;&#x64A; Laravel 5</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-eloquent-orm_(2).png.7a36fca37cb2068edc4fac2e5c00a714.png" /></p>

<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%8Alaravel-5-r224/">الدرس السابق</a> بنية قاعدة البيانات الخاصة بمشروع Larashop. نكمل في هذا الدرس حديثنا عن قواعد البيانات في Laravel بشرح كيفية إدراج تسجيلات في قواعد البيانات وكيفية استخراجها منها باستخدام إطار العمل Eloquent.</p><p id="مقدمة">هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>. </li><li>استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها. <span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-eloquent-orm_(2).png.32768a23fb6f69435d0d68fdbd1e8130.png"><img data-fileid="11066" class="ipsImage ipsImage_thumbnailed" alt="laravel5-eloquent-orm_(2).thumb.png.cd53" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-eloquent-orm_(2).thumb.png.cd53ab3e9f38a94e32aebe5309cc5bb0.png"></a></p><p>سنغطي في هذا الدرس المواضيع التالية:</p><ul><li>نماذج Eloquent<ul><li>أعراف التسمية.</li><li>أسماء الجداول والمفاتيح الخارجية.</li><li>الأختام الزمنية.</li></ul></li><li>إطار العمل Eloquent<ul><li>قراءة البيانات READ.</li><li>تحديث البيانات UPDATE.</li><li>حذف البيانات DELETE.</li><li>إدراج البيانات INSERT.</li></ul></li><li>تنفيذ استعلامات SQL في Laravel.</li><li>نماذج Eloquent لمشروع Larashop.<ul><li>استخدام النماذج في المتحكمات.</li><li>إظهار بيانات النماذج في العروض.</li></ul></li></ul><h2 id="إطار-عمل-eloquent">إطار عمل Eloquent</h2><p>يأتي Laravel مضمنًّا بإطار عمل Eloquent الذي يُستخدَم للتخاطب مع قاعدة البيانات وتنفيذ عمليات مثل الإدراج <strong>Insert</strong>، التحديث <strong>Update</strong> أو الحذف <strong>Delete</strong> على الجداول. Eloquent هو إطار عمل لربط كائنات التطبيق بعلاقات (جداول) قاعدة البيانات Object Relational Mapper, ORM.</p><p>يقوم مبدأ ربط العلاقات بالكائنات على تنفيذ نمط ActiveRecord (التسجيلة النشطة)؛ الذي هو وسيلة للوصول إلى البيانات في قاعدة البيانات، حيث يضمن جدول بيانات (أو علاقة في قاعدة البيانات بصفة عامة) في صنف Class وتُربط كل تسجيلة من جدول البيانات بكائن Object من الصنف. بهذه الطريقة يُصبح التعامل مع الصنف مماثلا للتعامل مع الجدول في قاعدة البيانات. مثلا، لإدراج تسجيلة جديدة في جدول قاعدة البيانات ننشئ - في التطبيق - كائنا جديدا من الصنف المربوط بالجدول. وإذا أردنا أن نحدّث بيانات تسجيلة من الجدول نحدّث خاصيّات الكائن المربوط بها.</p><h3 id="نماذج-eloquent">نماذج Eloquent</h3><p>تُستخدَم النماذج في بنية MVC للتفاعل مع مصادر البيانات (قواعد البيانات، ملفات نصية، … إلخ). تُعرَّف النماذج في Laravel بتمديد الصنف <code>Illuminate\Database\Eloquent\Model</code> الذي يوفّر دوال جاهزة للاستخدام من أجل التفاعل مع مصدر البيانات.</p><h3 id="أعراف-التسمية-في-eloquent">أعراف التسمية في Eloquent</h3><p>توجد بعض الأعراف التي يفترض إطار العمل Eloquent مبدئيا اتّباعها، مع وجود إمكانية لتغييرها حسب الرغبة. في العرف أن اسم النموذج يكون كلمة مفردة تبدأ بحرف كبير Upper case، بينما اسم الجدول في قاعدة البيانات كلمة للجمع بأحرف صغيرة Lower case. يعتمد Laravel هذا العرف فيربط تلقائيا بين النموذج ذي الاسم المفرد والجدول الذي يكون اسمه جمعا لاسم النموذج.</p><p>نستخدم أداة Artisan لإنشاء نموذج لجدول التصنيفات <code>categories</code> باسم <code>Category</code> (مفرد <code>categories</code>):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:model Category</pre><p>ينشئ الأمر ملفا للنموذج على المسار <code>app/Category.php</code>. نفتح الملف لرؤية محتواه:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
  //
}</pre><ul><li>نعرف فضاء الأسماء الذي يتبع له النموذج: <code>;namespace App</code>.</li><li>نستورد فضاء الأسماء الخاص بـ Eloquent بالتعليمة: <code>use Illuminate\Database\Eloquent\Model;</code>.</li><li>يمدّد الصنفُ <code>Category</code> صنفَ نماذج Eloquent الذي تحدثنا عنه أعلاه: <code>class Category extends Model</code>.</li></ul><p>من المتعارف عليه أيضا أن حقل المفتاح الرئيس للجدول يُسمّى <code>id</code>، ومن الممكن مثل ما هو الحال مع اسم الجدول، تحديدُ اسم مغاير لحقل المفتح الرئيس.</p><p>يمكن تحديد اسم الجدول في النموذج بغض النظر عن المتعارف عليه بإعطاء قيمة للمتغير <code>table$</code>، نفس الشيء بالنسبة للمفتاح الرئيس مع المتغير <code>primaryKey$</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">protected $primaryKey = 'id';
protected $table = 'categories';</pre><h3 id="تسجيلات-الأختام-الزمنية">تسجيلات الأختام الزمنية</h3><p>يفترض Laravel إضافةَ الحقلين <code>created_at</code> و<code>updated_at</code> إلى جداول قاعدة البيانات. تُدرج قيمتا الحقلين عند إنشاء تسجيلة جديدة في الجدول، وتحدّث قيمة <code>updated_at</code> عند تحديث قيمة التسجيلة. إن لم تضف هذين الحقلين في جداول قاعدة البيانات فيمكن تعطيل الإعداد المبدئي على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public $timestamps = false;</pre><h2 id="استخدام-eloquent">استخدام Eloquent</h2><p>نكمل كتابة الشفرة المصدرية للنموذج <code>Category</code> ليصبح كما يلي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App;

class Category extends Model {
  protected $primaryKey = 'id';
  protected $table = 'categories';
}</pre><ul><li>عرّفنا حقل المفتاح الرئيس للجدول: ;'<code>$primaryKey = 'id</code>. ليس هذا ضروريا هنا ما دام اسم الحقل يوافق العُرْف (<code>id</code>). نفس الملحوظة تنطبق على تعريف اسم الجدول في التعليمة الموالية.</li></ul><h3 id="قراءة-محتوى-جدول-في-قاعدة-البيانات">قراءة محتوى جدول في قاعدة البيانات</h3><p>سنرى، في هذه الفقرة، كيفية العثور على جميع التصنيفات التي نحتفظ بها في جدول التصنيفات.</p><p><strong>ملحوظة:</strong> نطبع النتائج في الأمثلة أدناه مباشرة من الشيفرة المصدرية للمسار دون الاستعانة بالمتحكم رغم أن ذلك مخالف لمبدأ MVC، إلا أن الغرض هنا هو رؤية عمل Eloquent. سنعود لترتيب الأمور في ما بعد.</p><p>افتح ملف المسارات <code>routes.php</code> وأضف المسار التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/read', function() {
  $category = new App\Category();

  $data = $category-&gt;all(array('name','id'));

  foreach ($data as $list) {
   echo $list-&gt;id . ' ' . $list-&gt;name . '&lt;/br&gt;';
  }
});
</pre><ul><li><p>ننشئ كائنا جديدا من صنف النموذج:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$category = new App\Category();</pre></li><li><p>التعليمة التالية تستدعي الدالة <code>all</code> في الكائن الذي أنشأناه للتو، وتمرر له مصفوفة تحدد الحقول التي نود الحصول عليها؛ في حالتنا حدّدنا الحقلين <code>id</code> (المعرِّف) و<code>name</code> (اسم التصنيف). إن لم تُحدَّد معطيات للمصفوفة فستُرجع الدالة جميع الحقول.</p></li><li>نستخدم حلقة تكرارية <code>foreach</code> لإظهار النتائج التي تحصلنا عليها.</li></ul><p>احفظ التعديلات ثم افتح الرابط <code><a rel="external nofollow" href="http://larashop.dev/read">http://larashop.dev/read</a></code> في المتصفح. ستحصُل على لائحة شبيهة بالتالي (قد تختلف النتيجة لديك قليلا):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">5 CLOTHING
4 FASHION
3 KIDS
1 MEN
2 WOMEN</pre><h3 id="تحديث-تسجيلات">تحديث تسجيلات</h3><p>سنحدّث في هذه الفقرة تسجيلة في جدول التصنيفات باستخدام المعرِّف <code>id</code>. نختار معرّف إحدى التصنيفات الظاهرة في نتيجة المثال السابق، مثلا التصنيف<code>KIDS</code> ذو المعرِّف <code>3</code>.</p><p>نعيد فتح ملف المسارات <code>routes.php</code> ونضيف مسارا جديدا كما يلي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/update', function() {
  $category = App\Category::find(4);
  $category-&gt;name = 'KIDS 2';
  $category-&gt;save();

  $data = $category-&gt;all(array('name','id'));

  foreach ($data as $list) {
    echo $list-&gt;id . ' ' . $list-&gt;name . '&lt;/br&gt;';
  }
});</pre><ul><li>نستدعي الدالة <code>find</code> الموجودة في النموذج مع تمرير معرّف التصنيف إليها. ترجع الدالة كائنا من صنف <code>Category</code> يحوي بيانات التصنيف المستقاة من تسجيلة في الجدول <code>categories</code>.</li><li>نعيّن الاسم الجديد للتصنيف بالتعديل على الخاصية <code>name</code> في الكائن <code>category$</code>.</li><li>لتُعتمَد التعديلات وتخزَّن في السجل نستدعي الدالة <code>save</code> من الكائن <code>category$</code>.</li><li>نستخدم حلقة تكرارية <code>foreach</code> لإظهار النتائج التي تحصلنا عليها.</li></ul><p>احفظ الملف ثم افتح الرابط <code><a rel="external nofollow" href="http://larashop.dev/update">http://larashop.dev/update</a></code> في المتصفح. لاحظ تغيّر اسم التصنيف من <code>KIDS</code> إلى <code>KIDS 2</code>.</p><h3 id="حذف-تسجيلة-من-جدول-في-قاعدة-البيانات">حذف تسجيلة من جدول في قاعدة البيانات</h3><p>نختار أحد التصنيفات لحذفه (مثلا، التصنيف <code>CLOTHING</code> ذو المعرف <code>5</code>). افتح ملف المسارات <code>routes.php</code> وأضف المسار التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">Route::get('/delete', function() {
    $category = App\Category::find(5);
    $category-&gt;delete();

    $data = $category-&gt;all(array('name','id'));

    foreach ($data as $list) {
        echo $list-&gt;id . ' ' . $list-&gt;name . '&lt;/br&gt;';
    }
});
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">ي</span>وجد شبه كبير بين تحديث تسجيلة وحذفها. الفرق هو أنه بعد إيجاد التصنيف (الدالة <span style="font-family:courier new,courier,monospace;">find</span>) نستدعي الدالة <span style="font-family:courier new,courier,monospace;">delete</span> في الكائن<span style="font-family:courier new,courier,monospace;"> category$</span> لحذف التسجيلة المربوطة به.</p><p>افتح الرابط <code><a rel="external nofollow" href="http://larashop.dev/delete">http://larashop.dev/delete</a></code> ولاحظ أن التصنيف لم يعد موجودا.</p><h3 id="إدراج-تسجيلة">إدراج تسجيلة</h3><p>لإدراج تسجيلة جديدة في جدول قاعدة البيانات ننشئ كائنا جديدا من صنف <code>Category</code> ونعيّن خواصّه ثم نخزنه في الجدول، كما يلي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">Route::get('/insert', function() {
    $category= new App\Category;
    $category-&gt;name='Music';
    $category-&gt;save();
    return 'category added';
});
</pre><p>بالذهاب إلى الرابط <a rel="external nofollow" href="http://larashop.dev/insert">http://larashop.dev/insert</a> تظهر رسالة category added دلالةً على إضافة التصنيف. يمكن أيضا التحقق من إضافة التصنيف من سطر أوامر MySQL أو بالذهاب إلى الرابط <a rel="external nofollow" href="http://larashop.dev/read">http://larashop.dev/read</a>.</p><p>توجد طريقة أخرى لاستخدام سطر برمجي واحد لإدراج تصنيف في تسجيلة. نستخدم لهذا الغرض الدالة <code>create</code> من نموذج التصنيف <code>Category</code>؛ ولكن يجب قبل ذلك التعديل على النموذج <code>Category</code> لتمكين الإسناد الشامل Mass assignment (تحديد قيم معطيات عدّة مرة واحدة).</p><p>نفتح ملف النموذج لتحريره ثم نضيف السطر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">protected $fillable = array('name', 'created_at_ip', 'updated_at_ip');
</pre><p>يعرف المتغير <code>fillable$</code> مصفوفة بالحقول التي يمكن تعيين قيمها دفعة واحدة. احفظ ملف النموذج ثم افتح ملف المسارات <code>routes.php</code> وعدل المسار <code>insert/</code> ليصبح التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/insert', function() {
  App\Category::create(array('name' =&gt; 'New Music'));
  return 'category added';
});
</pre><p>نستدعي الدالة <code>create</code> من الصنف <code>Category</code> ونمرر لها مصفوفة بحقول التسجيلة الجديدة مع قيمها. ينبغي أن تكون الحقول الممررة قابلة للإسناد الشامل، أي مذكورة في المتغير <code>fillable$</code>. لاحظ أن إنشاء الكائن وتعيين قيم خاصياته ثم تخزين محتوياته في قاعدة البيانات كل هذا تم من خلال استدعاء الدالة <code>create</code>.</p><p><strong>ملحوظة 1:</strong> عند طلب الرابط <code><a rel="external nofollow" href="http://larashop.dev/insert">http://larashop.dev/insert</a></code> في المرة الأولى تظهر الرسالة <code>category added</code> ولكن عند طلب نفس الرابط مرة أخرى دون تعديل المسار تظهر صفحة بيضاء دلالة على عدم إدراج التسجيلة. يعود السبب في ذلك إلى أننا أثناء تعريف الجدول <code>categories</code> في الدرس السابق علّمنا الحقل <code>name</code> بالدالة <code>unique</code> أي أنه لا يمكن لتسجيلتين من هذا الجدول أن يكون لهما نفس الاسم.</p><p><strong>ملحوظة 2</strong>: الإسناد الشامل غير ممكّن مبدئيا لأسباب أمنية ويجب عند تمكينه اختيار حقول <code>fillable$</code> بعناية حتى لا تمثل خطرا أمنيا. يجب دائما تطهير Sanitize البيانات التي يستقيها التطبيق من المستخدم.</p><h3 id="تنفيذ-استعلامات-sql-مباشرة">تنفيذ استعلامات SQL مباشرة</h3><p>قد ترغب، لسبب أو آخر، في التعامل المباشر مع قاعدة البيانات باستخدام استعلامات SQL؛ يوفر Laravel صنف <code>DB</code> لهذا الغرض.</p><ul><li><strong>استعلامات SELECT</strong></li></ul><p>تُستخدَم دالة <code>select</code> لتنفيذ استعلامات القراءة من قاعدة البيانات على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$category = DB::select('SELECT name FROM categories WHERE id = ?', [1]);</pre><p>تأخذ الدالة <code>DB::select</code> معطيين: الأول هو استعلام القراءة المراد تنفيذه، والثاني معطيات نود استخدامها في الاستعلام. بالنسبة للمعطيات المراد استخدامها في الاستعلام فتُحدّد أماكنها بعلامة <code>?</code> وتكون قيمتها في مصفوفة تمرّر في المعطى الثاني للدالة <code>DB::select</code>. ينفذ السطر أعلاه استعلام SQL التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">SELECT name FROM categories WHERE id = 1;</pre><p>نفرض أننا نريد تنفيذ استعلام SQL التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">SELECT name FROM categories WHERE id BETWEEN 1 AND 4;</pre><p>يطلب الاستعلام قيمتين (<code>1</code> و<code>4</code>). يُترجم الاستعلام في النموذج على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$category = DB::select('SELECT name FROM categories WHERE id BETWEEN ? AND ?', [1,4]);</pre><p>تُبدل أول علامة <code>?</code> في الاستعلام بأول عنصر من المصفوفة في معطى الدالة الثاني، وعلامة <code>?</code> الثانية بالمعطى الموالي وهكذا.<br>يمكن أيضا استخدامُ متغيرات بدلا من <code>?</code> على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$category = DB::select('SELECT name FROM categories WHERE id BETWEEN :id1 AND :id2', ['id1' =&gt; 1, 'id2' =&gt; 4]);</pre><p>لاحظ استخدام <code>:</code> قبل أسماء المتغيرات في استعلام SQL.</p><ul><li><strong>استعلامات INSERT</strong></li></ul><p>تُستخدم دالة <code>DB::insert</code> لإدراج تسجيلات في الجدول بنفس طريقة استخدام <code>DB::select</code> للقراءة منه:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$inserted=DB::insert('INSERT INTO categories (name) VALUES (?)', ['TEST']);</pre><p>ترجع الدالة <code>DB::insert</code> عدد التسجيلات التي أدرجها الاستعلام.</p><ul><li><strong>استعلامات UPDATE</strong></li></ul><p>لتحديث تسجيلة في جدول بقاعدة البيانات نستخدم الدالة <code>DB::update</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$affected = DB::update('UPDATE categories SET name = 'TEST UPDATE' WHERE name = ?', ['TEST']);</pre><p>ترجع الدالة <code>DB::update</code> عدد التسجيلات التي حدثها الاستعلام.</p><ul><li><strong>استعلامات DELETE</strong></li></ul><p>توفر الدالة <code>DB::delete</code> إمكانية تنفيذ استعلامات <code>DELETE</code> على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$deleted = DB::delete('DELETE FROM categories WHERE id = ?', [13]);</pre><p>ترجع الدالة <code>DB::delete</code> عدد التسجيلات التي حذفها الاستعلام.</p><ul><li><strong>استعلامات عامة</strong></li></ul><p>بالنسبة للاستعلامات التي لا ترجع أية قيمة فيمكن استخدام الدالة <code>DB::statement</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">DB::statement('drop tables drinks');</pre><h2 id="نماذج-eloquent-لمشروع-larashop">نماذج Eloquent لمشروع Larashop</h2><p>نشرع الآن بعد أن رأينا آلية عمل Eloquent ببناء بقية نماذج مشروع Larashop.</p><p>نفذ الأوامر التالية لإنشاء نماذج للعلامات التجارية، المنتجات ومنشورات المدونة على التوالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:model Brand
php artisan make:model Product
php artisan make:model Post</pre><p>نعرّف في كل ملف نموذج حقل المفتاح الرئيس، اسم الجدول وأسماء الحقول المسموح بإسنادها <code>fillable</code>.</p><ul><li><p>ملف <code>Brand.php</code>:</p><pre style="text-align: left;" data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App;

class Brand extends Model {
  protected $primaryKey = 'id';
  protected $table = 'brands';
  protected $fillable = array('name', 'created_at_ip', 'updated_at_ip');
}
</pre></li><li><p>ملف <code>Product.php</code>:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint" style="text-align: left;">&lt;?php

namespace App;

class Product extends Model {
    protected $primaryKey = 'id';
    protected $table = 'products';
    protected $fillable = array('name', 'title',    'description','price','category_id','brand_id','created_at_ip', 'updated_at_ip');
}

</pre></li><li><p><span style="line-height: 22.4px; text-align: right;">ملف </span><code style="line-height: 22.4px; text-align: right;">Post.php</code><span style="line-height: 22.4px; text-align: right;">:</span> </p></li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

namespace App;

class Post extends Model {
    protected $primaryKey = 'id';
    protected $table = 'posts';
    protected $fillable = array('url', 'title', 'description','content','blog','created_at_ip', 'updated_at_ip');
}
</pre><h2 id="استخدام-النماذج-في-المتحكمات">استخدام النماذج في المتحكمات</h2><p>تقضي بنية MVC وعادات البرمجة الصحيحة أن تكون المتحكمات هي من يتعامل مع النماذج. سنعدّ متحكم المشروع <code>Front.php</code> للعثور على البيانات من النماذج وتمريرها إلى العروض لتظهر لدى المتصفح.</p><p>عدّل ملف <code>Front.php</code> كالتالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App\Http\Controllers;

use App\Brand;
use App\Category;
use App\Product;
use App\Http\Controllers\Controller;

class Front extends Controller {

 var $brands;
 var $categories;
 var $products;
 var $title;
 var $description;

public function __construct() {
  $this-&gt;brands = Brand::all(array('name'));
  $this-&gt;categories = Category::all(array('name'));
  $this-&gt;products = Product::all(array('id','name','price'));
}

public function index() {
  return view('home', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'home', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function products() {
  return view('products', array('title' =&gt; 'Products Listing','description' =&gt; '','page' =&gt; 'products', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function product_details($id) {
  $product = Product::find($id);
  return view('product_details', array('product' =&gt; $product, 'title' =&gt; $product-&gt;name,'description' =&gt; '','page' =&gt; 'products', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function product_categories($name) {
  return view('products', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'products', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function product_brands($name, $category = null) {
  return view('products', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'products', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function blog() {
  return view('blog', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'blog', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function blog_post($id) {
  return view('blog_post', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'blog', 'brands' =&gt; $this-&gt;brands, 'categories' =&gt; $this-&gt;categories, 'products' =&gt; $this-&gt;products));
}

public function contact_us() {
  return view('contact_us', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'contact_us'));
}

public function login() {
  return view('login', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'home'));
}

public function logout() {
  return view('login', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'home'));
}

public function cart() {
  return view('cart', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'home'));
}

public function checkout() {
  return view('checkout', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'home'));
}

public function search($query) {
  return view('products', array('title' =&gt; 'Welcome','description' =&gt; '','page' =&gt; 'products'));
}
}
</pre><p>في المتحكم:</p><ul><li><p>نستورد النماذج:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint" style="text-align: left;">use App\Brand;
use App\Category;
use App\Product;
</pre></li><li><p>نعرف متغيرات لتحميل بيانات النماذج:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint" style="text-align: left;">var $brands;
var $categories;
var $products;
</pre></li><li><p>يعرف المتغيران <code>title$</code> و<code>description$</code> على التوالي عنوانا ووصفا لأغراض التحسين لمحركات البحث.</p></li><li><p>نُعرّف باني Constructor صنف المتحكم:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">public function __construct(){…}</pre><p>تحمّل هذه الدالة البيانات من النماذج إلى المتغيرات المعرّفة سابقا.</p></li><li>نحمّل في الدالة <code>index</code> العرض <code>home</code> مع تمرير مصفوفة معطيات تمثل بيانات النماذج مع بيانات أخرى لغرض التحسين لمحركات البحث.</li></ul><h2 id="عرض-بيانات-النماذج-في-العروض">عرض بيانات النماذج في العروض</h2><p>نستخدم الحلقات التكرارية في قوالب Blade من أجل عرض بيانات النماذج التي مررها المتحكم إلى العروض. على سبيل المثال:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@foreach ($brands as $brand)
  &lt;li&gt;&lt;a href='{{url("products/brands/$brand-&gt;name")}}'&gt; &lt;span class="pull-right"&gt;(50)&lt;/span&gt;{{$brand-&gt;name}}&lt;/a&gt;&lt;/li&gt;
@endforeach</pre><p>توجد عروض المشروع في الملف المرفق.</p><h2 id="خاتمة">خاتمة</h2><p>من السهل إنشاء نماذج Eloquent واستخدامها؛ كل ما عليك فعله هو تمديد صنف <code>Model</code> والبدء باستخدام النموذج. يوفر Laravel أيضا إمكانية تخصيص استعلامات SQL دون المرور بـEloquent لمن يرغب في ذلك.</p><p>ملف مرفق: <a class="ipsAttachLink" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=10412">عروض المشروع.</a></p><p>ترجمة -وبتصرف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-eloquent-orm">Laravel 5 Eloquent ORM</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">227</guid><pubDate>Tue, 12 Jan 2016 21:59:00 +0000</pubDate></item><item><title>&#x62A;&#x647;&#x62C;&#x64A;&#x631; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x641;&#x64A; Laravel 5</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-database-migration.png.40e35785820c8580dbe633ccb12dd7f0.png" /></p>

<p id="مقدمة">يوفر تهجير قواعد البيانات Database migration في Laravel آليات لإنشاء الجداول Tablesوالتعديل عليها بغض النظر نظام إدارة قواعد البيانات المستخدم. يعني هذا أنك لن تضطر للاهتمام بالاختلافات بين نظم إدارة قواعد البيانات في صياغة أوامر SQL. يمكّن التهجير أيضا من التراجع والعودة إلى ما كانت عليه قاعدة البيانات قبل آخر التعديلات.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li><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/">نظام Blade للقوالب</a>.</li><li>تهجير قواعد البيانات في Laravel. (هذا الدرس)</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-database-migration.png.f3cc9672b6e2ff6c33a4652d1ba6c1fc.png"><img data-fileid="10802" class="ipsImage ipsImage_thumbnailed" alt="laravel5-database-migration.thumb.png.1f" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-database-migration.thumb.png.1f2cb0d3e1a0ba0db0c87a75763f25da.png"></a></p><p>يمكن النظر إلى تهجير قواعد البيانات كما لو كان نظام إدارة نسخ خاص بقواعد البيانات، إذ يتيح لفريق العمل سهولة تغيير مخطّط Schema البيانات وتشاركه.</p><p>نكمل في هذا الدرس اعتمادا على ما أنشأناه في الدروس السابقة من السلسلة. يغطي الدرس المواضيع التالية:</p><ul><li>متطلبات التهجير.</li><li>أمر Artisan لتهجير قواعد البيانات.</li><li>بنية التهجير.</li><li>إنشاء جدول بآلية التهجير.</li><li>استخدام آلية التهجير للتراجع Rollback عن التعديلات.</li><li>بذر قواعد البيانات Database seeding.</li><li>بنية قاعدة البيانات الخاصة بمشروع Larashop.</li><li>ملفات التهجير لقاعدة بيانات Larashop.</li></ul><h2 id="متطلبات-التهجير">متطلبات التهجير</h2><p>يجب أولا إنشاء قاعدة بيانات في نظام إدارة قواعد البيانات المستخدم (MySQL في حالتنا) وإعداد معطيات الاتصال بها في Laravel ولدى أداة سطر الأوامر Artisan.</p><h3 id="إنشاء-قاعدة-بيانات">إنشاء قاعدة بيانات</h3><p>نفذ الأمر التالي في سطر أوامر MySQL أو استخدم التطبيق المفضّل لديك (<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D9%8F%D8%AB%D8%A8%D9%91%D9%90%D8%AA-%D9%88%D8%AA%D8%A4%D9%85%D9%91%D9%90%D9%86-phpmyadmin-%D8%B9%D9%84%D9%89-ubuntu-1404-r35/">PHPMyAdmin</a> مثلا) لإنشاء قاعدة بيانات larashop:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">CREATE DATABASE `larashop`;</pre><h3 id="إعداد-laravel-للاتصال-بقاعدة-البيانات">إعداد Laravel للاتصال بقاعدة البيانات</h3><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/">الدرس الأول</a> من <a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">هذه السلسلة</a> للاتصال بقاعدة بيانات باسم <code>larashop</code>. في ما يلي تذكير بخطوات الإعداد.</p><p>افتح الملف <code>config/database.php</code> واعثر على الأسطُر التالية:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">'mysql' =&gt; [
  'driver' =&gt; 'mysql',
  'host' =&gt; env('DB_HOST', 'localhost'),
  'database' =&gt; env('DB_DATABASE', 'forge'),
  'username' =&gt; env('DB_USERNAME', 'forge'),
  'password' =&gt; env('DB_PASSWORD', ''),
  'charset' =&gt; 'utf8',
  'collation' =&gt; 'utf8_unicode_ci',
  'prefix' =&gt; '',
  'strict' =&gt; false,
],</pre><p>حدّث القيم التالية لتوافق إعدادات MySQL لديك:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'database'  =&gt; env('DB_DATABASE', 'larashop'),
'username'  =&gt; env('DB_USERNAME', 'root'),
'password'  =&gt; env('DB_PASSWORD', 'melody'),
</pre><h3 id="إعداد-معطيات-اتصال-artisan-بقاعدة-البيانات">إعداد معطيات اتصال Artisan بقاعدة البيانات</h3><p>يواجه الكثير من المطورين رسالة الخطأ التالية عند العمل على تهجير قواعد البيانات باستخدام أداة Artisan:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Access denied for user 'homestead'@' localhost' (using password: YES)</pre><p>ستظهر الرسالة أعلاه حتى ولو كانت معطيات الاتصال في الملف <code>configuration/database.php</code> صحيحة. يعود السبب في ذلك إلى أن Artisan يستخدم المعطيات الموجودة في الملف <code>env.</code>. الحل هو إذن تحرير الملف <code>env.</code> الواقع في مجلد التطبيق، ستجد ما يلي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">APP_ENV=local
APP_DEBUG=true
APP_KEY=aqk5XHULL8TZ8t6pXE43o7MBSFchfgy2

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
</pre><p><span style="line-height: 1.6;">حدث المتغيرات التالية:</span></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret</pre><p><span style="line-height: 1.6;">لتصبح:</span></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">DB_HOST=localhost
DB_DATABASE=larashop
DB_USERNAME=root
DB_PASSWORD=melody
</pre><p><span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.6;">احرص على موافقة اسم قاعدة البيانات، اسم المستخدم وكلمة مروره للمعطيات لديك. احفظ التعديلات.</span></p><h2 id="تهجير-قواعد-البيانات-بأداة-artisan">تهجير قواعد البيانات بأداة Artisan</h2><p>ينشئ أمر artisan ملفا على المسار <code>database/migrations</code> لكل عملية تهجير. يمكن تغيير المسار الخاص بحفظ ملفات التهجير إن أردت ولكننا هنا سنكتفي بالمسار المبدئي.</p><p>ننفذ الأمر التالي لإنشاء أول ملف تهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration create_drinks_table</pre><p>تظهر رسالة باسم ملف التهجير الجديد. اخترنا اسم <code>create_drinks_table</code> للدلالة على أن التهجير ينشئ جدولا باسم <code>drinks</code> في قاعدة البيانات. نتيجة الأمر هي إنشاء ملف للتهجير بنفس الاسم الذي أعطيناه مع إضافة ختم زمني قبله، مثلا:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">2015_12_21_215845_create_drinks_table.php</pre><h3 id="بنية-ملف-التهجير">بنية ملف التهجير</h3><p>ندرس الآن محتوى ملف التهجير الذي أنشأناه للتو. افتح الملف التالي لرؤية محتواه (انتبه إلى أن اسم الملف يبدأ بختم زمني للحظة إنشائه):</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">database/migrations/2015_12_21_215845_create_drinks_table.php</pre><p>نجد ما يلي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateDrinksTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        //
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        //
    }
}</pre><ul><li><p>يعرف ملف التهجير صنفا جديدا باسم <code>CreateDrinksTable</code> يمدد الصنف <code>Migration</code>:</p></li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">CreateDrinksTable extends Migration</pre><ul><li><p>داخل الصنف <code>CreateDrinksTable</code> توجد دالة باسم <code>up</code>. تنفّذ تعليمات الدالة <code>up</code> عند تشغيل التهجير.</p></li><li>توجد أيضا دالة باسم <code>down</code> في الصنف <code>CreateDrinksTable</code>. تنفذ تعليمات الدالة <code>down</code> عند التراجع عن تغييراتِ تهجير.</li></ul><h3 id="ملف-تهجير-لإنشاء-جدول-بقاعدة-البيانات">ملف تهجير لإنشاء جدول بقاعدة البيانات</h3><p>ليمكن إنشاء جدول في قاعدة البيانات فجيب تعريف حقوله في ملف التهجير. نعيد فتح ملف التهجير السابق ونعدله ليصبح محتواه التالي :</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateDrinksTable extends Migration {

    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up() {
        Schema::create('drinks', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name',75)-&gt;unique();
            $table-&gt;text('comments')-&gt;nullable();
            $table-&gt;integer('rating');
            $table-&gt;date('juice_date');
            $table-&gt;timestamps();        
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down() {
        Schema::dropIfExists('drinks');
    }
}</pre><ul><li>في الدالة <code>up</code>: نستدعي الدالة <code>create</code> المعرَّفة في الصنف <code>Schema</code> ونمرر لها معطيين، الأول اسم الجدول الذي نريد إنشاءه <code>drinks</code>، والمعطى الثاني دالة غير محدّدة الاسم تعرّف حقول الجدول. نستخدم كائنا من صنف <code>Blueprint</code> لتعريف الجدول.</li><li>نعرف أول حقل من الجدول وهو الحقل <code>id</code>. تعرف الدالة <code>increments</code> التابعة للصنف <code>Blueprint</code> عددا طبيعيا (عدد صحيح إشارته موجبة) يزداد تلقائيّا مع كل إدخال للبيانات في الجدول.</li><li>الحقل الثاني هو حقل الاسم <code>name</code>، الذي نعرفه بالدالة <code>string</code>. تنشئ الدالة <code>string</code>حقلا من سلسلة محارف مع تحديد طول السلسلة (75 في المثال). نعلّم الحقل <code>name</code> بالدالة <code>unique</code> \لجعله وحيدا وهو ما يعني أنه لا يمكن لتسجيلتين في الجدول أن تحويا نفس القيمة بالنسبة لهذا الحقل.</li><li>الحقل الثالث <code>comments</code> نصي، وتستخدم الدالة <code>text</code> لتعريفه. نتيح إمكانية ألا يحوي الحقل بيانات باستخدام الدالة <code>nullable</code>.</li><li>الحقل الرابع <code>rating</code> للتقيمات. نستخدم الدالة <code>integer</code> للإشارة إلى أنه عدد صحيح.</li><li>ثم نضيف حقلا لتخزين تاريخ المشروب <code>juice_date</code> ونستخدم الدالة <code>date</code> لهذا الغرض.</li><li>تُستخدم الدالة <code>timestamps</code> لإضافة حقلين هما <code>created_at</code> و<code>updated_at</code> في الجدول تلقائيا. الحقلان عبارة عن ختم زمني ل، على التوالي، تاريخ إضافة التسجيلة إلى قاعدة البيانات وتاريخ آخر تحديث عليها.</li><li>في الدالة <code>down</code> نحذف الجدول <code>drinks</code> من قاعدة البيانات في حالة وجوده.</li></ul><p>ننفذ بعد حفظ ملف التهجير الأمر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>ستظهر مخرجات في سطر الأوامر على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_12_21_215845_create_drinks_table</pre><p>إن نظرت في جداول قاعدة البيانات الآن فستجد التالي:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_artisan__migrate.png.f264699b68b214c5e118ca2660f89ceb.png"><img data-fileid="10340" class="ipsImage ipsImage_thumbnailed" alt="01_artisan__migrate.thumb.png.6f23c5237b" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_artisan__migrate.thumb.png.6f23c5237bbd250852c9e8260a0c8f2d.png"></a></p><p>ستلاحظ وجود أربعة جداول من بينها جدول <code>drinks</code>. الجداول الأخرى أنشأها Laravel لأن ملفات تهجيرها تأتي مبدئيا مع Laravel.</p><h3 id="التراجع-عن-التعديلات">التراجع عن التعديلات</h3><p>يوفر التهجير إمكانية التراجع عن تعديلاته والعودة إلى حالة قاعدة البيانات قبل تنفيذه. أنشأنا في الفقرة السابقة جداول في قاعدة البيانات، ننفذ الأمر التالي للتراجع عن ذلك:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate:rollback</pre><p>تظهر الرسائل التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Rolled back: 2015_12_21_215845_create_drinks_table
Rolled back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_000000_create_users_table</pre><p>إن أعدت التحقق في MySQL سترى أن الجدول <code>drinks</code> لم يعد موجودا.</p><p>نعيد إنشاء الجدول بتنفيذ التهجير مرة أخرى:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>تمكن ملاحظة أن تنفيذ التهجير يكون بالتسلسل الزمني التصاعدي لتاريخ إنشاء ملفات التهجير (من الأقدم إلى الأحدث)، في ما يكون التراجع بتنفيذ ملفات التهجير حسب التسلسل الزمني التنازلي (من الأحدث إلى الأقدم).</p><h2 id="إدارة-جداول-البيانات-في-laravel-باستخدام-التهجير">إدارة جداول البيانات في Laravel باستخدام التهجير</h2><p>سنرى في هذه الفقرة كيفية استخدام التهجير للقيام بأشغال شائعة على جداول قواعد البيانات.</p><h3 id="إدراج-بيانات">إدراج بيانات</h3><p>سنرى الآن كيفية استخدام التهجير لإدراج بيانات في جدول أثناء إنشائه. ننشئ جدولا بالموظفين <code>employees</code> وندرج فيه 33 تسجيلة بالاعتماد على مكتبة Faker (سنخصص درسا لتفصيل استخدام Faker).</p><p>نفذ الأمر التالي لإنشاء ملف تهجير لجدول <code>employees</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration employees</pre><p>نفتح الملف المنشأ للتو ونضيف الشفرة التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Employees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('employees', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name');
            $table-&gt;string('email')-&gt;unique();
            $table-&gt;string('contact_number');
            $table-&gt;timestamps();       
        }); 

        $faker = Faker\Factory::create();
        $limit = 33;

        for ($i = 0; $i &lt; $limit; $i++) {
            DB::table('employees')-&gt;insert([ //,
               'name' =&gt; $faker-&gt;name,
               'email' =&gt; $faker-&gt;unique()-&gt;email,
               'contact_number' =&gt; $faker-&gt;phoneNumber,
            ]);
        }
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('employees');
    }
}
</pre><ul><li><p>ننشئ كائنا من صنف Faker بالتعليمة</p></li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$faker = Faker\Factory::create();</pre><ul><li><p>نحدد عدد التسجيلات التي نود إدراجها: <code>limit$</code>.</p></li><li>نستخدم حلقة <code>for</code> التكرارية لإضافة التسجيلات إلى الجدول. تولد التعليمة <code>faker-&gt;name$</code> اسما وهميّا، <code>faker-&gt;unique()-&gt;email$</code> اسم بريد وحيد و<code>faker-&gt;phoneNumber$</code> رقم هاتف وهميا.</li></ul><p>الأمر التالي ينفذ التهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>تظهر الرسالة التالية دلالة على تهجير الجدول <code>employees</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Migrated: 2015_12_21_225233_employees</pre><p> </p><p>إن بحثت الآن عن محتوى الجدول <code>employees</code>، مثلا بتنفيذ الاستعلام التالي في سطر أوامر MySQL:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">SELECT * FROM employees;</pre><p>ستحصُل على أسماء الموظفين، عناوينهم البريدية وأرقام هواتفهم.</p><p>نتراجع عن إنشاء الجدول <code>employees</code> بتنفيذ الأمر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate:rollback</pre><p>تظهر رسالة دلالة على التراجع عن إنشاء الجدول. نفتح ملف التهجير للتعديل عليه ثم نضع الشفرة الخاصة بإدراج بيانات وهمية بين علامتي تعليق، هكذا:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">/*
$faker = Faker\Factory::create();

$limit = 33;

for ($i = 0; $i &lt; $limit; $i++) {
  DB::table('employees')-&gt;insert([ //,
    'name' =&gt; $faker-&gt;name,
    'email' =&gt; $faker-&gt;unique()-&gt;email,
    'contact_number' =&gt; $faker-&gt;phoneNumber,
  ]);
}
*/</pre><p>احفظ ملف التهجير ثم نفذ الأمر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>سيُنشأ جدول <code>employees</code> من جديد ولكن هذه المرة دون إدراج تسجيلات في الجدول.</p><h3 id="إضافة-عمود-إلى-جدول-أو-حذفه-منه">إضافة عمود إلى جدول أو حذفه منه</h3><p>نفرض أننا نود إضافة عمود جديد <code>gender</code> لتخزين جنس الموظّف، مباشرة بعد العمود <code>contact_number</code>. ننفذ الأمر التالي لإنشاء ملف تهجير باسم <code>add_gender_to_employees</code> مع تحديد الجدول الذي نريد العمل عليه وهو <code>employees</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration add_gender_to_employees --table=employees</pre><p>تشير التعليمة <code>table=employees--</code> إلى أننا نريد العمل على الجدول <code>employees</code> الموجود في قاعدة البيانات.</p><p>افتح ملف التهجير المنشأ بعد الأمر السابق، وعدله ليصبح على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddGenderToEmployees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table-&gt;string('gender')-&gt;after('contact_number');
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table-&gt;dropColumn('gender');
        });
    }
}
</pre><ul><li>في الدالة <code>up</code> أضفنا حقلا جديدا من نوع <code>string</code> (سلسلة محارف) وحددنا مكانه بأنه بعد العمود <code>contact_number</code>.</li><li>في الدالة <code>down</code> نحذف الحقل <code>gender</code>.</li></ul><p>الآن عند تنفيذ أمر التهجير <code>php artisan migrate</code> ستلاحظ إضافة عمود جديد باسم <code>gender</code> بعد عمود <code>contact_number</code>.</p><h3 id="تغيير-نوع-عمود">تغيير نوع عمود</h3><p>يحتاج تغيير نوع العمود لتثبيت حزمة Doctrine Database Abstract Layer, DBAL. تُستخدم هذه الحزمة لتهجيرات التعديل على الجداول Alter table.</p><p>سنستخدم أداة إدارة الاعتماديات Composer لتثبيت الحزمة. افتح ملف <code>composer.json</code> الذي يوجد في مجلد التطبيق. ابحث عن مقطع <code>require</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">"require": {
  "php": "&gt;=5.5.9",
  "laravel/framework": "5.2.*"
},</pre><p>توجد في هذا المقطع حزم المكتبات التي يحتاجها تطبيقنا. حتى الآن توجد حزمتان فقط هما <code>php</code> و<code>laravel</code>. يشير الجزء الأول (قبل النقطتين) إلى اسم الحزمة، في ما يشير الثاني لإصدارها. نضيف حزمة dbal` إلى هذه الاعتماديات، وذلك على النجو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">"require": {
  "php": "&gt;=5.5.9",
  "laravel/framework": "5.2.*",
  "doctrine/dbal": "v2.4.2"
},
</pre><p>لاحظ  الفاصلة اللاتينية التي أضفناها بعد حزمة Laravel.</p><p>نفذ الأمر التالي لتحديث المشروع:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">composer update</pre><p>عند إنشاء العمود <code>gender</code> لم نحدد طول الحقل، أي أنه سيأخذ الطول المبدئي للحقول من نوع <code>string</code> وهو255 محرفا. ننشئ ملف تهجير جديدا لتعديل طول الحقل ليصبح 5 كحد أقصى.</p><p>نعدل الملف على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint" style="line-height: 22.4px;">php artisan make:migration modify_gender_in_employees --table=employees</pre><h3 id="قبول-فراغ-الحقول-في-الجدول">قبول فراغ الحقول في الجدول</h3><p>يفترض Laravel عند إنشاء الحقول أنها لا تقبل فراغ القيمة، أي أنه يجب ذكر قيمة للحقل عند إدراج تسجيلات في الجدول. يمكننا تغيير هذا الإعداد المبدئي وجعل قيمة حقل ما اختيارية. سنأخذ الحقل <code>gender</code> للتمثيل به.</p><p>ننشئ ملفا للتهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration make_gender_null_in_employees --table=employees</pre><p>ثم نعدله على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class MakeGenderNullInEmployees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table-&gt;string('gender', 5)-&gt;nullable()-&gt;change();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
   {
        Schema::table('employees', function (Blueprint $table) {
            $table-&gt;string('gender', 5)-&gt;change();
        });
    }
}
</pre><ul><li>تجعل الدالة <code>nullable</code> الحقل <code>gender</code> يقبل قيما فارغة.</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan migrate
</pre><h3 id="إضافة-مفتاح-خارجي-foreign-key">إضافة مفتاح خارجي Foreign key</h3><p>نصنف موظفينا حسب القسم الذي يعملون فيه. ننشئ جدولا للأقسام <code>depts</code> ثم نضيف مفتاحا خاريجا في جدول الموظفين <code>employees</code>.</p><p>الأمر أدناه ينشئ ملف تهجير لجدول الأقسام:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration depts</pre><p>عدل ملف التهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Depts extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('depts', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name');
            $table-&gt;timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('depts');
    }
}</pre><p>ثم ننفذ أمر التهجير لإنشاء الجدول:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate</pre><p>يُشترط لتصح علاقة عبر مفتاح خارجي بين جدولين أن يكون المفتاح الخارجي والمفتاح الرئيس Primary key متطابقين في النوع. استخدمنا في تعريف المفتاح الرئيس <code>id</code>ضمن الجدول <code>depts</code> دالة <code>increments</code> التي تعطي النوع عددا طبيعيا من عشرة أرقام ;<code>(unsigned integer INT(10</code> وهو ما يعني أننا سنعطي نفس النوع للمفتاح الخارجي الذي سننشئه في الجدول <code>employees</code>. الفرق أن المفتاح الخارجي لا يزداد تلقائيا لذا سنستخدم الدالة <code>unsignedInteger</code> التي لها نفس مفعول <code>increments</code> من حيث نوع الحقل وطوله، مع فرق أنها لا تضيف الازدياد التلقائي.</p><p><strong>ملحوظة:</strong> حتى تمكن إضافة مفتاح خارجي في الجدول <code>employees</code> يجب أن يكون الجدول فارغا (بدون تسجيلات). لهذا السبب علقنا في فقرة ماضية الشفرة الخاصة بـFaker.</p><p>نفذ الأمر التالي لإنشاء ملف تهجير لإضافة حقل المفتاح الخارجي <code>dept_id</code> إلى الجدول <code>employees</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:migration add_dept_id_in_employees --table=employees</pre><p>ثم نعدل ملف التهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddDeptIdInEmployees extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table-&gt; unsignedInteger ('dept_id')-&gt;after('gender');
            $table-&gt;foreign('dept_id')
                  -&gt;references('id')-&gt;on('depts')
                  -&gt;onDelete('cascade');
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table-&gt;dropColumn('dept_id');
        });
    }
}</pre><p>ثم ننفذ التهجير:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan migrate </pre><h3 id="بذر-قواعد-البيانات">بذر قواعد البيانات</h3><p>يشير مصطلح البذر Seeding إلى عملية إضافة بيانات وهمية لأغراض الاختبار في قواعد البيانات. نطبق هذا الإجراء على جدول <code>drinks</code> الذي أنشأناه في أول الدرس.</p><p>نفذ الأمر التالي لإنشاء ملف للبذر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:seeder DrinksTableSeeder</pre><p>ينشئ الأمر ملفا باسم <code>DrinksTableSeeder.php</code> على المسار <code>database/seeds</code>. افتح الملف:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class DrinksTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}
</pre><p>يمدد الصنف <span style="font-family: monospace; line-height: 22.4px;">DrinksTableSeeder</span> الصنف <span style="font-family: monospace; line-height: 22.4px;">Seeder</span> ويعرّف الدالة <span style="font-family: monospace; line-height: 22.4px;">run</span><span style="line-height: 1.6;"> التي تُنفّذ عند تشغيل أمر البذر في Artisan. </span></p><p>عدل الملف ليصبح محتواه التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class DrinksTableSeeder extends Seeder {

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        
    <span style="font-family:monospace"><span style="color: rgb(0, 0, 0);">DB::</span><span style="color: rgb(178, 178, 178);">table(</span><span style="color: rgb(0, 0, 0);">'drinks')-&gt;</span><span style="color: rgb(178, 178, 178);">insert(</span><span style="color: rgb(0, 0, 0);">[ </span>
           'name' =&gt; 'Orange Juice',
           'comments' =&gt; 'Rich in C vitamin',
           'rating' =&gt; 9,
           'juice_date' =&gt; '2015-12-20',
       ]);</span>


}
</pre><p>أضفنا في الدالة <span style="font-family: monospace; line-height: 22.4px;">run</span> أمر إدراج في جدول البيانات drinks ومررنا مصفوفة توافق عناصرها حقول الجدول مع تحديد قيم عناصر المصفوفة. ننفذ الأمر أمر البذر لإضافة التسجيلة أعلاه إلى الجدول:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan db:seed --class=DrinksTableSeeder</pre><p>نمرر لأمر البذر <span style="font-family: monospace; line-height: 22.4px;">php artisan db::seed</span> اسم الملف المراد تنفيذه.</p><p>الآن عند التحقق نجد في جدول قاعدة البيانات التسجيلة التالية:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_seeding.png.597787d1a23b115b2516c6cfc797ea57.png"><img data-fileid="10341" class="ipsImage ipsImage_thumbnailed" alt="02_seeding.thumb.png.52cc250e5d895deb9d8" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_seeding.thumb.png.52cc250e5d895deb9d804fc7a027a867.png"></a></p><h2 id="قاعدة-البيانات-الخاصة-بمشروع-larashop">قاعدة البيانات الخاصة بمشروع Larashop</h2><p>تعرفنا في الفقرات الماضية على أساسيات التهجير في Laravel. سنجعل هذه المعرفة موضع التطبيق لإنشاء قاعدة بيانات لمشروع Larashop.</p><p>ستشنرك جميع الجداول في الحقول التالية التي أنشأناها لأغراض الفحص والتدقيق.</p><table style="line-height: 1.6;"><tbody><tr><th>التسلسل</th><th>الحقل</th><th>نوع البيانات</th><th>الوصف</th></tr><tr><td>1</td><td>created_at</td><td>    Timestamp</td><td>    ختم زمني لتاريخ إدراج التسجيلة</td></tr><tr><td>2</td><td>updated_at</td><td>    Timestamp</td><td>    ختم زمني لتاريخ تحديث التسجيلة</td></tr><tr><td>3</td><td>created_at_ip</td><td>   (Varchar(45</td><td>    عنوان IP المستخدم لإدراج التسجيلة</td></tr><tr><td>4</td><td>updated_at_ip</td><td>    (Varchar(45</td><td>    عنوان IP المستخدم لتحديث التسجيلة</td></tr></tbody></table><h3><span style="line-height: 22.4px;">جدول منشورات المدونة</span></h3><table><tbody><tr><th>التسلسل</th><th>الحقل</th><th>نوع البيانات</th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>    INT</td><td>    مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا</td></tr><tr><td>2</td><td>url</td><td>    (Varchar(255</td><td>    رابط الصفحة</td></tr><tr><td>3</td><td>title</td><td>    (Varchar(140</td><td>     عنوان الصفحة</td></tr><tr><td>4</td><td>description</td><td>    (Varchar(170</td><td>     وصف يظهر في محركات البحث</td></tr><tr><td>5</td><td>content</td><td>    Text</td><td>     محتوى الصفحة أو المنشور </td></tr><tr><td>6</td><td>conblogtent</td><td>    (Tinyint(1</td><td>    يحدد ما إذا كان المنشور صفحة</td></tr></tbody></table><h3><span style="line-height: 1.6;">جدول التصنيفات</span></h3><table><tbody><tr><th>التسلسل</th><th>الحقل</th><th>نوع البيانات</th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>    INT</td><td>    مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا</td></tr><tr><td>2</td><td>name</td><td>    (Varchar(255</td><td>    اسم التصنيف</td></tr></tbody></table><h3><span style="line-height: 22.4px;">جدول العلامات التجارية</span></h3><table><tbody><tr><th>التسلسل</th><th>الحقل</th><th>نوع البيانات</th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>    INT</td><td>    مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا</td></tr><tr><td>2</td><td>name</td><td>    (Varchar(255</td><td>    اسم العلامة التجارية</td></tr></tbody></table><h3>جدول المنتجات</h3><p>لكل منتج تصنيف وعلامة تجارية وحيدين.</p><table><tbody><tr><th>التسلسل</th><th>الحقل</th><th>نوع البيانات</th><th>الوصف</th></tr><tr><td>1</td><td>id</td><td>    INT</td><td>     مفتاح رئيس (AUTOINCREMENT) عدد طبيعي يزداد تلقائيا</td></tr><tr><td>2</td><td>name</td><td>    (Varchar(255</td><td>    اسم المنتج</td></tr><tr><td>3</td><td>title</td><td>    (Varchar(140</td><td>    عنوان المنتج</td></tr><tr><td>4</td><td>description</td><td>    (Varchar(500</td><td>    عنوان المنتج</td></tr><tr><td>5</td><td>price</td><td>    int</td><td>    ثمن المنتج</td></tr><tr><td>6</td><td>category_id</td><td>    int</td><td>    معرف تصنيف المنتج</td></tr><tr><td>7</td><td>brand_id</td><td>    int</td><td>    معرف العلامة التجارية للمنتج</td></tr></tbody></table><h3><span style="line-height: 1.2;">ملفات التهجير لجداول قاعدة بيانات المشروع</span></h3><p>سننشئ في هذه الفقرة ملفات تهجير لجداول البيانات المذكورة أعلاه؛ سنضيف أيضا بعض البيانات الوهمية إلى الجداول باستخدام آلية البذر التي تعرفنا عليها سابقا.</p><h4 id="توليد-ملفات-التهجير">توليد ملفات التهجير</h4><p>افتح سطر الأوامر ونفذ الأوامر التالية لتوليد ملفات الجداول:</p><p>جدول منشورات المدونة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan make:migration create_posts_table
</pre><p>جدول تصنيفات المنتجات</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan make:migration create_categories_table</pre><p>جدول العلامات التجارية للمنتجات</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan make:migration create_brands_table</pre><p>جدول المنتجات</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan make:migration create_products_table</pre><h4 id="تحرير-ملفات-التهجير">تحرير ملفات التهجير</h4><p>ننتقل لتحرير كل ملف من ملفات التهجير.</p><p>جدول منشورات المدونة</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('posts', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('url', 255)-&gt;unique();
            $table-&gt;string('title', 140);
            $table-&gt;string('description', 170);
            $table-&gt;text('content');
            $table-&gt;boolean('blog');
            $table-&gt;timestamps();
            $table-&gt;string('created_at_ip');
            $table-&gt;string('updated_at_ip');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('posts');
    }
}
</pre><p>جدول التصنيفات</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('categories', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name', 255)-&gt;unique();
            $table-&gt;timestamps();
            $table-&gt;string('created_at_ip');
            $table-&gt;string('updated_at_ip');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('categories');
    }
}
</pre><p>جدول العلامات التجارية</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBrandsTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('brands', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name', 255)-&gt;unique();
            $table-&gt;timestamps();
            $table-&gt;string('created_at_ip');
            $table-&gt;string('updated_at_ip');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('brands');
    }
}
</pre><p>جدول المنتجات</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
                $table-&gt;increments('id');
                $table-&gt;string('name', 255)-&gt;unique();
                $table-&gt;string('title', 140);
                $table-&gt;string('description', 500);
                $table-&gt;integer('price');
                $table-&gt;unsignedInteger('category_id');
                $table-&gt;unsignedInteger('brand_id');
                $table-&gt;timestamps();
                $table-&gt;string('created_at_ip');
                $table-&gt;string('updated_at_ip');
                // مفتاح خارجي على جدول التصنيفات
                $table-&gt;foreign('category_id')
                -&gt;references('id')-&gt;on('categories')
                -&gt;onDelete('cascade');
                // مفتاح خارجي على جدول العلامات التجارية
                $table-&gt;foreign('brand_id')
                -&gt;references('id')-&gt;on('brands')
                -&gt;onDelete('cascade');
            });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}</pre><h3 id="بذر-قاعدة-بيانات-المشروع">بذر قاعدة بيانات المشروع</h3><p>ندرج بيانات وهمية في جداول قاعدة البيانات قصدَ الاختبار.</p><p>أنشئ ملفات البذر بتنفيذ الأوامر أدناه على التوالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:seeder CategoriesTableSeeder
php artisan make:seeder BrandsTableSeeder
php artisan make:seeder ProductsTableSeeder</pre><p>يحوي جدول المنتجات مفتاحين خارجيين لجدولي التصنيف والعلامة التجارية. لذا يجب البدء بهما (لا يصح إدراج مفتاح خارجي لتسجيلة غير موجودة في الجدول الذي مثل المفتاح الخارجي مرجعا إليه).</p><ul><li><p>بذر جدول التصنيفات</p></li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class CategoriesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('categories')-&gt;insert(['name' =&gt; 'MENS']);
        DB::table('categories')-&gt;insert(['name' =&gt; 'WOMENS']);
        DB::table('categories')-&gt;insert(['name' =&gt; 'KIDS']);
        DB::table('categories')-&gt;insert(['name' =&gt; 'FASHION']);
        DB::table('categories')-&gt;insert(['name' =&gt; 'CLOTHING']);
    }
}
</pre><ul><li>بذر جدول العلامات التجارية</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class BrandsTableSeeder extends Seeder {

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run() {
        DB::table('brands')-&gt;insert(['name' =&gt; 'ACNE']);
        DB::table('brands')-&gt;insert(['name' =&gt; 'RONHILL']);
        DB::table('brands')-&gt;insert(['name' =&gt; 'ALBIRO']);
        DB::table('brands')-&gt;insert(['name' =&gt; 'ODDMOLLY']);
    }
}
</pre><ul><li>بذر جدول المنتجات</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

use Illuminate\Database\Seeder;

class ProductsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('products')-&gt;insert(['name' =&gt; 'Mini skirt black edition', 'title' =&gt; 'Mini skirt black edition','description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' =&gt; 35,'category_id' =&gt; 1,'brand_id' =&gt; 1,]);
        DB::table('products')-&gt;insert(['name' =&gt; 'T-shirt blue edition', 'title' =&gt; 'T-shirt blue edition','description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' =&gt; 64,'category_id' =&gt; 2,'brand_id' =&gt; 3,]);
        DB::table('products')-&gt;insert(['name' =&gt; 'Sleeveless Colorblock Scuba', 'title' =&gt; 'Sleeveless Colorblock Scuba','description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna','price' =&gt; 13,'category_id' =&gt; 3,'brand_id' =&gt; 2,]);
    }
}
</pre><p>ثم ننفذ أوامر البذر لكل جدول.</p><h2 id="خاتمة">خاتمة</h2><p>تعرفنا في هذا الدرس على تهجير قواعد البيانات وبذرها في Laravel. كما أننا حددنا هيكلة قاعدة بيانات المشروع الذي نعمل عليه. في الدروس القادمة سنتعرف على إطار عمل Eloquent الذي سنعتمد عليه للتخاطب مع قاعدة البيانات وعرض محتوياتها عند الاقتضاء.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-migrations">Laravel 5 Migrations</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">224</guid><pubDate>Wed, 06 Jan 2016 08:38:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x642;&#x648;&#x627;&#x644;&#x628; Blade &#x644;&#x625;&#x646;&#x634;&#x627;&#x621; &#x639;&#x631;&#x648;&#x636; 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%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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-blade-templates.png.1c8e299088801dacef46337b334cab0b.png" /></p>

<p id="مقدمة">أنشأنا في <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-laravel-%D9%85%D8%AD%D8%B3%D9%91%D9%8E%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-r217/">الدرس السابق</a> مسارات تكتفي بكتابة عبارات في صفحة الويب. سننشئ في هذا الدرس عروضا لتقديمها إلى الزوار حسب الرابط الذي يختارونه؛ نستخدم لهذا الغرض قوالب Blade.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a>.</li><li>نظام Blade للقوالب.<span style="line-height: 22.4px; text-align: right;"> </span><span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-blade-templates.png.8625b178979e10f49c67c9c42f41afdd.png"><img data-fileid="10604" class="ipsImage ipsImage_thumbnailed" alt="laravel5-blade-templates.thumb.png.7bc42" src="https://academy.hsoub.com/uploads/monthly_2016_01/laravel5-blade-templates.thumb.png.7bc42b84193c2ac3999d1423110a39d2.png"></a></p><p>تعرِّف القوالب Templates إطارا عامًّا للعرض، يحدّد أجزاءه والعناصر التي تكوّنه. Blade هو نظام إدارة القوالب والتعامل معها المضمَّن في Laravel.</p><p>نحصُل بنهاية هذا الدرس على الواجهة التالية.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_larashop.png.a72e5645d6c8b59a9b923e4c965472ac.png"><img data-fileid="9864" class="ipsImage ipsImage_thumbnailed" alt="01_larashop.thumb.png.7311920014fa3c410a" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_larashop.thumb.png.7311920014fa3c410a404275b7b1381d.png"></a></p><p>يشمل الدرس المواضيع التالية:</p><ul><li>توريث القالب.</li><li>المخطّط الرئيس Master layout.</li><li>تمديد المخطّط الرئيس.</li><li>عرض المتغيرات.</li><li>التعبيرات الشرطية Conditional statements في Blade.</li><li>الحلقات التكراراية Loops في Blade.</li><li>تنفيذ تعليمات PHP في Blade,</li></ul><p>تنتهي جميع ملفات العروض في Blade بالامتداد <code>blade.php</code>.</p><h2 id="توريث-القوالب">توريث القوالب</h2><p>يمكن تعريف توريث القوالب بأنه تلك الخاصيّة التي تسمح بجمع عناصر مشتركة بين عدة عروض ضمن عرض تعيد استخدامه عند الحاجة مع إضافة العناصر الخاصة بالصفحة؛ مما يجنب تكرار العناصر المشتركة في كلّ مرة.</p><h2 id="المخطط-الرئيس">المخطط الرئيس</h2><p>تُجمع العناصر المشتركة في عرض يُطلَق عليه المخطّط الرئيس تعيد العروض الأخرى استخدامه وتضيف إليه العناصر الخاصة بها.</p><ul><li>سننشئ في ما يلي مخطّطا رئيسا نضمنه عناصر مشتركة بين العروض.</li><li>ننشئ مجلدا جديدا باسم <code>layouts</code> على المسار <code>resources/views/</code>. ثم ننشئ ملفا باسم <code>master.blade.php</code> ضمن المجلد <code>layouts</code>.</li><li>نضيف الشفرة التالية إلى الملف <code>master.blade.php</code>:</li></ul><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;@yield('title')&lt;/title&gt;
    &lt;/head&gt;
    &lt;body dir="rtl"&gt;
        @section('sidebar')
            هنا يوجد محتوى المقطع sidebar في المخطط الرئيس.
        @show

        &lt;div class="container"&gt;
            @yield('content')
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre><p>قالب Blade عبارة عن وسوم HTML مع تعليمات خاصة بنظام القوالب. يستخدم القالب أعلاه ثلاث تعليمات هي <code>section </code>،<span style="font-family:courier new,courier,monospace;">@</span><code>yield@</code> و <code>show@</code>.</p><ul><li>تُستخدم التعليمة <code>section@</code> لتعريف مقطع (عنصر) من القالب.</li><li>بينما تستخدم التعليمة <code>yield@</code> لعرض محتوى مقطع معطى (مقطع باسم <code>title</code> في أول استخدام للتعليمة <code>yield@</code> في المخطّط السابق).</li><li>أما التعليمة <code>show@</code> فتستخدم لعرض محتوى مقطع.</li></ul><h2 id="تمديد-المخطط-الرئيس">تمديد المخطط الرئيس</h2><p>ننشئ الآن قالبا يمدّد القالب الرئيس السابق.</p><p>أنشئ ملفا باسم <code>page.blade.php</code> في المسار <code>resources/views</code> وأضف إليه الشفرة التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@extends('layouts.master')

@section('title', 'عنوان الصفحة')

@section('sidebar')
@parent
  &lt;p&gt;هذا المحتوى ملحق بمحتوى المقطع sidebar الموجود في المخطط الرئيس&lt;/p&gt;
@endsection

@section('content')
  &lt;p&gt;جسم الصفحة.&lt;/p&gt;
@endsection</pre><ul><li>تشير التعليمة <strong><span style="font-family:courier new,courier,monospace;">('<code>extends('layouts.master</code></span></strong> إلى أننا في صدد تمديد المخطّط الرئيس <code>master.blade.php</code> الموجود ضمن المجلد <code>layouts</code>.</li><li>تعيّن التعليمة <strong><span style="font-family:courier new,courier,monospace;">('<code>section('title', 'Page Title</code></span></strong> قيمة المقطع <code>title</code> المعرّف في المخطّط الرئيس. ثم نعرّف مقطع جديدا باسم <code>sidebar</code> ضمن العرض <code>page</code>. داخل المقطع <code>sidebar</code> نطبع محتوى المقطع الذي يحمل نفس الاسم في المخطّط الرئيس باستخدام التعليمة <code>parent@</code>، نضيف فقرة HTML باستخدام الوسم <span style="font-family:courier new,courier,monospace;"><code>&lt;p&gt;...&lt;/p&gt;</code></span> ثم ننهي المقطع <code>sidebar</code> بالتعليمة <code>endsection@</code>.</li><li>تعرّف التعليمة <strong><span style="font-family:courier new,courier,monospace;">('</span></strong><code><strong><span style="font-family:courier new,courier,monospace;">section('content</span></strong> </code>محتوى المقطع <code>content</code> وهو في هذا المثال الفقرة <code>&lt;p&gt;جسم الصفحة.&lt;/p&gt;</code>.</li></ul><p>في المخطط الرئيس توجد ثلاثة مقاطع وهي، حسب ترتيب الاستخدام، <code>sidebar </code>،<code>title</code> و <code>content</code>. بالنسبة للمقطعين <code>title</code> و <code>content</code> فقد اكتفينا بتحديد أماكنهما (التعليمة <code>yield@</code>)؛ أما المقطع <code>sidebar</code> فقد عرفنا محتواه وعرضناه (التعليمتان <code>section@</code> و <code>show@</code>).</p><p>في القالب <code>page</code> أعدنا استخدام المخطّط الرئيس ثم أعطينا قيمتي المقطعين <code>title</code> و <code>content</code> المعرّفين سابقا. بالنسبة للمقطع <code>sidebar</code> فقد أعدنا تعريفه مع إعادة استخدام محتوى المقطع المماثل له في الاسم ضمن القالب الرئيس (تعليمة <code>parent@</code>) وإضافة فقرة نصية أخرى.<br>سنضيف مسارا خاصًّا لتجربة عمل نظام القوالب. افتح ملف المسارات <code>routes.php</code> وأضف المسار التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('blade', function () { return view('page'); });</pre><p>احفظ التعديلات.</p><p>الآن أدخل الرابط في المتصفح:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">http://larashop.dev/blade</pre><p>ستحصل على الصفحة التالية:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_blade_templating.png.9393bb43ead604e4d0108fc51dc04a86.png"><img data-fileid="9865" class="ipsImage ipsImage_thumbnailed" alt="02_blade_templating.thumb.png.36e12c3491" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_blade_templating.thumb.png.36e12c349175e71602db915d39ce5336.png"></a></p><h2 id="استخدام-متغيرات-في-قوالب-blade">استخدام متغيرات في قوالب blade</h2><p>نعرّف متغيرا باسم <code>name</code> ونمرره إلى قالب blade. افتح ملف المسارات وغيره بحيث يصبح على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('blade', function () {
  return view('page',array('name' =&gt; 'حسوب'));
});</pre><p>احفظ التعديلات.</p><p>نحدّث القالب <code>page.blade.php</code> لإظهار المتغير الذي يمرره المسار:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@extends('layouts.master')

@section('title', 'عنوان الصفحة')

@section('sidebar')
@parent
  &lt;p&gt;هذا المحتوى ملحق بمحتوى المقطع sidebar الموجود في المخطط الرئيس&lt;/p&gt;
@endsection

@section('content')
  &lt;h2&gt;{{$name}}&lt;/h2&gt; 
  &lt;p&gt;جسم الصفحة&lt;/p&gt;
@endsection</pre><p>تستخدم التعليمة <code>{{name$}}</code> لطباعة قيمة المتغير <code>name$</code>.</p><p>احفظ التعديلات ثم أعد تحميل الصفحة <code><a rel="external nofollow" href="http://larashop.dev/blade">http://larashop.dev/blade</a></code>. ستلاحظ وجود عنوان <span style="font-family:courier new,courier,monospace;"><code>h2</code></span> جديد هو <code>حسوب</code> التي هي قيمة المتغير الممرًّر لقالب <code>page.blade.php</code>.</p><h2 id="التعبيرات-الشرطية-في-blade">التعبيرات الشرطية في Blade</h2><p>يدعم نظام Blade التعبيرات الشرطية التي تحدّد ما يُعرض حسب شرط معرَّف مسبقا. سنمرر متغيرا إلى القالب ثم نختبر قيمته (الشرط) وحسب نتيجة الاختبار يكون العرض.</p><p>افتح ملف <code>routes.php</code> وعدل المسار بحيث يصبح ما يلي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('blade', function () {
  return view('page',array('name' =&gt; 'حسوب','day' =&gt; 'Friday'));
});</pre><p>أضفنا هنا متغيرا جديد باسم <code>day</code> وأعطيناه القيمة <code>Friday</code>. احفظ التعديلات.</p><p>افتح ملف القالب وعدله على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@extends('layouts.master')

@section('title', 'عنوان الصفحة')

@section('sidebar')
@parent
  &lt;p&gt;هذا المحتوى ملحق بمحتوى المقطع sidebar الموجود في المخطط الرئيس&lt;/p&gt;
@endsection

@section('content')
  &lt;h2&gt;{{$name}}&lt;/h2&gt;  
  &lt;p&gt;جسم الصفحة&lt;/p&gt;

  &lt;h2&gt;تعبير if الشرطي&lt;/h2&gt;

  @if ($day == 'Friday')
    &lt;p&gt;إنه يوم الجمعة&lt;/p&gt;
  @else
    &lt;p&gt;اليوم ليس يوم الجمعة&lt;/p&gt;
  @endif
@endsection</pre><p>إذا كانت قيمة المتغير <code>day</code> هي <code>Friday</code> نعرض الجملة <code><span style="font-family:courier new,courier,monospace;">&lt;p&gt;</span><span style="font-family:arial,helvetica,sans-serif;">إنه يوم الجمعة</span>&lt;/p&gt;</code> وإلا فإن الفقرة المعروضة تصبح <code>&lt;p&gt;اليوم ليس يوم الجمعة&lt;/p&gt;</code>.</p><p>احفظ التعديلات ثم أعد تنزيل الصفحة ولاحظ الفرق.</p><h2 id="الحلقات-التكراراية-في-blade">الحلقات التكرارية في Blade</h2><p>يدعم Blade كل الحلقات التكرارية التي يدعمها PHP. سنرى مثالا لاستخدام الحلقة التكرارية <code>foreach</code> لعرض محتويات مصفوفة Array في قالب Blade.</p><p>عدل ملف المسارات <code>routes.php</code> على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('blade', function () {
  $foods = array('Barbecue','Couscous','Fish');
  return view('page',array('name' =&gt; 'حسوب', 'day' =&gt; 'Friday', 'foods' =&gt; $foods));
});</pre><p>عرّفنا مصفوفة تحوي ثلاثة عناصر ومررناها إلى قالب Blade.</p><p>احفظ التعديلات ثم افتح ملف القالب وعدّله على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@extends('layouts.master')

@section('title', 'عنوان الصفحة')

@section('sidebar')
@parent
  &lt;p&gt;هذا المحتوى ملحق بمحتوى المقطع sidebar الموجود في المخطط الرئيس&lt;/p&gt;
@endsection

@section('content')
  &lt;h2&gt;{{$name}}&lt;/h2&gt; 
  &lt;p&gt;جسم الصفحة&lt;/p&gt;
 
  &lt;h2&gt;تعبير if الشرطي&lt;/h2&gt;

  @if ($day == 'Friday')
    &lt;p&gt;إنه يوم الجمعة&lt;/p&gt;
  @else
    &lt;p&gt;اليوم ليس يوم الجمعة&lt;/p&gt;
  @endif

  &lt;h2&gt;حلقة foreach التكرارية&lt;/h2&gt;
 
  @foreach ($foods as $food)
    {{$food}} &lt;br&gt;
  @endforeach
@endsection</pre><p>احفظ التعديلات ثم أعد تحميل الصفحة ولاحظ طباعة محتوى المصفوفة.</p><h2 id="تضمين-شفرة-php-في-قالب-blade">تضمين شفرة PHP في قالب Blade</h2><p>افتح ملف القالب وعدّله بإضافة سطر يستخدم إحدى دوالّ PHP (اخترنا الدالة <code>date</code>). يصبح ملف القالب كما يلي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@extends('layouts.master')
@section('title', 'عنوان الصفحة')

@section('sidebar')
@parent
  &lt;p&gt;هذا المحتوى ملحق بمحتوى المقطع sidebar الموجود في المخطط الرئيس&lt;/p&gt;
@endsection

@section('content')
  &lt;h2&gt;{{$name}}&lt;/h2&gt; 
  &lt;p&gt;جسم الصفحة&lt;/p&gt;

  &lt;h2&gt;تعبير if الشرطي&lt;/h2&gt;

  @if ($day == 'Friday')
    &lt;p&gt;إنه يوم الجمعة&lt;/p&gt;
  @else
    &lt;p&gt;اليوم ليس يوم الجمعة&lt;/p&gt;
  @endif

  &lt;h2&gt;حلقة Loop التكرارية&lt;/h2&gt;

  @foreach ($foods as $food)
    {{$food}} &lt;br&gt;
  @endforeach

  &lt;h2&gt;شفرة PHP&lt;/h2&gt;
  &lt;p&gt;تاريخ اليوم  {{date(' D M, Y')}}&lt;/p&gt;
@endsection</pre><p>وضعنا دالة PHP داخل معكوفين مزدوجين لتنفيذها.</p><p>أعد تنزيل الصفحة <code><a rel="external nofollow" href="http://laravel.dev/blade">http://laravel.dev/blade</a></code> بعد حفظ التعديلات.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/03_blade_templating.png.11d768c637ca9ce34cdc8244f7faf434.png"><img data-fileid="9866" class="ipsImage ipsImage_thumbnailed" alt="03_blade_templating.thumb.png.a32d69dc00" src="https://academy.hsoub.com/uploads/monthly_2015_12/03_blade_templating.thumb.png.a32d69dc00ab13436f593b2bbfefbcc6.png"></a></p><h2 id="العروض-المكونة-لمشروع-larahop">العروض المكونة لمشروع Larashop</h2><p>ذكرنا في بداية السلسلة أننا نهدف إلى إنشاء موقع للتسوق الإلكتروني. سنستخدم ما تعلمناه في هذا الدرس والدروس السابقة لبناء اللبنة الأولى من هذا المشروع وهي الجانب المرئي. لإعطاء وجه لائق لمشروعنا بحثنا عن تصميم HTML جاهز ووجدنا أن قالب Eshopper من موقع <a rel="external nofollow" href="https://shapebootstrap.net/">shapebootstrap.net</a> مناسب لما نريد. الخطوة التالية للحصول على تصميم HTML هي تحويله إلى قالب Blade يعمل مع Laravel.</p><p>سنبدأ أولا بمحتوى الملف المرفق وكيفية استخدامه للحصول على واجهة الموقع المعروضة في أول الدرس، ثم نشرح بعد ذلك تعليمات Blade التي لم نتطرق إليها حتى الآن.</p><h3 id="محتوى-الملف-المرفق">محتوى الملف المرفق</h3><p>يحوي الملف المرفق:</p><ul><li>عروض المشروع larashop.</li><li>ملف المتحكم Front الذي حدثناه ليحمّل عروض المشروع.</li><li>ملف المسارات.</li><li>الموارد المستخدمة في القالب: ملفات CSS، الصور، ملفات Js والخطوط.</li></ul><h3 id="العروض">العروض</h3><p>يحوي المشروع العروض التالية:</p><ul><li><strong><code>layout</code></strong>: وهو المخطط الرئيس ويوجد في المجلد الفرعي <code>layouts</code>.</li><li><strong><code>sidebar</code></strong>: وهو عرض مشترك بين صفحاتٍ عدة، يوجد في مجلد فرعي باسم <code>shared</code>.</li><li><strong><code>blog</code></strong>: صفحة المدونة.</li><li><strong><code>blog_post</code></strong>: صفحة منشور على المدونة.</li><li><strong><code>cart</code></strong>: صفحة سلة المشتريات.</li><li><strong><code>checkout</code></strong>: صفحة الدفع.</li><li><strong><code>contact_us</code></strong>: صفحة الاتصال.</li><li><strong><code>home</code></strong>: الصفحة الرئيسية.</li><li><strong><code>login</code></strong>: صفحة تسجيل الدخول.</li><li><strong><code>products</code></strong>: صفحة المنتجات.</li><li><strong><code>product_details</code></strong>: تفاصيل منتج.</li></ul><p>يجب أن توضع العروض في المجلد <code>resources/views</code>. تبدو بنية هذا المجلد كالتالي بعد إضافة العروض إليها.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/04_views.png.887ffba2a637d741c0e879d3ef650a3f.png"><img data-fileid="9867" class="ipsImage ipsImage_thumbnailed" alt="04_views.thumb.png.fe03146f5338afe8ef448" src="https://academy.hsoub.com/uploads/monthly_2015_12/04_views.thumb.png.fe03146f5338afe8ef4481f48711f65f.png"></a></p><h3 id="المتحكم-front-وملف-المسارات">المتحكم Front وملف المسارات</h3><p>أنشأنا في الدرس السابق متحكم <code>Front</code> لكنه يكتفي بعرض نص في المتصفح. سنحتاج لتعديله ليحمِّل العروض. عدّلنا قليلا على ملف المسارات <code>routes.php</code> لتعريف مسار لكل تصنيف أو علامة تجارية.</p><h3 id="مجلد-public">مجلد public</h3><p>يحوي الموارد (صور، css، js) التي تحتاجها واجهة الموقع للعمل. يجب وضع هذه الموارد في مجلد <code>public</code> في المشروع.</p><p><strong>ملحوظة:</strong> تأكد بعد نقل الملفات من المرفق إلى أماكنها في المشروع من أن الأذون ما زالت على الحال التي ضبطناها بها في <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%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel">درس الإعداد (لينكس)</a>.</p><p>الآن وبعد التأكد من نقل الملفات من المرفق إلى أماكنها الصحيحة، اذهب إلى الصفحة الرئيسية <code><a rel="external nofollow" href="http://larashop.dev">http://larashop.dev</a></code> وستظهر واجهة الموقع.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/05_larashop.png.5fd71f809d53845f83896db8990f27a5.png"><img data-fileid="9868" class="ipsImage ipsImage_thumbnailed" alt="05_larashop.thumb.png.5eaca0c248d7fe5355" src="https://academy.hsoub.com/uploads/monthly_2015_12/05_larashop.thumb.png.5eaca0c248d7fe535573acd8d8faeba7.png"></a></p><p>نأخذ وقتا لشرح المشروع.</p><h2 id="تحويل-صفحات-html-إلى-قالب-blade">تحويل صفحات HTML إلى قالب Blade</h2><p>قوالب Blade هي، كما رأينا، وسوم HTML مع تعليمات خاصّة بنظام القوالب؛ لذا نحافظ على البنية العاملة لملفات HTML المكوِّنة للموقع مع إجراء تغييرين أساسيين:</p><ul><li>جمع العناصر المشتركة بين مختلف الصفحات ضمن صفحة خاصة.</li><li>إبدال الروابط في صفحة HTML بتعليمات Blade.</li></ul><p>يُترجَم تحويل صفحات HTML إلى قوالب Blade بالخطوات التالية:</p><ul><li>إنشاء مخطّط رئيس تُمدده جميع الصفحات. يحوي المخطط الرئيس العناصر المشتركة بين الصفحات.</li><li>إنشاء صفحة (عرض) لكل مسار من المسارات المعرَّفة في الدرس السابق.</li><li>تحديث المتحكم <code>Front.php</code> لتحميل العروض.</li><li>إضافة الموارد (الصور، ملفات css وjs) إلى مجلد <code>public</code> في تطبيق Laravel.</li></ul><p>يحوي <a class="ipsAttachLink" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=9869">الملف المرفق بهذا المقال</a> عروض Blade الناتجة عن تحويل صفحات HTML إلى قوالب Blade، إضافة إلى ملف المسارات الخاص بمشروع Larahop، المتحكم <code>Front.php</code> والموارد مثل الصور وملفات css (مجلد <code>public</code>).</p><h3 id="المخطط-الرئيس-1">المخطط الرئيس</h3><p>أنشأنا ملفا لمخطط رئيس باسم <code>layout.blade.php</code> على المسار <code>resources/views/layouts</code>. في هذا الملف توجد وسوم HTML مع تعليمات Blade؛ بعضها لم نتطرق له بعد:</p><ul><li>تعليمة <span style="font-family:courier new,courier,monospace;"><code>{{url}}</code></span>:</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{{url('products')}}</pre><p>تنشئ التعليمة <span style="font-family:courier new,courier,monospace;"><code>{{url}}</code></span> رابط URL بالنسبة للمجلد<code>public</code>. في المثال أعلاه فإن الرابط الذي ترجعه التعليمة هو <code><a rel="external nofollow" href="http://larashop.dev/products">http://larashop.dev/products</a></code>؛ وهو الرابط الذي تتعامل معه دالة المسار <code>products/</code>.</p><p>لإنشاء رابط إلى الصفحة الرئيسية فالتعليمة تكون:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{{url('')}}</pre><p>نأخذ أيضا المثال التالي الموجود في المخطط الرئيس:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;li&gt;&lt;a href="{{url('products')}}" {{$page == 'products' ? 'class=active' : ''}}&gt;Products&lt;/a&gt;&lt;/li&gt;</pre><p>نلاحظ استخدام التعليمة <code>url</code> لإعطاء قيمة الرابط ضمن وسم <code>&lt;a&gt;</code>. في نفس السطر توجد تعليمة تشبه تعليمةً مألوفة في PHP وهي</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">{{$page == 'products' ? 'class=active' : ''}}</pre><p>هنا نتحقق من قيمة المتغير <code>page</code> فإذا كانت تساوي <code>products</code> نضيف صنف CSS يسمّى <code>active</code> إلى الوسم.</p><ul><li>تعليمة <span style="font-family:courier new,courier,monospace;"><code>{{asset}}</code></span>:</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{{asset('css/bootstrap.min.css')}}</pre><p>تُرجع الدالة <code>asset</code> مسار مجلد <code>public</code> (أي عنوان الموقع) وتلحق به المعطى الممرَّر إليها. في السطر أعلاه ترجِع الدالةُ القيمةَ <code><a rel="external nofollow" href="http://larashop.dev/css/bootstrap.min.css">http://larashop.dev/css/bootstrap.min.css</a></code>.</p><p>تُستخدم هذه الدالة كثيرا لإضافة ملفات CSS، الصور وملفات JavaScript كما في الأمثلة التالية المأخدوذة من المخطط الرئيس.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;!-- CSS --&gt;
&lt;link href="{{asset('css/bootstrap.min.css')}}" rel="stylesheet"&gt;

&lt;!-- صورة --&gt;
&lt;img src="{{asset('images/home/iframe1.png')}}" alt="" /&gt;

&lt;!-- JavaScript --&gt;
&lt;script src="{{asset('js/jquery.js')}}"&gt;&lt;/script&gt;</pre><p>يمكن من خلال المعطيات الممرَّرة إلى الدالة <code>asset</code> في الأمثلة أعلاه اسنتاجُ أننا نستخدم مجلدًّا فرعيا في <code>public</code> لكل نوع من الموارد (CSS، الصور، JS إضافة للخطوط fonts).</p><p>إن نظرت جيدا في ملف المخطط الرئيس فستميز ثلاثة أجزاء فارقة:</p><ul><li>الجزء الأول ويحوي الوسوم المؤسِّسة للجزء الأعلى المشترك بين مختلف صفحات الموقع، ويحوي ترويسة الموقع وقائمته الرئيسية.</li><li>الجزء الثاني تمثله التعليمة <strong><span style="font-family:courier new,courier,monospace;">('</span></strong><code><strong><span style="font-family:courier new,courier,monospace;">yield('content</span></strong></code><strong style="font-family: monospace; line-height: 22.4px; text-align: right;"><span style="font-family: 'courier new', courier, monospace;">@</span></strong><code> </code>وتلعب دور ماسك مكان Place holder. ستحدّد العروض الأخرى الممدّدة للمخطط الرئيس محتوى ماسك المكان.</li><li>الجزء الثالث وبه التذييل المشترك بين صفحات الموقع.</li></ul><p>إن فهمت جيدا آلية عمل نظام القواعد فستعرف أن الجزأين الأول والثالث لا يتغيران بتغير الصفحة التي يطلبها الزائر. ما يتغير هو فقط الجزء الثاني الذي يعبئه نظام القوالب بمحتوى مختلف حسب الصفحة.</p><h3 id="الصفحات-المشتقة">الصفحات المشتقة</h3><p>ننتقل الآن للعروض الخاصة بكل صفحة. يمدّد كل عرض المخطّط الرئيس. في ما يلي المنحى العام للعروض:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@extends('layouts.layout')

@section('content')

&lt;!--وسوم HTML --&gt;
@include('shared.sidebar')
&lt;!--وسوم HTML --&gt;

@endsection</pre><ul><li>يمدد العرض المخطط الرئيس بتنفيذ التعليمة التالية:</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@extends('layouts.layout')</pre><ul><li>يعرّف مقطعا باسم <code>content</code>:</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@section('content')</pre><p>يُحمَّل محتوى المقطع <code>content</code> في المكان المعرّف بنفس الاسم في المخطّط الرئيس. ينتهي المقطع عند التعليمة <code>endsection@</code>.</p><ul><li>نضمِّن محتوى العرض <code>sidebar</code> الموجود في المجلد <code>resources/views/shared</code>:</li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">@include('shared.sidebar')</pre><p>تستخدم التعليمة <code>include</code> لتحميل محتوى عرض ضمن آخر. عرض <code>sidebar</code> الذي يمثل شريطا جانبيا للموقع موجود في أغلب الصفحات.</p><ul><li>نضيف وسوم HTML المأخوذة من قالب E-Shopper لتكوين الصفحة.</li></ul><h3 id="تحديث-المتحكم-front">تحديث المتحكم Front</h3><p>نحدّث المتحكم <code>Front.php</code> ليحمل العروض بدلا من الاكتفاء بطباعة نص في الصفحة.</p><p>يصبح محتوى المتحكم بعد التحديث على النحو التالي. تحمل كل دالّة العرض الموافق لها حسب <a rel="external nofollow" href="academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-laravel-%D9%85%D8%AD%D8%B3%D9%91%D9%8E%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-r217#%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-%D9%81%D9%8A-laravel">جدول الدرس السابق</a>.</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class Front extends Controller {

    public function index() {
        return view('home', array('page' =&gt; 'home'));
    }

    public function products() {
        return view('products', array('page' =&gt; 'products'));
    }

    public function product_details($id) {
        return view('product_details', array('page' =&gt; 'products'));
    }

    public function product_categories($name) {
        return view('products', array('page' =&gt; 'products'));
    }

    public function product_brands($name, $category = null) {
        return view('products', array('page' =&gt; 'products'));
    }

    public function blog() {
        return view('blog', array('page' =&gt; 'blog'));
    }

    public function blog_post($id) {
        return view('blog_post', array('page' =&gt; 'blog'));
    }

    public function contact_us() {
        return view('contact_us', array('page' =&gt; 'contact_us'));
    }

    public function login() {
        return view('login', array('page' =&gt; 'home'));
    }

    public function logout() {
        return view('login', array('page' =&gt; 'home'));
    }

    public function cart() {
        return view('cart', array('page' =&gt; 'home'));
    }

    public function checkout() {
        return view('checkout', array('page' =&gt; 'home'));
    }

    public function search($query) {
        return view('products', array('page' =&gt; 'products'));
    }

}
</pre><p>جرب تصفح الموقع والتنقل بين صفحاته. إذا اتبعت خطوات الدرس على النحو المشروع فستكون قادرا على التنقل بين صفحات الموقع دون مشاكل. يمكنك أيضا فتح الشفرة المصدرية لصفحات موقع الويب ومقارنتها بما كتبناه في قوالب Blade.</p><h2 id="خاتمة">خاتمة</h2><p>نحصل بنهاية الدرس على تصميم أنيق لصفحات الموقع، استخدمنا لإنشائه Blade الذي يوفر نظاما فعّالا لكتابة قوالب العروض في Laravel مما يتيح تجنب تكرار العناصر المشتركة.</p><p>بانتهاء هذا الدرس نكون قد أنهينا أساس جزء العرض من بنية MVC. الدروس التالية من السلسلة تتناول بقية الأجزاء.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-blade-template">Laravel 5 Blade Template</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">220</guid><pubDate>Fri, 01 Jan 2016 21:27:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x631;&#x648;&#x627;&#x628;&#x637; &#x645;&#x62D;&#x633;&#x646;&#x629; &#x644;&#x645;&#x62D;&#x631;&#x643;&#x627;&#x62A; &#x627;&#x644;&#x628;&#x62D;&#x62B; (SEO) &#x641;&#x64A; &#x625;&#x637;&#x627;&#x631; &#x639;&#x645;&#x644;  Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-5-r217/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel-seo-urls.png.518c1c5b5a653e36c818cdf6bc6acf64.png" /></p>

<p id="مقدمة">تلعب روابط URL دورا هامًّا في العثور على مواقع الويب؛ لذا من المهم تحسينها لمحركات البحث Search Engine Optimization. سنرى في هذا الدرس طريقةً لجعل روابط مشروع larashop محسّنة للمحركات. رأينا في الدرس السابق <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-r216/">كيف تعمل المسارات والمتحكمات</a>، سنبني على هذه المعرفة التي اكتسبناها من أجل الوصول إلى الهدف المحدّد.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a>.</li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li>إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel. <span style="line-height: 22.4px; text-align: right;">(هذا الدرس)</span></li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/laravel-seo-urls.png.25779f0fa05bfdf3f0aee71cd884e716.png"><img data-fileid="10245" class="ipsImage ipsImage_thumbnailed" alt="laravel-seo-urls.thumb.png.70bf53bf53ad1" src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel-seo-urls.thumb.png.70bf53bf53ad1043ebf3b633a0299e37.png"></a></p><p>سنغطّي في هذا الدرس موضوعين أساسيّين:</p><ul><li>العوامل المؤثّرة في التحسين لمحركات البحث.</li><li>كيفية إنشاء روابط محسّنة لمحركات البحث في Laravel.</li></ul><h2 id="العوامل-المؤثرة-في-التحسين-لمحركات-البحث">العوامل المؤثرة في التحسين لمحركات البحث</h2><p>لا نهدف إلى تقديم دليل شامل عن التحسين لمحركات البحث؛ ما نريده هنا هو ذكر بضعة عوامل يجب على المطور أن يكون على اطّلاع عليها. في ما يلي عوامل تؤثر على تقويم محركات البحث مثل Google لصفحات الويب:</p><ul><li><strong>سرعة الموقع</strong>: يحب الجميع أن تظهر صفحة الويب التي يزورها بسرعة، فلا أحد يحب الانتظار إلى ما لا نهاية حتى تظهر الصفحة التي يطلبها. من الأحسن ألا يتعدى زمن تنزيل الصفحة ثانيتين وكل ما قلّ كلّ ما كان الأمر أفضل. يجب عليك بوصفك مطوّرا اختبارُ سرعة تطبيقك وإجراء التحسينات اللازمة إن اقتضت الضرورة.</li><li><strong>إحصاءات الشبكات الاجتماعية</strong>: من الطبيعي، عند قراءتك شيئا مهمّا، مشاركتُه مع متابعيك وأصدقائك على الشبكات الاجتماعية؛ وهذا دليل على الأهمية بالنسبة لمحركات البحث. دورك كمطور هو توفير الأدوات التي تسهل على الزوار مشاركة محتوى الموقع.</li><li><strong>تصميم تجاوبي Responsive</strong>: يمثل مستخدمو الأجهزة المتنقلة جزءًا كبيرًا من مستخدمي خدمات الويب. من هذا المنطلق يجب التأكد من أن موقع الويب يظهر بشكل صحيح على أجهزة الجوّال، الأجهزة اللوحية وأجهزة سطح المكتب؛ إذ أن تجربة المستخدم من العوامل المؤثرة في تقويم محركات البحث.</li><li><strong>الكلمات المفتاحية Keywords</strong>: تصنف محركات البحث مليارات صفحات الويب حسب الكلمات الأساسية الواردة فيها. يتمثل دور المطور في التأكد من توفير آليات مثل الوسوم Tags، أوصاف meta، وعناوين HTML يمكن لكاتب المحتوى استخدامها لتمييز المحتوى المفتاحي.</li><li><strong>روابط URL الخاصة بالموقع</strong>: يجب أن تظهر الكلمات المفتاحية في روابط الموقع.</li></ul><h2 id="كيفية-إنشاء-روابط-محسنة-لمحركات-البحث-في-laravel">كيفية إنشاء روابط محسنة لمحركات البحث في Laravel</h2><p>عرضنا لأساسيات تحسين محركات البحث مع ذكر دور المطور في تنفيذها. سنبدأ الآن في وضع هذه المبادئ موضع التنفيذ. سننشئ مسارات ونربطها بمت حكم. يُظهر الجدول التالي الروابط التي سيتكون منها متجرنا الإلكتروني.</p><table><tbody><tr><td>التسلسل  </td><td>الرابط                                    </td><td>الدالة                             </td><td>الوصف</td></tr><tr><td>1</td><td>/</td><td>index</td><td>الصفحة الرئيسية</td></tr><tr><td>2</td><td>/products</td><td>products</td><td>صفحة المنتجات</td></tr><tr><td>3</td><td>/products/details/{id}</td><td>product_details(id)</td><td>صفحة المنتج ذي المعرّف id</td></tr><tr><td>4</td><td>/products/category</td><td>product_categories</td><td>عرض تصنيفات المنتجات</td></tr><tr><td>5</td><td>/products/brands</td><td>product_brands</td><td>عرض العلامات التجارية للمنتجات</td></tr><tr><td>6</td><td>/blog</td><td>blog</td><td>عرض فهرس بمنشورات المدونة</td></tr><tr><td>7</td><td>/blog/post/{id}</td><td>blog_post($id)</td><td>عرض محتوى التدوينة ذات المعرّف id</td></tr><tr><td>8</td><td>/contact-us</td><td>contact_us</td><td>عرض صفحة الاتصال</td></tr><tr><td>9</td><td>/login</td><td>login</td><td>صفحة تسجيل الدخول</td></tr><tr><td>10</td><td>/logout</td><td>logout</td><td>تسجيل خروج المستخدم</td></tr><tr><td>11</td><td>/cart</td><td>cart</td><td>عرض محتوى سلة المشتريات</td></tr><tr><td>12</td><td>/checkout</td><td>checkout</td><td>صفحة الدفع</td></tr><tr><td>13</td><td>/search/{query}</td><td>search($query)</td><td>عرض نتائج البحث في الموقع</td></tr></tbody></table><h3>تعريف مسارات الروابط</h3><p>سنعرّف مسارا لكل من الروابط الموجودة في الجدول أعلاه، لذا نفتح الملف <code>app/Http/routes.php</code> ونعدّل المحتوى بحيث يصبح التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/','Front@index');
Route::get('/products','Front@products');
Route::get('/products/details/{id}','Front@product_details');
Route::get('/products/category','Front@product_categories');
Route::get('/products/brands','Front@product_brands');
Route::get('/blog','Front@blog');
Route::get('/blog/post/{id}','Front@blog_post');
Route::get('/contact-us','Front@contact_us');
Route::get('/login','Front@login');
Route::get('/logout','Front@logout');
Route::get('/cart','Front@cart');
Route::get('/checkout','Front@checkout');
Route::get('/search/{query}','Front@search');</pre><p>احفظ الملف.</p><p>يستدعي كلٌّ مسار دالة المتحكم <code>Front</code> الموافقة له، حسب الجدول أعلاه. بقي الآن إنشاء المتحكم وكتابة الدوال.</p><p>نستخدم أداة Artisan لإنشاء شفرة نمطية لمتحكم Laravel. تأكد من وجودك في مجلد المشروع <code>larashop</code> ثم نفذ الأمر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:controller Front
</pre><p>يعني ظهور الرسالة التالية أن الأمر نُفذ كما يجب:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Controller created successfully.</pre><p>افتح ملف المتحكم <code>Font</code> الذي أنشأناه للتو (<code>app/Http/Controllers/Front.php</code>) وعدّل عليه بحيث يصبح محتواه التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class Front extends Controller {

  public function index() {
    return 'index page';
  }

  public function products() {
    return 'products page';
  }

  public function product_details($id) {
    return 'product details page';
  }

  public function product_categories() {
    return 'product categories page';
  }

  public function product_brands() {
    return 'product brands page';
  }

  public function blog() {
    return 'blog page';
  }

  public function blog_post($id) {
    return 'blog post page';
  }

  public function contact_us() {
    return 'contact us page';
  }

  public function login() {
    return 'login page';
  }

  public function logout() {
    return 'logout page';
  }

  public function cart() {
    return 'cart page';
  }

  public function checkout() {
    return 'checkout page';
  }

  public function search($query) {
    return "$query search page";
  }
}</pre><p>تعرّف الشفرة أعلاه الدوال التي تجيب على كل طلب يأتي من المسارات التي عرّفناها في ملف <code>routes.php</code>. اكتفينا -لحد الساعة- بجعل كل دالة ترجع اسم المسار الذي تجيب على طلباته.</p><p>انتقل الآن للمتصفح وأدخل الرابط التالي في شريط العناوين:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">http://larashop.dev/search/boots</pre><p>ستحصل على صفحة بالمحتوى التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">boots search page</pre><p>جرب الروابط الأخرى أيضا:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">http://larashop.dev/
http://larashop.dev/products
http://larashop.dev/products/details/7
http://larashop.dev/products/category
http://larashop.dev/products/brands
http://larashop.dev/blog
http://larashop.dev/blog/post/3
http://larashop.dev/contact-us
http://larashop.dev/login
http://larashop.dev/logout
http://larashop.dev/cart
http://larashop.dev/checkout
http://larashop.dev/search/Keyword</pre><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-seo-friendly-urls">Laravel 5 SEO Friendly URLs</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">217</guid><pubDate>Sun, 27 Dec 2015 22:20:00 +0000</pubDate></item><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x628;&#x646;&#x627;&#x621; &#x627;&#x644;&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x641;&#x64A; &#x625;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; Laravel 5</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-hello-world.png.7bc52bfac6f09aef5d11ea3bcf42bc10.png" /></p>

<p id="مقدمة">ثبّتنا في <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/">الدرس السابق</a> من هذه السلسلة إطار Laravel وأعددناه. سنستخدم تلك الإعدادات كقاعدة لبناء تطبيق صغير عليها؛ ونرى العناصر الأساسية لتطبيق يعمل على إطار العمل Laravel.</p><p>هذا الدرس جزء من سلسلة تعلم Laravel والتي تنتهج مبدأ "أفضل وسيلة للتعلم هي الممارسة"، حيث ستكون ممارستنا عبارة عن إنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. يتكون فهرس السلسلة من التالي:</p><ul><li><a style="line-height: 22.4px; text-align: right;" href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/">مدخل إلى Laravel 5</a><span style="line-height: 22.4px; text-align: right;">.</span></li><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li>أساسيات بناء تطبيق باستخدام Laravel. (هذا الدرس)</li><li><span style="line-height: 22.4px; text-align: right;"><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a></span><span style="line-height: 22.4px; text-align: right;">. </span></li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-hello-world.png.1a7285f405e93b39a08963818b7a17d2.png"><img data-fileid="10010" class="ipsImage ipsImage_thumbnailed" alt="laravel5-hello-world.thumb.png.7fe71d4a9" src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-hello-world.thumb.png.7fe71d4a9a48734a22944ed01bbb517e.png"></a></p><p>يشمل الدرس المواضيع التالية:</p><ul><li>مفهوم التوجيه Routing وآلية عمله.</li><li>أداة Artisan التي تعمل على سطر الأوامر.</li><li>استخدام أداة Artisan لتوليد شفرة مصدرية نمطية للمتحكّمات Controllers (وهي المسؤولة عن الإجابة على الطّلبات التي تردها Requests).</li><li>إنشاء نداء لمتحكّم في مسار Route.</li><li>تمرير المتغيّرات من متحكّم إلى عرض View.</li></ul><h2 id="أساسيات-التوجيه-في-laravel">أساسيات التوجيه في Laravel</h2><p>عند وصول طلب إلى تطبيق Laravel تتلقى آلية التوجيه الطلب ثم تختار طريقة التعامل معه.</p><p>سنرى في هذه الفقرة كيفية عمل هذه الآلية. أول ما سنفعله هو إنشاء مسار جديد؛ لذا افتح ملف <code>routes.php</code> الموجود على المسار <span style="font-family:courier new,courier,monospace;"><code>app\Http</code></span> بمحرّر النصوص المفضّل لديك.</p><p><strong>ملحوظة1:</strong> جميع المسارات المذكورة في الدرس هي بالنسبة لمجلد تطبيق Laravel. يعني هذا أن المقصود بالمسار (على افتراض أنك اتبعت خطوات الإعداد في الدرس السابق) <code>app/Http</code> هو المسار <code>C:\laragon\www\larashop\app\Http</code> على وندوز و <code>/var/www/html/larashop/</code> على لينكس.</p><p><strong>ملحوظة2:</strong> انتبه لحالة الأحرف، كبيرة أو صغيرة.</p><p>أضف المحتوى التالي إلى الملف <code>routes.php</code> :</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">Route::get('/hello',function(){
  return 'Hello World!';
});</pre><p>تعرّف الشفرة السابقة مسارًا لتلقي الطلبات من نوع <code>GET</code> (الدّالة <code>get</code> الموجودة في الصنف <code>Route</code>). المعطى الأول للدّالة هو الرابط المعني بالمسار (أي <code>/hello</code>) أما الثاني فهو دالة مجهولة الاسم Anonymous function تعرّف طريقة التعامل مع الطلب. يعني هذا أنه عند تلقي طلب على العنوان <code><a rel="external nofollow" href="http://larashop.dev/hello">http://larashop.dev/hello</a></code> فإن التطبيق ينفذ الدالة مجهولة الاسم والتي تُرجِع العبارة: <code>Hello World!</code>.</p><p>احفظ الملف ثم اذهب إلى المتصفح وأدخل العنوان:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">http://larashop.dev/hello</pre><p>يجب أن تظهر صفحة بيضاء مطبوعة عليها عبارة: <code>Hello World!</code>.</p><p>ربما تكون لاحظت وجود الشفرة التالية في الملف <code>routes.php</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/', function () {
  return view('welcome');
});</pre><p>تتبع هذه الشفرة نفس المبدأ حيث تعرّف مسارا للطلبات الآتية على الرابط <code>/</code> أي رابط الصفحة الرئيسية (<code><a rel="external nofollow" href="http://larashop.dev">http://larashop.dev</a></code>) وتحيلها إلى عرض باسم<code>welcome</code> بدلا من طباعة عبارة مباشرةً (سنرى في ما بعد كيفية ذلك).</p><h2 id="أداة-artisan">أداة Artisan</h2><p>Artisan عبارة عن أداة تُستدعى من سطر الأوامر لأتممة تنفيذ أنشطة اعتيادية على Laravel. يمكن استخدام أداة Artisan لتنفيذ الأنشطة التالية من بين أخرى:</p><ul><li><strong>توليد شفرة نمطية: </strong>إنشاء المتحكّمات، النماذج Models، وغيرها بيُسر.</li><li><strong>تهجير قواعد البيانات Database migrations:</strong> وهو نظام لإدارة الإصدارات الخاصة بقواعد البيانات يجعل من التعامل مع الكائنات في قواعد البيانات (إنشاء جداول أو حذفها مثلا) أسهل عبر وصفها دون الحاجة للتعديل عليها مباشرةً.</li><li><strong>بذر قواعد البيانات Database seeding:</strong> وهو مصطلح يشير إلى إضافة بيانات وهمية للتسجيلات Records في جداول قاعدة البيانات لأغراض الاختبار.</li><li><strong>التوجيه:</strong> وهي الآليّة المسؤولة عن تلقي الطلبات ثم اختيار طريقة التعامل معها (عادةً بإرسالها إلى متحكّم).</li><li><strong>ضبط التطبيق.</strong></li><li><strong>تشغيل الاختبارات الأحاديّة</strong> Unit tests.</li></ul><h3 id="كيف-تستخدم-أداة-artisan">كيف تستخدم أداة Artisan</h3><p>افتح سطر الأوامر ثم انتقل إلى مجلد التطبيق. على افتراض أنك موجود في أصل المستند (<code>C:\laragon\www</code> على وندوز أو <code>/var/www/html/</code> على لينكس):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">cd larashop</pre><p>ثم نفّذ الأمر التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan list</pre><p><strong>ملحوظة:</strong> تأكّد من وجودك في مجلّد التطبيق (أي المجلّد larashp) قبل تنفيذ الأمر <code>artisan</code>.</p><p>تظهر أوامر artisan المتاحة للتنفيذ.</p><p>مثال على النتيجة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Laravel Framework version 5.1.26 (LTS)

Usage:
command [options] [arguments]

Options:
-h, --help            Display this help message
-q, --quiet           Do not output any message
-V, --version         Display this application version
--ansi            Force ANSI output
--no-ansi         Disable ANSI output
-n, --no-interaction  Do not ask any interactive question
--env[=ENV]       The environment the command should run under.
-v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
clear-compiled      Remove the compiled class file
down                Put the application into maintenance mode
env                 Display the current framework environment
help                Displays help for a command
inspire             Display an inspiring quote
list                Lists commands
migrate             Run the database migrations
optimize            Optimize the framework for better performance
serve               Serve the application on the PHP development server
tinker              Interact with your application
up                  Bring the application out of maintenance mode
</pre><h3 id="أمر-artisan-لتوليد-شفرة-متحكم">أمر Artisan لتوليد شفرة متحكم</h3><p>سنستخدم Artisan لتوليد متحكم بسيط يجيب على طلب Http ويحمّل عرضا باسم <code>hello</code>.</p><p>افتح سطر الأوامر ونفذ الأمر التالي (تأكد من وجودك في مجلّد التطبيق قبل تنفيذ الأمر):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:controller Hello</pre><p>استخدمنا أمر <code>make:controller</code> الذي توفره أداة Artisan لتوليد شفرةِ متحكّم ومررنا له اسم المتحكم الذي نريد توليده <code>Hello</code>. يُنشئ الأمر أعلاه ملفا باسم <code>Hello.php</code> على المسار <code>app/Http/Controllers</code>.</p><p>يجب أن تظهر رسالة في سطر الأوامر تفيد بنجاح توليد المتحكم. نفتح ملف <code>Hello.php</code> لرؤية محتواه:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class Hello2 extends Controller
{
  /**
  * Display a listing of the resource.
  *
  * @return \Illuminate\Http\Response
  */
  public function index()
  {
    //
  }

  /**
  * Show the form for creating a new resource.
  *
  * @return \Illuminate\Http\Response
  */
  public function create()
  {
    //
  }

  /**
  * Store a newly created resource in storage.
  *
  * @param  \Illuminate\Http\Request  $request
  * @return \Illuminate\Http\Response
  */
  public function store(Request $request)
  {
    //
  }

  /**
  * Display the specified resource.
  *
  * @param  int  $id
  * @return \Illuminate\Http\Response
  */
  public function show($id)
  { 
    //
  }

  /**
  * Show the form for editing the specified resource.
  *
  * @param  int  $id
  * @return \Illuminate\Http\Response
  */
  public function edit($id)
  {
    // 
  }

  /**
  * Update the specified resource in storage.
  *
  * @param  \Illuminate\Http\Request  $request
  * @param  int  $id
  * @return \Illuminate\Http\Response
  */
  public function update(Request $request, $id)
  {
    //
  }

  /**
  * Remove the specified resource from storage.
  *
  * @param  int  $id
  * @return \Illuminate\Http\Response
  */
  public function destroy($id)
  {
    //
  }
}</pre><ul><li>يعرف الملف فضاء اسم Namespace خاصًّا بالمتحكم: <code>namespace App\Http\Controllers</code>.</li><li>تستورد التعليمات التالية (<code>use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller;</code>) الأصناف Classes المطلوبة لتشغيل المتحكم.</li><li>الصنف <code>Hello</code> هو تمديد للصنف <code>Controller</code> الذي يعرّفه إطار العمل.</li></ul><p>بالنسبة للدوال التي يعرفها المتحكم فاستخدامها يكون كالآتي:</p><ul><li><strong>الدالة <code>index</code> هي الدالة الافتراضية للمتحكم:</strong> تتعامل مع الطلبات الموجهة للرابط الجذر الذي يجيب عنه المتحكم.</li><li><strong>الدالة <code>create</code>:</strong> إنشاء موارد جديدة مثل تسجيلة في جدول قاعدة البيانات.</li><li><strong>الدالة <code>store</code>:</strong> تخزين مورد جديد مُنشَأ بالدالة السابقة.</li><li><strong>الدالة <code>show</code>:</strong> العثور على مورد اعتمادا على المعرِّف <code>ID</code> الممرَّر للدالة.</li><li><strong>الدالة <code>edit</code>:</strong> تتيح إمكانية التعديل على المورد الممرّر للدالة.</li><li><strong>الدالة <code>update</code>:</strong> تحديث مورد مخزّن.</li><li><strong>الدالة <code>destroy</code>:</strong> حذف مورد مخزَّن.</li></ul><p>سنأتي تباعا لتفصيل استخدام هذه الدوال في الوقت المناسب.</p><h2 id="توجيه-طلب-إلى-متحكم">توجيه طلب إلى متحكم</h2><p>في المسار الذي عرفناه سابقا تُطبع العبارة مباشرة من داخل دالة التوجيه، وهذا خلط بين عناصر نموذج MVC، لذا سنضع المسار بين علامات تعليق لتجاهله:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">/*
Route::get('/hello',function(){
  return 'Hello World!';
});
*/</pre><p>ثم نضيف شفرة مصدرية جديدة تنشئ مسارا لنفس الرابط <code>hello/</code> ولكنها بدلا من طبع سلسلة محارف ترسل نداءً إلى المتحكم <code>Hello</code> وبالتحديد دالة <code>index</code>:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('hello', 'Hello@index');</pre><p>نفتح ملف المتحكم لتحرير الدالة <code>index</code> لتأخذ المحتوى التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public function index()
{
  return 'hello world from controller : )';
}</pre><p>احفظ الملف.</p><p>افتح الآن الرابط <code><a rel="external nofollow" href="http://larashop.dev/hello">http://larashop.dev/hello</a></code>، وستجد أن الرسالة التالية تظهر في الصفحة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">hello world from controller :)</pre><p>ما حدث هنا هو أن المسار الخاص بالرابط <code>hello</code> تلقى الطلب من المتصفح ثم أحاله إلى المتحكم <code>Hello</code> الذي طبع سلسلة محارف على الشاشة.</p><h3 id="تحميل-عرض-view-انطلاقا-من-متحكم">تحميل عرض View انطلاقا من متحكم</h3><p>احترام مبادئ MVC يقضي بألا يتداخل عمل المتحكمات والعروض؛ فتنسيق ما يراه الزائر من مسؤولية العروض، ولذا فعلى المتحكم توكيل عرض بهذه المهمة مع إمداده بما يحتاجه من متغيرات. وهو ما سنفعله في الفقرات التالية.</p><p>سيتلخص عملنا في ثلاث نقاط:</p><ul><li>إنشاء مسار لتلقي الطلب على الرابط <code>hello/</code> وإرساله إلى المتحكم المناسب (تم هذا الأمر).</li><li>إنشاء متحكم للإجابة عن الطلب (تم).</li><li>إنشاء عرض لتنسيق ما سيظهر على شاشة الزائر.</li><li>تغيير المتحكم لإرسال نداء إلى العرض وتمرير المتغيرات المناسبة إليه.</li></ul><p>أنشئ ملفا باسم <code>hello.blade.php</code> في المسار <code>resources/views/</code> وأضف إليه المحتوى التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Laravel&lt;/title&gt;
    &lt;link href="//fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css"&gt;
    &lt;style&gt;
      html, body {
       height: 100%;
      }

      body {
       margin: 0;
       padding: 0;
       width: 100%;
       display: table;
       font-weight: 100;
       font-family: 'Lato';
      }

      .container {
         text-align: center;
         display: table-cell;
         vertical-align: middle;
      }

      .content {
         text-align: center;
         display: inline-block;
      }

      .title {
        font-size: 96px;
      }
    &lt;/style&gt;
   &lt;/head&gt;
&lt;body&gt;
   &lt;div class="container"&gt;
      &lt;div class="content"&gt;
        &lt;div class="title"&gt;Hello {{$name}}, welcome to Laraland! : )&lt;/div&gt;
      &lt;/div&gt;
   &lt;/div&gt;
 &lt;/body&gt;
&lt;/html&gt;</pre><p>يحوي الملف كما يظهر شيفرة HTML عادية مع تغييرين أساسيين، هما لاحقة اسم الملف (<code>blade.php</code>) واستخدام المتغير <code>name</code> في الملف. تشير اللاحقة إلى أن العرض يستخدم نظام Blade للقوالب الذي يأتي مضمّنا في Laravel (سنخصص درسا للعروض والقوالب). نكتفي الآن بالقول إن <code>{{$name}}</code> تطبع قيمة المتغير <code>name</code>.</p><p>افتح الملف <code>app/Http/routes.php</code> وأضف الشفرة التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/hello/{name}', 'Hello@show');</pre><p>يعمل هذا السطر على إنشاء مسار للروابط ذات الصيغة <code>/hello/value</code> حيث <code>value</code> قيمة ما، تخزن هذه القيمة في المتغير <code>name</code> ثم تمرّر إلى الدالة <code>show</code> الموجودة في المتحكم <code>Hello</code>.</p><p>نفتح ملف المتحكم <code>Hello</code> ونعدّل الدالة <code>show($id)</code> لتصبح على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public function show($name)
{
  return view('hello',array('name' =&gt; $name));
}</pre><ul><li>نعرف الدالة <code>show</code> التي تقبل المعطى <code>name</code>.</li><li>تحمِّل الدالة عرضا باسم <code>hello.blade.php</code> (يُكتفى بذكر اسم العرض دون اللاحقة <code>blade.php</code>) ثم تمرر له مصفوفة تحوي متغيراتٍ وقيمَها. في حالتنا يوجد متغير واحد باسم <code>name</code> وقيمته هي المعطى الممرَّر للدالة <code>show</code>.</li></ul><p>احفظ التعديلات التي أجريناها في الفقرات السابقة ثم افتح الرابط <code><a rel="external nofollow" href="http://larashop.dev/hello/HsoubAcademy">http://larashop.dev/hello/HsoubAcademy</a></code> في المتصفح.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_Hello_HsoubAcademy.png.0da5ccf8a72e0221fed09e1c9b2fc1a1.png"><img data-fileid="9606" class="ipsImage ipsImage_thumbnailed" alt="01_Hello_HsoubAcademy.thumb.png.41afb2b0" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_Hello_HsoubAcademy.thumb.png.41afb2b024e659ec095865fe5d5cd968.png"></a></p><p>يمكن أن نلاحظ هنا أن <code>HsoubAcademy</code> هي قيمة المتغير <code>name</code> الموجود في تعريف المسار التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Route::get('/hello/{name}', 'Hello@show');</pre><p>إذن:</p><ul><li>طلب الزائر العنوان <code><a rel="external nofollow" href="http://larashop.dev/hello/HsoubAcademy">http://larashop.dev/hello/HsoubAcademy</a></code> في المتصفح.</li><li>وجد التطبيق أن المسار الموافق لهذا الرابط هو المسار <code>/hello/{name{</code> وأعطى القيمة <code>HsoubAcademy</code> للمتغير <code>name</code> ثم وجّه الطلب إلى الدالة <code>show</code> في المتحكم <code>Hello</code>.</li><li>تلقت الدالة <code>show</code> الطلب ثم أرسلته إلى العرض <code>hello</code> مع إنشاء متغير جديد بنفس الاسم المستخدم في العرض وحددت قيمته بالمعطى الذي تلقته من المسار. كان بإمكان الدالة <code>show</code> إجراء عمليات على المعطى قبل تمريره.</li><li>بدأ نظام القوالب العمل ووجد أن العرض <code>hello</code> يحوي متغيرا باسم <code>name</code> وأن قيمة هذا المتغير كما مررها له المتحكم هي <code>HsoubAcademy</code>، فوضعها مكان المتغير وأرسل النتيجة إلى المتصفح.</li></ul><h2 id="خاتمة">خاتمة</h2><p>تعرفنا في هذا الدرس على الآلية الأساسية التي تعمل بها تطبيقات Laravel. من المهم جدّا فهم محتويات هذا الدرس قبل الانتقال إلى الدروس الموالية.</p><p>ترجمة -وبتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-hello-world">Laravel 5 Hello World</a> لصاحبه Rodrick Kazembe.</p>
]]></description><guid isPermaLink="false">216</guid><pubDate>Fri, 25 Dec 2015 21:40:00 +0000</pubDate></item><item><title>&#x62A;&#x62B;&#x628;&#x64A;&#x62A; Laravel 5 &#x648;&#x625;&#x639;&#x62F;&#x627;&#x62F;&#x647; &#x639;&#x644;&#x649; Windows &#x648;Ubuntu</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-install-config.png.d59e7fd9e6d77122915dfdf42d571fa7.png" /></p>

<p>
	سنعرض في هذا الدرس كيفية تثبيت إطار عمل Laravel وطريقة إعداده ثم نكتشف المجلدات المكوِّنة للإطار.
</p>

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

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/" rel="">مدخل إلى Laravel 5</a>.
	</li>
	<li>
		تثبيت Laravel وإعداده على كلّ من Windows وUbuntu. (هذا الدرس)
	</li>
	<li>
		<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</a>.
	</li>
	<li>
		<span style="line-height: 22.4px; text-align: right;"><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-r217/" rel="">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a></span><span style="line-height: 22.4px; text-align: right;">.</span>
	</li>
	<li>
		<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>.
	</li>
	<li>
		<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="">تهجير قواعد البيانات في Laravel</a>.
	</li>
	<li>
		<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 لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/" rel="">إنشاء سلة مشتريات في Laravel</a>.
	</li>
	<li>
		<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/" rel="">الاستيثاق في Laravel</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/" rel="">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> في Laravel</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/" rel="">إنشاء مدوّنة باستخدام Laravel</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/" rel="">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.
	</li>
	<li>
		<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="">الدوّال المساعدة المخصّصة في Laravel</a>.
	</li>
	<li>
		<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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/" rel="">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9706" href="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-install-config.png.87b0a61aa419b1107b8fcb708cf6f24a.png" rel=""><img alt="laravel5-install-config.png" class="ipsImage ipsImage_thumbnailed" data-fileid="9706" src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-install-config.thumb.png.e17553fad631ebd91530115be33fb87f.png"></a>
</p>

<p>
	يتكون جانب التثبيت في هذا الدرس من جزأين، الأول لنظام تشغيل وندوز وسيكون الاعتماد فيه على برنامج Laragon؛ أما الجزء الثاني فهو موجَّه لتوزيعة لينكس Ubuntu 14.04.
</p>

<p>
	وقع الاختيار على Laragon لسهولة العمل عليه إذ يأتي مضمَّنا بإطار عمل Laravel ولا يتطلب سوى إعدادات يسيرة، كما أنه يوفر واجهة أوامر Shell تتيح تنفيذ بعض أوامر Linux.
</p>

<p>
	يغطي الدرس المواضيع التالية:
</p>

<ul>
<li>
		متطلبات تثبيت Laravel
	</li>
	<li>
		تثبيت Laravel باستخدام Composer
	</li>
	<li>
		التحقق من نجاح تثبيت Laravel
	</li>
	<li>
		بنية المجلدات في Laravel
	</li>
	<li>
		إعداد مشروع عمل جديد في Laravel
	</li>
</ul>
<h2 id="متطلبات-تثبيت-laravel">
	متطلبات تثبيت Laravel
</h2>

<p>
	يجب قبل البدء في تثبيت Laravel التأكد من توفر العناصر التالية:
</p>

<ol>
<li>
		خادوم ويب (Apache).
	</li>
	<li>
		الإصدار 5.5.9 من PHP لتثبيت الإصدار  5.2 من Laravel.
	</li>
	<li>
		قاعدة بيانات (MySQL).
	</li>
	<li>
		أداة Composer.
	</li>
	<li>
		تفعيل الوحدات المطلوبة على كلّ من PHP (وهيّ OpenSSL، PDO ،Mbstring وTokenizer) وتعليمة <code>mod_rewrite</code> على Apache .
	</li>
	<li>
		بيئة تطوير IDE (اختياري).
	</li>
</ol>
<p>
	تتناول الفقرات التالية آلية تثبيت هذه العناصر على كل من <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%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D8%B9%D9%84%D9%89-windows" rel="">نظام تشغيل Windows</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/#%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D8%A7%D9%84%D8%AE%D8%A7%D8%B5%D8%A9-%D8%A8%D9%80laravel-%D8%B9%D9%84%D9%89-%D9%84%D9%8A%D9%86%D9%83%D8%B3" rel="">توزيعة Ubuntu 14.04</a>.
</p>

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

<h2 id="تهيئة-بيئة-العمل-على-windows">
	تهيئة بيئة العمل على Windows
</h2>

<p>
	توجد برامج عدة تمكن من الحصول على بيئة تطوير Apache PHP MySQL على Windows ومن أشهرها XAMPP وWAMP. يوجد أيضا خيار آخر وهو برنامج Laragon الذي يتضمن خدمات أخرى إضافة للثلاثة المذكورة، من بينها أداة Composer لإدارة الاعتماديات Dependencies والتي تسهل من تثبيت Laravel وإنشاء مشاريع تعمل عليه كما سنرى لاحقا.
</p>

<h3 id="تثبيت-laragon">
	تثبيت Laragon
</h3>

<p>
	نبدأ بتنزيل برنامج Laragon من <a href="http://laragon.org/" rel="external nofollow">الموقع الرسمي</a> ثم تثبيته. اختر أثناء التثبيت مجلد عمل Laragon:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9302" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_install_laragon.PNG.f8c150902447955ec72fd383fc8b2dc3.PNG" rel=""><img alt="01_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9302" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_install_laragon.thumb.PNG.daddd83d05b458fa4575a597a80bb94e.PNG"></a>
</p>

<p>
	سيقترح عليك المثبِّت تفعيل إنشاء المضيفات الافتراضية Virtual hosts تلقائيا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9303" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_install_laragon.PNG.20406ce552a9975d37c907f34dbcf3a0.PNG" rel=""><img alt="02_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9303" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_install_laragon.thumb.PNG.bc567fd13e58cbd1ebd3fbc33a85e711.PNG"></a>
</p>

<p>
	تمكّن هذه الميزة من إنشاء مضيف افتراضي لكل مجلد يُنشأ ضمن أصل المستند Document root (أي <span style="font-family: monospace; line-height: 22.4px;">\</span><code>C:\laragon\www</code> في حالتنا). يعني هذا أنه عند إنشاء مجلد باسم <code>wordpress</code> على المسار <span style="font-family: monospace; line-height: 22.4px;">\</span><code>C:\laragon</code> فإن مضيفا افتراضيا باسم <code>wordpress.dev</code> يحيل إلى هذا المجلد سيُعد تلقائيا.
</p>

<p>
	نكمل عملية التثبيت:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9304" href="https://academy.hsoub.com/uploads/monthly_2015_12/03_install_laragon.PNG.285f5eaf9971c732a99364396083d077.PNG" rel=""><img alt="03_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9304" src="https://academy.hsoub.com/uploads/monthly_2015_12/03_install_laragon.thumb.PNG.80c5832c6b3573703a883404f5b1f32c.PNG"></a>
</p>

<p>
	بإكمال تثبيت Laragon نكون قد ثبّتنا كلّا من خادوم ويب Apache، قاعدة بيانات MySQL وأداة إدارة الاعتماديات Composer.
</p>

<p>
	نشغل الخدمات بالضغط على زر Start All.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9305" href="https://academy.hsoub.com/uploads/monthly_2015_12/04_install_laragon.PNG.66588ffee8c4f00c8059518852d7c3a8.PNG" rel=""><img alt="04_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9305" src="https://academy.hsoub.com/uploads/monthly_2015_12/04_install_laragon.thumb.PNG.636abac4d9a48f7c295c8a1b69daa0ff.PNG"></a>
</p>

<p>
	تظهر الخدمات المشغَّلة (خادوم ويب Apache وقاعدة بيانات MySQL) في الواجهة الرئيسية للبرنامج.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9306" href="https://academy.hsoub.com/uploads/monthly_2015_12/05_install_laragon.PNG.dcd8ec974db58e1bdbe2d0a8548ffd47.PNG" rel=""><img alt="05_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9306" src="https://academy.hsoub.com/uploads/monthly_2015_12/05_install_laragon.thumb.PNG.cb139c9be3937e4580aa88de544835f2.PNG"></a>
</p>

<p>
	يمكننا الآن إنشاء مشروع Laravel للعمل عليه. سنستخدم سطر الأوامر لهذا الغرض. توجد إمكانية إنشاء مشروع من واجهة البرنامج بالذهاب إلى قائمة:
</p>

<p style="text-align: center;">
	<strong>Menu -&gt; Laravel -&gt; Create project -&gt; Laravel 5</strong>
</p>

<p>
	اضغط على زر Shell لإظهار سطر الأوامر. تبدو واجهة سطر الأوامر على النحو التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9307" href="https://academy.hsoub.com/uploads/monthly_2015_12/06_install_laragon.PNG.01c8a7263c6b08007027d0ac79352ccd.PNG" rel=""><img alt="06_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9307" src="https://academy.hsoub.com/uploads/monthly_2015_12/06_install_laragon.thumb.PNG.b3aef15a7785d3cf35b2f685eb7e680e.PNG"></a>
</p>

<h3 id="إنشاء-مشروع-laravel-باستخدام-أداة-composer">
	إنشاء مشروع Laravel باستخدام أداة Composer
</h3>

<p>
	تُستخدَم أداة Composer لإدارة الاعتماديات في برمجيات PHP. يقوم مبدأ عملها على التصريح بالمكتبات والعناصر اللازمة للمشروع وستتولى الأداة تثبيتها وإدارة تحديثاتها.
</p>

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

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

<p>
	ستحصُل على مخرجات مشابهة لما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9308" href="https://academy.hsoub.com/uploads/monthly_2015_12/07_install_laragon.PNG.3af25ca1f7f18d96d3ea5657c0ec5bc7.PNG" rel=""><img alt="07_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9308" src="https://academy.hsoub.com/uploads/monthly_2015_12/07_install_laragon.thumb.PNG.b583a688ede0a348002996a55b24952a.PNG"></a>
</p>

<p>
	<span style="line-height: 22.4px;">ننتظر اكتمال تثبيت Laravel وإنشاء مشروع larashop:</span>
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9309" href="https://academy.hsoub.com/uploads/monthly_2015_12/08_install_laragon.PNG.ec089d7f91b34de2ca8f2c2c6cf5dbee.PNG" rel=""><img alt="08_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9309" src="https://academy.hsoub.com/uploads/monthly_2015_12/08_install_laragon.thumb.PNG.84f548facfa1d4da734d85e9551b7e9d.PNG"></a>
</p>

<p>
	يثبت الأمر السابق Laravel وينشئ مشروع Laravel باسم larashop في المجلد <span style="font-family: monospace; line-height: 22.4px;">\</span>C:\laragon<code>\www</code> الذي هو أصل المستند.
</p>

<p>
	<strong>ملحوظة:</strong> إذا كان إصدار Composer المضمّن في Laragon قديما فسيظهر لديك تحذير - قد يكون مصحوبا بخطأ في التثبيت - عند تنفيذ أمر <span style="font-family:courier new,courier,monospace;">Composer</span>. للتخلّص من هذا التحذير، وتجاوز الخطأ، حدّث Composer بتنفيذ الأمر أدناه في نافذة سطر الأوامر:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">composer </span><span class="kwd">self</span><span class="pun">-</span><span class="pln">update</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9310" href="https://academy.hsoub.com/uploads/monthly_2015_12/09_install_laragon.PNG.160bfee984cfd9b2fb2504390c00a8dc.PNG" rel=""><img alt="09_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9310" src="https://academy.hsoub.com/uploads/monthly_2015_12/09_install_laragon.thumb.PNG.4437585f380f1471373136c6b61b63b8.PNG"></a>
</p>

<p>
	نفعّل بعد اكتمال تثبيت Laravel وإنشاء مشروع larashop، خدمة <code>PHP Server</code> على المنفذ <code>8000</code> في واجهة Laragon بالذهاب إلى القائمة <strong>Menu</strong> ثم خيار <strong>Preferences</strong> ثم تبويب <strong>Services &amp; Ports</strong> ثم التأشير على الصندوق المناسب كما في الصورة أدناه.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9311" href="https://academy.hsoub.com/uploads/monthly_2015_12/10_install_laragon.PNG.531518ef9f3c3c5f41a5d10a469e4b2e.PNG" rel=""><img alt="10_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9311" src="https://academy.hsoub.com/uploads/monthly_2015_12/10_install_laragon.thumb.PNG.be130e69fb164fdda22b39a76e8c44a6.PNG"></a>
</p>

<p>
	ستلاحظ ظهور سطر جديد في واجهة البرنامج باسم الخدمة التي فعّلناها للتو.
</p>

<h3 id="اختبار-التثبيت">
	اختبار التثبيت
</h3>

<p>
	يمكننا الآن التحقق من أن كل شيء جرى على ما يُرام؛ إما بالذهاب إلى واجهة Laragon ثم اختيار:
</p>

<p style="text-align: center;">
	<strong>Menu -&gt; www -&gt; larashop</strong>
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9312" href="https://academy.hsoub.com/uploads/monthly_2015_12/11_install_laragon.PNG.e9e364767e93411f1e0518d23a1c366d.PNG" rel=""><img alt="11_install_laragon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9312" src="https://academy.hsoub.com/uploads/monthly_2015_12/11_install_laragon.thumb.PNG.ff8e0fd08ffee6c02e92d3090769553a.PNG"></a>
</p>

<p>
	أو إدخال المسار التالي في شريط عنوان المتصفح:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">http</span><span class="pun">:</span><span class="com">//localhost/larashop/public/</span></pre>

<p>
	أو اسم المضيف التالي (إن كنت تركت خيار إنشاء المضيفات الافتراضية تلقائيا أثناء تثبيت Laragon):
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">http</span><span class="pun">:</span><span class="com">//larashop.dev</span></pre>

<p>
	يجب أن تظهر صفحة الويب التالية في المتصفّح دلالة على أن كل شيء وُضع في مكانه الصحيح:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9313" href="https://academy.hsoub.com/uploads/monthly_2015_12/12_Laravel_5.PNG.a2d694f9c072f26213543887069f0ed4.PNG" rel=""><img alt="12_Laravel_5.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9313" src="https://academy.hsoub.com/uploads/monthly_2015_12/12_Laravel_5.thumb.PNG.66037a9692356b4e0fa3403ad224de59.PNG"></a>
</p>

<h2 id="تهيئة-بيئة-العمل-الخاصة-بـlaravel-على-لينكس">
	تهيئة بيئة العمل الخاصة بـLaravel على لينكس
</h2>

<p>
	يتلخّص إعداد بيئة العمل الخاصة بـLaravel على لينكس بالخطوات التاليّة.
</p>

<h3 id="تثبيت-apache-php-وmysql">
	تثبيت Apache، PHP وMySQL
</h3>

<p>
	نبدأ بتثبيت حزم LAMP على أوبنتو. توجد خطوات التثبيت بالتّفصيل في درس <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D9%8F%D8%AB%D8%A8%D9%91%D9%90%D8%AA-%D8%AD%D9%90%D8%B2%D9%85-mysql%D8%8C-apache%D8%8C-linux-lamp-%D9%88php-%D8%B9%D9%84%D9%89-ubuntu-1404-r27/" rel=""> كيف تُثبِّت حِزم MySQL، Apache، Linux :LAMP وPHP على Ubuntu 14.04</a>. نشير هنا إلى أن الإصدر الموجود في المستودعات الرسمية لأوبنتو (5.6.11 أثناء كتابة هذه السطور) يفي بالمتطلبات (5.5.9 فما فوق).
</p>

<h3 id="تثبيت-المتطلبات-الأخرى">
	تثبيت المتطلبات الأخرى
</h3>

<p>
	تثبَّت بعض الوحدات المطلوبة لتشغيل Laravel تلقائيا عند تثبيت PHP، في ما تحتاج أخرى لتثبيتها وتفعيلها. يثبت الأمر التالي هذه الوحدات وأدوات إضافية أخرى:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install </span><span class="pun">-</span><span class="pln">y php5</span><span class="pun">-</span><span class="pln">json openssl php5</span><span class="pun">-</span><span class="pln">mcrypt curl git</span><span class="pun">-</span><span class="pln">core</span></pre>

<p>
	أضفنا حزمتي <code>curl</code> و <code>git-core</code> التين تحتاجهما أداة Composer لتنزيل أرشيف Laravel إلى أمر التثبيت.
</p>

<p>
	نفعّل وحدة <code>mcrypt</code> على PHP:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo php5enmod mcrypt</span></pre>

<p>
	نفعّل كذلك تعليمة <code>mod_rewrite</code> على خادوم ويب Apache:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo a2enmod rewrite</span></pre>

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

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo service apache2 restart</span></pre>

<h3 id="تثبيت-composer-وإعداده">
	تثبيت Composer وإعداده
</h3>

<p>
	نفذ الأمر التالي لتنزيل أداة Composer وتثبيتها:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">curl </span><span class="pun">-</span><span class="pln">sS https</span><span class="pun">:</span><span class="com">//getcomposer.org/installer | php</span></pre>

<p>
	نغيّر مكان الأداة ليصبح تنفيذها ممكنا دون الحاجة لذكر المسار الكامل للملف:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo mv composer</span><span class="pun">.</span><span class="pln">phar </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="kwd">local</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">composer</span></pre>

<p>
	ثم نتأكد من سلامة تثبيت الأداة:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">composer</span></pre>

<p>
	يجب أن تشبه النتيجة ما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9314" href="https://academy.hsoub.com/uploads/monthly_2015_12/13_check_composer.png.df0de41f2fd51fd8aabc2218847c3c71.png" rel=""><img alt="13_check_composer.png" class="ipsImage ipsImage_thumbnailed" data-fileid="9314" src="https://academy.hsoub.com/uploads/monthly_2015_12/13_check_composer.thumb.png.cb5d6aea1282813428ee0f0ac2f9ee28.png"></a>
</p>

<h3 id="تثبيت-laravel">
	تثبيت Laravel
</h3>

<p>
	يمكننا الآن تنفيذ الأمر التالي لتثبيت Laravel باستخدام Composer:
</p>

<pre class="ipsCode" id="ips_uid_3378_9">
sudo composer create-project --prefer-dist laravel/laravel /var/www/html/larashop "5.2.*"</pre>

<p>
	يثبت الأمر Laravel (الإصدار 5.2) وينشئ مشروعا على المسار<span style="font-family:courier new,courier,monospace;"> <code>/var/www/html/larashop/</code></span>.
</p>

<p>
	ننتظر حتى اكتمال التثبيت ثم نجعل الحساب الخاص بخادوم الويب مالكَ مجلد المشروع ونعطي إذن الكتابة لجميع المستخدمين حتى نتمكن من التعديل على ملفات المشروع:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo chown </span><span class="pun">-</span><span class="pln">R www</span><span class="pun">-</span><span class="pln">data</span><span class="pun">:</span><span class="pln">www</span><span class="pun">-</span><span class="pln">data </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">www</span><span class="pun">/</span><span class="pln">html</span><span class="pun">/</span><span class="pln">larashop
sudo chmod </span><span class="pun">-</span><span class="pln">R </span><span class="lit">777</span><span class="pln"> </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">www</span><span class="pun">/</span><span class="pln">html</span><span class="pun">/</span><span class="pln">larashop</span></pre>

<p>
	الخطوة الأخيرة هي نقل ملكية المجلد composer./~ إلى المستخدم الحالي:
</p>

<pre class="html ipsCode prettyprint prettyprinted" data-pbcklang="html" data-pbcktabsize="4">
<span class="pln">sudo chown </span><span class="pun">-</span><span class="pln">R $USER $HOME</span><span class="pun">/.</span><span class="pln">composer</span></pre>

<p>
	عند الذهاب الآن إلى العنوان <code><a href="http://localhost/larashop/public/" rel="external nofollow">http://localhost/larashop/public/</a></code> ستظهر الشاشة التالية دلالة على نجاح عملية التثبيت:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9313" href="https://academy.hsoub.com/uploads/monthly_2015_12/12_Laravel_5.PNG.a2d694f9c072f26213543887069f0ed4.PNG" rel=""><img alt="12_Laravel_5.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="9313" src="https://academy.hsoub.com/uploads/monthly_2015_12/12_Laravel_5.thumb.PNG.66037a9692356b4e0fa3403ad224de59.PNG"></a>
</p>

<h3 id="إنشاء-مضيف-افتراضي">
	إنشاء مضيف افتراضي
</h3>

<p>
	نقدم هنا باختصار طريقة إنشاء مضيف افتراضي Virtual host بحيث يمكننا الوصول إلى واجهة Laravel بكتابة اسم المضيف (اخترنا <span style="font-family:courier new,courier,monospace;">larashop.dev</span> اسما للمضيف) فقط في المتصفح. للمزيد حول المضيفات الافتراضية راجع <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%B6%D8%A8%D8%B7-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%B6%D9%8A%D9%81%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D9%88%D8%A8-apache-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r10/" rel="">هذا الدرس</a>.
</p>

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

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">/etc/</span><span class="pln">apache2</span><span class="pun">/</span><span class="pln">sites</span><span class="pun">-</span><span class="pln">available</span><span class="pun">/</span><span class="pln">larashop</span><span class="pun">.</span><span class="pln">dev</span><span class="pun">.</span><span class="pln">conf</span></pre>

<p>
	أضف المحتوى:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="tag">&lt;VirtualHost</span><span class="pln"> *:80</span><span class="tag">&gt;</span><span class="pln">

  ServerName larashop.dev
  DocumentRoot /var/www/html/larashop/public/

   </span><span class="tag">&lt;Directory</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
      Options FollowSymLinks
      AllowOverride None
   </span><span class="tag">&lt;/Directory&gt;</span><span class="pln">
   </span><span class="tag">&lt;Directory</span><span class="pln"> </span><span class="pun">/</span><span class="atn">var</span><span class="pun">/</span><span class="atn">www</span><span class="pun">/</span><span class="atn">html</span><span class="pun">/</span><span class="atn">larashop</span><span class="tag">/&gt;</span><span class="pln">
      AllowOverride All
   </span><span class="tag">&lt;/Directory&gt;</span><span class="pln">

   ErrorLog ${APACHE_LOG_DIR}/error.log
   LogLevel warn
   CustomLog ${APACHE_LOG_DIR}/access.log combined
</span><span class="tag">&lt;/VirtualHost&gt;</span></pre>

<p>
	أضف اسم المضيف إلى خادوم الويب:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo a2ensite larashop</span><span class="pun">.</span><span class="pln">dev</span></pre>

<p>
	عطل اسم المضيف الافتراضي:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo a2dissite </span><span class="lit">000</span><span class="pun">-</span><span class="kwd">default</span></pre>

<p>
	أعد تحميل إعدادات Apache:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo service apache2 reload</span></pre>

<p>
	افتح ملف المضيفات لتحريره:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="pln">sudo nano </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">hosts</span></pre>

<p>
	أضف السطر التالي مباشرة بعد السطر الأخير من الأسطر التي تبدأ بـ<code>127.X.X.X</code>:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="lit">127.0</span><span class="pun">.</span><span class="lit">1.1</span><span class="pln">       larashop</span><span class="pun">.</span><span class="pln">dev</span></pre>

<p>
	يمكن الآن الوصول إلى واجهة Laravel الأمامية بالذهاب إلى العنوان <span style="font-family:courier new,courier,monospace;"><code>larashop.dev</code></span> في المتصفح.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="9315" href="https://academy.hsoub.com/uploads/monthly_2015_12/14_Laravel_5.png.04bef708139729db86d37bbda06ae427.png" rel=""><img alt="14_Laravel_5.png" class="ipsImage ipsImage_thumbnailed" data-fileid="9315" src="https://academy.hsoub.com/uploads/monthly_2015_12/14_Laravel_5.thumb.png.212f0ffed5c20b1cdf5746079046c26c.png"></a>
</p>

<h2 id="بنية-مجلدات-laravel">
	بنية مجلدات Laravel
</h2>

<p>
	يلخص الجدول التالي أهم مجلدات Laravel التي تجب عليك معرفتها.
</p>

<ul>
<li>
		<strong><code>app</code></strong>: يحتوي على الشفرة المصدرية للتطبيق.
	</li>
	<li>
		<strong><code>app/console</code></strong>: توجد أوامر <code>artisan</code> هنا.
	</li>
	<li>
		<strong><code>app/events</code></strong>: يحتوي على أصناف Classes الأحداث Events.
	</li>
	<li>
		<strong><code>app/exceptions</code></strong>: الأصناف التي تتعامل مع الاستثناءات Exceptions.
	</li>
	<li>
		<strong><code>app/Http</code></strong>: تحتوي على الأصناف الخاصة بالمتحكِّمات Controllers، المُرشِحات Filters والطلبات Requests.
	</li>
	<li>
		<strong><code>app/jobs</code></strong>: يحتوي هذا المجلد على الأشغال Jobs التي تمكن إضافتها إلى قائمة الانتظار Queue.
	</li>
	<li>
		<strong><code>app/listeners</code></strong>: يحتوي على الأصناف التي تعالج الأحداث.
	</li>
	<li>
		<strong><code>bootstrap</code></strong>: توجد هنا الأصناف التي يحتاجها إطار عمل Bootstrap.
	</li>
	<li>
		<strong><code>config</code></strong>: يحتوي هذا المجلد على ملفات الإعداد.
	</li>
	<li>
		<strong><code>database</code></strong>: توجد في المجلد أصناف التهجير Migration والبذر Seed الخاصتين بقاعدة البيانات. كما يحتوي المجلد على قاعدة بيانات SQLite.
	</li>
	<li>
		<strong><code>public</code></strong>: يحتوي على متحكمات الواجهة الأمامية للتطبيق وموارد أخرى مثل الصور، ملفات CSS، Javascript وغيرها.
	</li>
	<li>
		<strong><code>resources</code></strong>: يحوي العروض Views وملفات التوطين Localization.
	</li>
	<li>
		<strong><code>storage</code></strong>: يحتوي على قوالب <code>blade</code> المجمّعة Compiled، حقول الجلسات Sessions وأمور أخرى.
	</li>
	<li>
		<strong><code>tests</code></strong>: توجد به الاختبارات الأحادية Unit tests.
	</li>
	<li>
		<strong><code>vendor</code></strong>: يحتوي على اعتماديات Composer.
	</li>
</ul>
<h2 id="إعداد-مشروع-laravel-جديد">
	إعداد مشروع Laravel جديد
</h2>

<h3 id="إعداد-التطبيق">
	إعداد التطبيق
</h3>

<p>
	توجد معلومات إعداد التطبيق في الملف<span style="font-family:courier new,courier,monospace;"> <code>config/app.php/</code></span> سنرى في هذه الفقرة:
</p>

<ul>
<li>
		<strong>ضبط وضع التنقيح Debugging mode</strong>: يُستخدم وضع التنقيح لتحديد مقدار المعلومات الواجب إظهارها عند حدوث أخطاء في التطبيق.
	</li>
	<li>
		<strong>ضبط المنطقة الزمنية Time zone</strong>: يستخدم PHP هذا الإعداد في دوالّ الوقت والتاريخ.
	</li>
	<li>
		<strong>مفتاح التطبيق Application key</strong>: تُستخدَم هذه القيمة في التعميّة Encryption.
	</li>
</ul>
<h3 id="وضع-التنقيح">
	وضع التنقيح
</h3>

<p>
	افتح الملف <span style="font-family:courier new,courier,monospace;"><code>config/app.php/</code></span> واعثر على السطر التالي:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'debug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'APP_DEBUG'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span></pre>

<p>
	عدّل السطر بحيث يصبح على النحو التالي:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'debug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'APP_DEBUG'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span></pre>

<p>
	تفعلّ التعليمة<span style="font-family:courier new,courier,monospace;"> (<code>'debug' =&gt; env('APP_DEBUG', true</code></span> وضع التنقيح بإعطاء القيمة <span style="font-family:courier new,courier,monospace;"><code>true</code></span> للمتغيّر <span style="font-family:courier new,courier,monospace;"><code>APP_DEBUG</code></span>؛ وهو ما يعني أن Laravel سيظهر معلومات مفصَّلة عند حدوث أخطاء. تفيد المعلومات المفصَّلة كثيرًا في البحث عن مشاكل في التطبيق ومن ثم تصحيحها.
</p>

<h3 id="المنطقة-الزمنية">
	المنطقة الزمنية
</h3>

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

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'timezone'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'UTC'</span><span class="pun">,</span></pre>

<p>
	تعطي هذه التعليمة القيمة الافتراضيّة <span style="font-family:courier new,courier,monospace;"><code>UTC</code></span> للمتغيّر <span style="font-family:courier new,courier,monospace;"><code>timezone</code></span>. تشير <code>UTC</code> إلى التوقيت العالميّ الموّحّد؛ يمكنك إبدالها بالقيمة الموافقة لمنطقتك الزمنيّة المفضّلة.
</p>

<h3 id="مفتاح-التطبيق">
	مفتاح التطبيق
</h3>

<p>
	اعثر على السطر التالي:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'key'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'APP_KEY'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SomeRandomString'</span><span class="pun">),</span></pre>

<p>
	وضع سلسلة محارف String من اختيارك مكان <span style="font-family:courier new,courier,monospace;"><code>SomeRandomString</code></span>:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'key'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'APP_KEY'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'ines5@dinemwa8aw3bambuyabakoiwe'</span><span class="pun">),</span></pre>

<p>
	اخترنا سلسلة محارف عشوائية من 32 محرفا Characters لاستخدامها في التعميّة.
</p>

<h3 id="إعدادات-أخرى">
	إعدادات أخرى
</h3>

<p>
	توجد الكثير من الإعدادات الأخرى التي يمكن اكتشافها بتصفح الملف <span style="font-family:courier new,courier,monospace;"><code>config/app.php</code></span>.
</p>

<h3 id="إعداد-الاستيثاق">
	إعداد الاستيثاق
</h3>

<p>
	توجد إعدادات الاستيثاق ضمن الملف <code>config/auth.php/</code>. سنترك الإعدادات بقيمها الافتراضية، يمكنك تغييرها بما يوافق احتياجاتك.
</p>

<h3 id="إعداد-قاعدة-البيانات">
	إعداد قاعدة البيانات
</h3>

<p>
	يوجد إعداد قاعدة البيانات ضمن الملف <code>config/database.php/</code>؛ تُستخدم قاعدة بيانات MySQL افتراضيّا. يمكن تعديل الملف لاستخدام نظام إدارة قواعد بيانات مختلف. سنستخدم قاعدة بيانات MySQL في هذا الدليل ونغيّر بضعة إعدادات:
</p>

<ul>
<li>
		اسم قاعدة البيانات database،
	</li>
	<li>
		اسم المستخدم username،
	</li>
	<li>
		كلمة سر المستخدم.
	</li>
</ul>
<p>
	ابحث عن الأسطر التالية في ملف إعداد قاعدة البيانات:
</p>

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'mysql'</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">'mysql'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'host'</span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'DB_HOST'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'localhost'</span><span class="pun">),</span><span class="pln">
  </span><span class="str">'database'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'DB_DATABASE'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'forge'</span><span class="pun">),</span><span class="pln">
  </span><span class="str">'username'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'DB_USERNAME'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'forge'</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"> env</span><span class="pun">(</span><span class="str">'DB_PASSWORD'</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">),</span><span class="pln">
  </span><span class="str">'charset'</span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'utf8'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'collation'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'utf8_unicode_ci'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'prefix'</span><span class="pln">    </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'strict'</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="pun">],</span></pre>

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

<pre class="ipsCode prettyprint prettyprinted" data-pbcklang="" data-pbcktabsize="">
<span class="str">'mysql'</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">'mysql'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'host'</span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'DB_HOST'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'localhost'</span><span class="pun">),</span><span class="pln">
  </span><span class="str">'database'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'DB_DATABASE'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'larashop'</span><span class="pun">),</span><span class="pln">
  </span><span class="str">'username'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'DB_USERNAME'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'root'</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"> env</span><span class="pun">(</span><span class="str">'DB_PASSWORD'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'melody'</span><span class="pun">),</span><span class="pln">
  </span><span class="str">'charset'</span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'utf8'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'collation'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'utf8_unicode_ci'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'prefix'</span><span class="pln">    </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'strict'</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="pun">],</span></pre>

<ul>
<li>
		تعد التعليمة <span style="font-family:courier new,courier,monospace;">(</span><code><span style="font-family:courier new,courier,monospace;">'database' =&gt; env('DB_DATABASE', 'larashop'</span>,</code> التطبيق لاستخدام قاعدة بيانات <code>larashop</code>. يمكنك الذهاب إلى MySQL وإنشاء قاعدة بيانات خاوية باسم <code>larashop</code> في MySQL.
	</li>
	<li>
		تضبط التعليمة <span style="font-family:courier new,courier,monospace;">(</span><code><span style="font-family:courier new,courier,monospace;">'username' =&gt; env('DB_USERNAME', 'root'</span>,</code> التطبيق لاستخدام الحساب <code>root</code> للوصول إلى قاعدة البيانات. يجب أن تستخدم حساب مستخدم صالحا في MySQL.
	</li>
	<li>
		التعليمة المواليّة <span style="font-family:courier new,courier,monospace;">(</span><code><span style="font-family:courier new,courier,monospace;">'password' =&gt; env('DB_PASSWORD', 'melody'</span>,</code> تحدد كلمة سر الحساب المستخدم في التعليمة السابقة.
	</li>
</ul>
<h2 id="خاتمة">
	خاتمة
</h2>

<p>
	رأينا في هذا الدرس كيفية تثبيت Laravel ثم بنية المجلدات الموجودة في إطار العمل وإعدادات أساسية لمشروع Laravel. الخطوة التاليّة ستكون إنشاء أول تطبيق في Laravel.
</p>

<p>
	ترجمة -وبتصرّف- لمقال <a href="http://www.tutorials.kode-blog.com/laravel-install-and-configure" rel="external nofollow">Laravel 5 Installation and Configuration</a> لصاحبه Rodrick Kazembe.
</p>

<p><a href="https://academy.hsoub.com/uploads/monthly_2015_12/python1.png.7bb61ae492d4a1c61d2abc77942538c7.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="9031" src="https://academy.hsoub.com/uploads/monthly_2015_12/python1.thumb.png.92c1f5fe8a4d11c53f4056790ceb9938.png" class="ipsImage ipsImage_thumbnailed" alt="python1.png"></a></p>
<p><a href="https://academy.hsoub.com/uploads/monthly_2015_12/python2.png.40cc90a6b83881456a78ddc4b03968c4.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="9032" src="https://academy.hsoub.com/uploads/monthly_2015_12/python2.thumb.png.7516f8e9372f3b33c99ddac442e732c3.png" class="ipsImage ipsImage_thumbnailed" alt="python2.png"></a></p>
<p><a href="https://academy.hsoub.com/uploads/monthly_2015_12/python3.png.ec16a4cbc53c1aed75c9f0aab8fe1557.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="9033" src="https://academy.hsoub.com/uploads/monthly_2015_12/python3.thumb.png.41784b114bb06e6bc6414e7ed37b4465.png" class="ipsImage ipsImage_thumbnailed" alt="python3.png"></a></p>
<p><a href="https://academy.hsoub.com/uploads/monthly_2015_12/python4.png.38bfb8f275506544455ab39f45b93e97.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="9034" src="https://academy.hsoub.com/uploads/monthly_2015_12/python4.thumb.png.c835d13eea0be1d59af631334e409a05.png" class="ipsImage ipsImage_thumbnailed" alt="python4.png"></a></p>]]></description><guid isPermaLink="false">212</guid><pubDate>Sat, 19 Dec 2015 18:12:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-introduction.png.637b4370a6548843a9dc89f22b8e6672.png" /></p>

<div id="wmd-preview-section-19"><p>كثُر الحديث في السنوات الأخيرة عن إطار العمل Laravel وانتشر بين مطوّري PHP حتى إنه أصبح إطار العمل الأكثر استخداما بينهم، سواء للمشاريع الشخصية أو المهنية، حسب استبيان أجراه موقع <a rel="external nofollow" href="http://www.sitepoint.com/best-php-framework-2015-sitepoint-survey-results/">SitePoint</a> الشهير. كما أنه من أكثر المشاريع التي يُساهَم فيها على GitHub.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-introduction.png.22ecc161c01abc4e34f9f458acd6f2ce.png"><img data-fileid="9674" class="ipsImage ipsImage_thumbnailed" alt="laravel5-introduction.thumb.png.dd518e68" src="https://academy.hsoub.com/uploads/monthly_2015_12/laravel5-introduction.thumb.png.dd518e68ab7ae0212d66802b75d11a2f.png"></a></p><p>سنتعرّف في سلسلة الدّروس هذه، التي يمثّل هذا المقال مقدّمة لها، على إطار العمل Laravel وأهم المبادئ التي يعمل وفقا لها.</p></div><div id="wmd-preview-section-20"><h2 id="لماذا-laravel">لماذا Laravel؟</h2><p>توجد الكثير من الأسباب التي تدعو لاختيار Laravel منها ماهو نفعيّ (انتشار أكبر يعني فرصًا أكثر للحصول على فرص توظيف) ومنها ماهو تقني بحت. قبل الإجابة على السؤال "لماذا Laravel؟" قد يكون من المفيد محاولة الإجابة عن "لماذا إطار عمل؟" بمعنى آخر ألا يمكنك كمطوّر PHP البدء من الصفر وبناء تطبيقك حسب الحاجة؟</p><p>يمكننا القول -باختصار- أن أطر العمل تجعلك تتخلص من ضرورة الاعتناء بتفاصيل كثيرة، ترفع كثيرا من إنتاجيتك وتقيك من أخطاء التعامل المباشر مع بيئة لغة البرمجة من قبيل أخطاء التعامل مع استعلامات قواعد البيانات التي قد تنتج عنها هجمات الحقن بتعليمات SQL المعروفة بــSQL injection.</p><p>تفرِض أطر العمل الجيدة على مستخدميها الفصل بين أجزاء التطبيق وتنفيذ بنية Architecture مجرَّبة تؤدي في النهاية إلى الرفع من تصميم التطبيق وجعل الشفرة المصدرية أيسر في القراءة وأسهل في الصيانة والاختبار.</p><p>نجمل في ما يلي أهم الأسباب التي تجعل من اختيار Laravel مناسبًا:</p><ul><li>سهولة الاستخدام.</li><li>الفصل بين عناصر التطبيق مما يسهل عمل فريق من المطوّرين وتقاسم المهامّ بينهم.</li><li>دعم التطوير السريع للتطبيقات Rapid Application Developing, RAD: توفر أداة Artisan وسيلة سريعة لإنشاء شفرة مصدرية نمطية للتعديل المباشر عليها. كما أنها تُستخدَم لمهامّ أخرى مثل تشغيل الاختبارات الأحادية Unit tests، تهجير قواعد البيانات، وغيرها.</li><li>التضمين الافتراضي لوظائف شائعة الاستخدام في تطبيقات الويب، مثل الاستيثاق Authentication، التوجيه Routing، إدارة قواعد البيانات، إرسال البريد الإلكتروني.</li><li>متحكمات <span style="font-family:courier new,courier,monospace;">RESTful</span>: يعني هذا أنه يمكن الاستفادة من أفعال <span style="font-family:courier new,courier,monospace;">HTTP</span> القياسية مثل <span style="font-family:courier new,courier,monospace;">PUT</span>، <span style="font-family:courier new,courier,monospace;">POST</span>، <span style="font-family:courier new,courier,monospace;">GET</span> <span style="font-family:courier new,courier,monospace;">وDELETE</span>.</li><li>إدارة الاعتماديات Dependencies باستخدام <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%A7-%D9%87%D9%88-composer-%D9%88%D9%84%D9%85%D8%A7%D8%B0%D8%A7-%D9%8A%D8%AC%D8%A8-%D8%B9%D9%84%D9%89-%D9%83%D9%8F%D9%84-%D9%85%D9%8F%D8%B7%D9%88%D8%B1-php-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-r10/">Composer</a> وهو ما يعني إمكانية استخدام الحزم والمكتبات الموجودة على الموقع www.packagist.com بيُسر ضمن مشاريعك.</li><li>استخدام إطار العمل Eloquent وهو إطار للربط بين الكائنات في قاعدة البيانات والتصنيفات في شفرة التطبيق Object Relational Mapper.</li></ul></div><div id="wmd-preview-section-21"><h3 id="بنية-mvc">بنية MVC</h3><p>تتبع المشاريع في إطار العمل Laravel بنية Model-View-Controller (تُختصر بـMVC) التي تقسّم التطبيق إلى ثلاثة أجزاء متصلة في ما بينها، وتُفرّق بين التمثيل الداخلي للمعلومة والطرق التي تُقدَّم بها المعلومة إلى المستخدم.</p><p>يقع جزء النموذج Model في قلب بنية التطبيق؛ تُعالَج في هذا القسم البيانات وتُنفَّذ عليها القواعد (في تطبيق محاسبة تنتمي الفواتير والعمليات عليها إلى هذا الجزء). يتولى الجزء الثاني في البنية وهو العرض View مهمة تقديم البيانات إلى المستخدم. يمكن أن تأخذ نفس البيانات أشكالا عدّة للعرض (مخطّط بياني، جدول، … إلخ). أما الجزء الثالث (المتحكِّم Controller) فيأخذ مُدخلات ويحوّلها إلى أوامر يرسلها للنموذج والعرض.</p><p>يمكن شرح الأمر على النحو التالي:</p><ul><li>يرسل المتحكّم أمرا إلى النموذج لتعديل حالته (تحرير فاتورة). كما يمكنه إرسال أمر إلى العرض بتغيير طريقة تقديم البيانات (الانتقال بين أسطر الفاتورة).</li><li>يخزّن النموذج البيانات المعثور عليها وفقا لأوامر المتحكّم وتلك المعروضة في العرض.</li><li>يولّد العرض مخرجات للمستخدم حسب البيانات الخزّنة في النموذج.</li></ul><p>يجمل المخطط البياني التالي آلية العمل.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/01_MVC-Laravel5.png.d1ca3d472f9c5f0153ca199a09b02a4e.png"><img data-fileid="9672" class="ipsImage ipsImage_thumbnailed" alt="01_MVC-Laravel5.thumb.png.3438297e027267" src="https://academy.hsoub.com/uploads/monthly_2015_12/01_MVC-Laravel5.thumb.png.3438297e027267c50edcec9ea02c9b8f.png"></a></p></div><div id="wmd-preview-section-22"><h2 id="سلسلة-دروس-laravel-إنشاء-تطبيق-ويب-للتسوق">سلسلة دروس Laravel: إنشاء تطبيق ويب للتسوق</h2><p>ننطلق في سلسلة الدروس هذه من مبدأ أن أفضل وسيلة للتعلم هي الممارسة، لذا سنبدأ خطوة خطوة بإنشاء تطبيق ويب للتسوق مع ميزة سلة المشتريات. تعطي الصورة التالية فكرة عن شكل الموقع الذي نريد إنشاءه.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_12/02_e-shopper.png.09d4f5f7083e5df094b5e315eaf29213.png"><img data-fileid="9673" class="ipsImage ipsImage_thumbnailed" alt="02_e-shopper.thumb.png.4da5546e82ac82dc4" src="https://academy.hsoub.com/uploads/monthly_2015_12/02_e-shopper.thumb.png.4da5546e82ac82dc41d6bc5b7e77e778.png"></a></p><p>تشمل السلسلة المواضيع التالية:</p><ul><li><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/">تثبيت Laravel وإعداده على كلّ من Windows وUbuntu</a>.</li><li><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/">أساسيات بناء تطبيق باستخدام Laravel</a>.</li><li><span style="line-height: 22.4px; text-align: right;"><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D9%85%D8%AD%D8%B3%D9%86%D8%A9-%D9%84%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-seo-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-laravel-r217/">إنشاء روابط محسنة لمحركات البحث (SEO) في إطار عمل Laravel</a></span><span style="line-height: 22.4px; text-align: right;">.</span></li><li><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/">نظام Blade للقوالب</a>.</li><li><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/">تهجير قواعد البيانات في Laravel</a>.</li><li><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/">استخدام Eloquent ORM لإدخال البيانات في قاعدة البيانات، تحديثها أو حذفها</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B3%D9%84%D8%A9-%D9%85%D8%B4%D8%AA%D8%B1%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r228/">إنشاء سلة مشتريات في Laravel</a>.</li><li><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/">الاستيثاق في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-%D9%81%D9%8A-laravel-5-r232/">إنشاء واجهة لبرمجة التطبيقات <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> في Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/">إنشاء مدوّنة باستخدام Laravel</a>.</li><li><a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-angularjs-%D9%84%D8%A8%D9%86%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-laravel-5-r234/">استخدام AngularJS واجهةً أمامية Front end لتطبيق Laravel</a>.</li><li><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/">الدوّال المساعدة المخصّصة في Laravel</a>.</li><li><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-faker-%D9%84%D8%AA%D9%88%D9%84%D9%8A%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D9%81%D9%8A-laravel-5-r237/">استخدام مكتبة Faker في تطبيق Laravel لتوليد بيانات وهمية قصدَ الاختبار</a>.</li></ul><p>ترجمة -بتصرّف- لمقال <a rel="external nofollow" href="http://www.tutorials.kode-blog.com/laravel-5-tutorial">Laravel 5 Tutorial</a> لصاحبه Rodrick Kazembe.</p></div>
]]></description><guid isPermaLink="false">218</guid><pubDate>Fri, 18 Dec 2015 21:44:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x646;&#x645;&#x637; &#x627;&#x644;&#x645;&#x633;&#x62A;&#x648;&#x62F;&#x639; &#x641;&#x64A; Laravel 5</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%86%D9%85%D8%B7-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%88%D8%AF%D8%B9-%D9%81%D9%8A-laravel-5-r195/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_10/laravel-repository-pattern.png.c2b32f2915ae01cd7f86c44b6d08360c.png" /></p>

<p dir="rtl">يكثر الحديث هذه الأيام عن أنماط تصميم البرمجيات، ومن الأسئلة الأكثر شيوعًا "كيف يمكنني استخدام النمط الفلاني مع التقنية (التكنولوجيا) الفلانيّة؟". أما في حالة Laravel ونمط المستودع (Repository pattern)، فكثيرًا أرى أسئلة من قبيل "كيف يمكنني أن أستخدم نمط المستودع في Laravel 4؟" أو في هذه الأيام "مع Laravel 5؟". من المهم أن تتذكر أنّ <strong>أنماط التصميم لا تعتمد على تقنيّة محدّدة، أو إطار برمجي محدد، أو لغة برمجة محددة.</strong></p><p dir="rtl" style="text-align: center;"><strong><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/laravel-repository-pattern.png.dfb79aaa3e91cf632ffbbe0f686b9787.png"><img data-fileid="6010" class="ipsImage ipsImage_thumbnailed" alt="laravel-repository-pattern.thumb.png.37e" src="https://academy.hsoub.com/uploads/monthly_2015_10/laravel-repository-pattern.thumb.png.37eba43cb81f556039695bd0eda7ce47.png"></a></strong></p><p dir="rtl">إذا كنت قد فهمت نمط المستودع بالفعل، فلا يهم الإطار البرمجي أو اللغة البرمجة التي ستستخدمها. المهم أن تفهم المبدأ الذي يقف خلف نمط المستودع، ومن ثم يمكنك استخدامه في أيّ تقنية تريد. آخذين هذا بعين الاعتبار، لنبدأ بتعريف نمط المستودع:</p><blockquote class="ipsQuote" data-cite="اقتباس" data-ipsquote=""><p>يتوسط المستودعُ كلًّا من طبقة النطاق وطبقة ربط البيانات، بحيث يمثل مجموعة كيانات نطاق في الذاكرة. تُنشئ كائنات العميل مواصفات الاستعلام تعبيريًّا، وتُرسلها إلى المستودع لتلبية المتطلبات. يمكن أن تُضاف كائنات أو تُحذف من المستودع، كما يمكن ذلك لو كانت في مجموعة بسيطة من الكائنات، سيستمر كود الربط المكانيّ المحاطً بالمستودع بالقيام بالعمليات المناسبة خلف الكواليس.</p></blockquote><p dir="rtl">يفصل نمط المستودع منطق الوصول إلى البيانات (data access logic) ويربطه مكانيًّا بكيانات الأعمال (business entities) في المنطق الأعمال (business logic). ويتم التواصل بين منطق الوصول إلى البيانات ومنطق الأعمال باستخدام واجهات (interfaces).</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/repository_pattern.png.3ffaf4744f23cc0ca965643fba68a14d.png"><img data-fileid="6007" class="ipsImage ipsImage_thumbnailed" alt="repository_pattern.thumb.png.50c63014965" src="https://academy.hsoub.com/uploads/monthly_2015_10/repository_pattern.thumb.png.50c63014965ea38712d9d0ebb63fa6f6.png"></a></p><p dir="rtl">ولتبسيط ذلك، فإن <strong>نمط المستودع</strong> نوع من الحاويات يخزّن فيه منطق الوصول إلى البيانات، بحيث يخفي منطق الوصول إلى البيانات عن منطق الأعمال. وبعبارة أخرى، نسمح لمنطق الأعمال أن يصل إلى كائن البيانات دون معرفة هيكلية الوصول إلى البيانات التي تتم خلف الكواليس.</p><p dir="rtl">ولفصل الوصول إلى البيانات عن منطق الأعمال فوائد عدّة، منها:</p><ul dir="rtl"><li>مركزية منطق الوصول إلى البيانات تجعل النصوص البرمجية أسهل في الصيانة.</li><li>يمكن فحص منطق الأعمال ومنطق الوصول إلى البيانات كلًّا على حدة.</li><li>تقليل تكرار الأكواد البرمجية.</li><li>فرصة أقل للوقوع في أخطاء برمجية.</li></ul><h2 dir="rtl">الأمر كلّه يتعلق بالواجهات</h2><p dir="rtl">كلّ ما في نمط المستودع ذو علاقة بالواجهات. تعمل الواجهة كاتفاقية تحدّد ما على فئة concrete تنفيذه.لنفكّر قليلًا. إذا كان لدينا كائني بيانات، الممثل والفلم، فما هي مجموعة العمليات الشائعة التي يمكن تطبيقها على هذين العنصرين؟ سنرغب في غالب الأحيان بالقيام بالعمليات التالية:</p><ol dir="rtl"><li>الحصول على جميع السجلات.</li><li>الحصول على مجموعة السجلّات مرقّمة.</li><li>إنشاء سجلّ جديد.</li><li>الحصول على سجل باستخدام المفتاح الرئيسيّ.</li><li>الحصول على سجل باستخدام خواص (attributes) أخرى.</li><li>تحديث سجلّ.</li><li>حذف سجلّ.</li></ol><p dir="rtl">هل يمكنك الآن أن ترى كميّة النصوص البرمجيّة المكررة التي ستكون لدينا إذا قمنا بذلك مع كلّ كائن بيانات؟ حسنًا، هذه ليست مشكلة كبيرة بالنسبة للمشاريع الصغيرة، ولكنها أمر سيّء بالنسبة للمشاريع الكبيرة.</p><p dir="rtl">الآن، وبعد أن عرّفنا العمليات الشائعة، يمكننا إنشاء واجهة:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">interface RepositoryInterface {
  public function all($columns = array('*'));
  public function paginate($perPage = 15, $columns = array('*'));
  public function create(array $data);
  public function update(array $data, $id);
  public function delete($id);
  public function find($id, $columns = array('*'));
  public function findBy($field, $value, $columns = array('*'));
}</pre><h2 dir="rtl">هيكليّة الدليل Directory Structure</h2><p dir="rtl">قبل أن نتابع إنشاء فئة مستودع concrete التي ستنفّذ هذه الواجهة، لنفكّر قليلًا كيف نريد أن ننظّم النصوص البرمجيّة لدينا. عادة، عندما أنشئ شيئًا ما، أفضّل أن أفكر بطريقة تقسيمه إلى مكوّنات، حيث أرغب بأن أكون قادرًا على إعادة استخدام ذاك النصّ البرمجيّ لمشاريع أخرى. إن هيكليّة الدليل البسيطة التي أتبعها لمكونات المستودع تبدو كما يلي:</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/repository_directory_structure.png.c795132458a8ba5b8309d71c90acc842.png"><img data-fileid="6008" class="ipsImage ipsImage_thumbnailed" alt="repository_directory_structure.thumb.png" src="https://academy.hsoub.com/uploads/monthly_2015_10/repository_directory_structure.thumb.png.e81f9be4c161dadb7c12dfe786586d5d.png"></a></p><p dir="rtl">ولكنها يمكن أن تكون مختلفة، كأن يكون للمكونات خيارات ضبط مثلًا.</p><p dir="rtl">لدي في داخل الدليل <span style="font-family:courier new,courier,monospace;">src</span> ثلاثة أدلّة أخرى، هي: <span style="font-family:courier new,courier,monospace;">Contracts</span> و<span style="font-family:courier new,courier,monospace;">Eloquent</span> و<span style="font-family:courier new,courier,monospace;">exceptions</span>. كما ترى، أسماء المجلدات مناسبة للغاية لما نريد وضعه فيها. ففي <span style="font-family:courier new,courier,monospace;">Contracts</span> نضع الواجهات، أو الاتفاقيات – كما سميناها أعلاه - . ويحوي مجلد <span style="font-family:courier new,courier,monospace;">Eloquent</span> مستودعي <span style="font-family:courier new,courier,monospace;">abstract</span> و <span style="font-family:courier new,courier,monospace;">concrete</span> تنفّذ الاتفاقات. ونضع في المجيد <span style="font-family:courier new,courier,monospace;">Exceptions</span> فئات الاستثناءات.</p><p dir="rtl">وحيث أننا ننشئ حزم، فعلينا أن ننشئ ملف <span style="font-family:courier new,courier,monospace;">composer.json</span>، حيث نجد فيه ربطًا مكانيًّا لنطاق الأسماء (<span style="font-family:courier new,courier,monospace;">namespaces</span>) لأدلّة معيّنة، واعتماديات حزم، وبيانات وصفيّة أخرى للحزم. فيما يلي محتوى <span style="font-family:courier new,courier,monospace;">composer.json</span> لهذه الحزمة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">{
  "name": "bosnadev/repositories",
  "description": "Laravel Repositories",
  "keywords": [
    "laravel",
    "repository",
    "repositories",
    "eloquent",
    "database"
  ],
  "licence": "MIT",
  "authors": [
    {
      "name": "Mirza Pasic",
      "email": "mirza.pasic@edu.fit.ba"
    }
  ],
  "require": {
    "php": "&gt;=5.4.0",
    "illuminate/support": "5.*",
    "illuminate/database": "5.*"
  },
  "autoload": {
    "psr-4": {
      "Bosnadev\\Repositories\\": "src/"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Bosnadev\\Tests\\Repositories\\": "tests/"
    }
  },
  "extra": {
    "branch-alias": {
      "dev-master": "0.x-dev"
    }
  },
  "minimum-stability": "dev",
  "prefer-stable": true
}
</pre><p dir="rtl">كما ترى، فقد ربطنا <span style="font-family:courier new,courier,monospace;">Bosnadev\Repository</span> إلى الدليل <span style="font-family:courier new,courier,monospace;">src</span>. وهناك شيء آخر علينا أخذه بعين الاعتبار قبل البدء بتنفيذ <span style="font-family:courier new,courier,monospace;">RepositoryInterface</span>، فحيث أنها موجودة في المجلد <span style="font-family:courier new,courier,monospace;">Contracts</span>، فعلينا أن نحدّد نطاق الاسم لها:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Contracts;

interface RepositoryInterface {...}</pre><p dir="rtl">نحن الآن مستعدون لبدء تنفيذ المحتوى.</p><h2 dir="rtl">تنفيذ المستودع</h2><p dir="rtl">على كل مستودع فرعيّ في <span style="font-family:courier new,courier,monospace;">concrete</span> أن يزيد من مستودع <span style="font-family:courier new,courier,monospace;">abstract</span> لدينا، مما يعني تنفيذ اتفاقية <span style="font-family:courier new,courier,monospace;">RepositoryInterface</span>. أما الآن، فكيف تنفّذ هذه الاتفاقيّة؟ ألقِ نظرة على method الأولى. ما الذي يمكنك قوله عنها بمجرد النظر إليها؟</p><p dir="rtl">تُسمى method الأولى في اتفاقيتنا بالاسم <span style="font-family:courier new,courier,monospace;">()all</span> للتوضيح. مهمتها هي جلب كلّ السجلات لهيئة <span style="font-family:courier new,courier,monospace;">concrete</span>. تستقبل معامِلاً واحدًا، وهو <span style="font-family:courier new,courier,monospace;">columns$ </span>الذي يجب أن يكون مصفوفة (array). يُستخدّم هذا المعامِل – كما هو واضح من اسمه – لتحديد الأعمدة التي ترغب بجلبها من مصدر البيانات، ومبدئيًّا نقوم بجلبها كلّها.</p><p dir="rtl">لهئيات محدّدة، يمكن أن تبدو كالتالي:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Contracts;

interface RepositoryInterface {...}</pre><p dir="rtl">لكننا نريدها أن تكون عامّة أكثر لكي نتمكن من استخدامها متى أردنا:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">public function all($columns = array('*')) {
  return $this-&gt;model-&gt;get($columns);
}</pre><p dir="rtl"><a rel="external nofollow" name="crayon-55f3d10a49613449828811"></a> في هذه الحالة <span style="font-family:courier new,courier,monospace;">this-&gt;model$ </span>هي نسخة من <span style="font-family:courier new,courier,monospace;">Bosnadev\Models\Actor</span>، ولهذا، فعلينا إنشاء نسخة جديدة للنموذج الموجود في مكان ما في المستودع. هنا أحد الحلول التي يمكنك استخدامها لتنفيذ هذا الأمر:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Eloquent;
 
use Bosnadev\Repositories\Contracts\RepositoryInterface;
use Bosnadev\Repositories\Exceptions\RepositoryException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Container\Container as App;
 
/**
 * Class Repository
 * @package Bosnadev\Repositories\Eloquent
 */
abstract class Repository implements RepositoryInterface {
 
    /**
     * @var App
     */
    private $app;
 
    /**
     * @var
     */
    protected $model;
 
    /**
     * @param App $app
     * @throws \Bosnadev\Repositories\Exceptions\RepositoryException
     */
    public function __construct(App $app) {
        $this-&gt;app = $app;
        $this-&gt;makeModel();
    }
 
    /**
     * Specify Model class name
     * 
     * @return mixed
     */
    abstract function model();
 
    /**
     * @return Model
     * @throws RepositoryException
     */
    public function makeModel() {
        $model = $this-&gt;app-&gt;make($this-&gt;model());
 
        if (!$model instanceof Model)
            throw new RepositoryException("Class {$this-&gt;model()} must be an instance of Illuminate\\Database\\Eloquent\\Model");
 
        return $this-&gt;model = $model;
    }
}
</pre><p dir="rtl">وحيث أننا عرفنا الفئة كـ <span style="font-family:courier new,courier,monospace;">abstract</span>، فهذا يعني أن علينا زيادتها باستخدام فئة متفرّعة عن <span style="font-family:courier new,courier,monospace;">concrete</span>. فعند تعريف <span style="font-family:courier new,courier,monospace;">method</span> المسمّى <span style="font-family:courier new,courier,monospace;">()model</span> كـ <span style="font-family:courier new,courier,monospace;">abstract</span>، فإننا نجبر المستخدم على تنفيذ هذه الطريقة (<span style="font-family:courier new,courier,monospace;">method</span>) في فئة متفرعة عن <span style="font-family:courier new,courier,monospace;">concrete</span>. فمثلًا:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace App\Repositories;
use Bosnadev\Repositories\Contracts\RepositoryInterface;
use Bosnadev\Repositories\Eloquent\Repository;

class ActorRepository extends Repository {

  /**
  * Specify Model class name
  *
  * @return mixed
  */
  function model(){
    return 'Bosnadev\Models\Actor';
  }
}</pre><p dir="rtl">يمكننا الآن أن ننفذ بقية طرق (<span style="font-family:courier new,courier,monospace;">methods</span>) الاتفاقات:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Eloquent;
 
use Bosnadev\Repositories\Contracts\RepositoryInterface;
use Bosnadev\Repositories\Exceptions\RepositoryException;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Container\Container as App;
 
/**
 * Class Repository
 * @package Bosnadev\Repositories\Eloquent
 */
abstract class Repository implements RepositoryInterface {
 
    /**
     * @var App
     */
    private $app;
 
    /**
     * @var
     */
    protected $model;
 
    /**
     * @param App $app
     * @throws \Bosnadev\Repositories\Exceptions\RepositoryException
     */
    public function __construct(App $app) {
        $this-&gt;app = $app;
        $this-&gt;makeModel();
    }
 
    /**
     * Specify Model class name
     *
     * @return mixed
     */
    abstract function model();
 
    /**
     * @param array $columns
     * @return mixed
     */
    public function all($columns = array('*')) {
        return $this-&gt;model-&gt;get($columns);
    }
 
    /**
     * @param int $perPage
     * @param array $columns
     * @return mixed
     */
    public function paginate($perPage = 15, $columns = array('*')) {
        return $this-&gt;model-&gt;paginate($perPage, $columns);
    }
 
    /**
     * @param array $data
     * @return mixed
     */
    public function create(array $data) {
        return $this-&gt;model-&gt;create($data);
    }
 
    /**
     * @param array $data
     * @param $id
     * @param string $attribute
     * @return mixed
     */
    public function update(array $data, $id, $attribute="id") {
        return $this-&gt;model-&gt;where($attribute, '=', $id)-&gt;update($data);
    }
 
    /**
     * @param $id
     * @return mixed
     */
    public function delete($id) {
        return $this-&gt;model-&gt;destroy($id);
    }
 
    /**
     * @param $id
     * @param array $columns
     * @return mixed
     */
    public function find($id, $columns = array('*')) {
        return $this-&gt;model-&gt;find($id, $columns);
    }
 
    /**
     * @param $attribute
     * @param $value
     * @param array $columns
     * @return mixed
     */
    public function findBy($attribute, $value, $columns = array('*')) {
        return $this-&gt;model-&gt;where($attribute, '=', $value)-&gt;first($columns);
    }
 
    /**
     * @return \Illuminate\Database\Eloquent\Builder
     * @throws RepositoryException
     */
    public function makeModel() {
        $model = $this-&gt;app-&gt;make($this-&gt;model());
 
        if (!$model instanceof Model)
            throw new RepositoryException("Class {$this-&gt;model()} must be an instance of Illuminate\\Database\\Eloquent\\Model");
 
        return $this-&gt;model = $model-&gt;newQuery();
    }
}
</pre><p dir="rtl">الأمر سهل للغاية، صح؟ الشيء الوحيد المتبقي الآن هو حقن <span style="font-family:courier new,courier,monospace;">ActorRepository</span> في <span style="font-family:courier new,courier,monospace;">ActorsController</span>، أو الجزء المتعلق بالأعمال (business logic) من تطبيقنا.</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace App\Http\Controllers;
use App\Repositories\ActorRepository as Actor;

class ActorsController extends Controller {

  /**
   * @var Actor
   */
  private $actor;

  public function __construct(Actor $actor) {
    $this-&gt;actor = $actor;
  }
  
  public function index() {
    return \Response::json($this-&gt;actor-&gt;all());
  }
}</pre><h2 dir="rtl">استعلامات المعايير Criteria Queries</h2><p dir="rtl">كما يمكنك أن تتخيل، فهذه الأعمال البسيطة كافية فقط لاستعلامات البسيطة. أما بالنسبة للتطبيقات الكبيرة، فستحتاج بالتأكيد لعمل بعض الاستعلامات الخاصّة لاستدعاء مجموعة بيانات محدّدة أكثر باستخدام معايير محدّدة.</p><p dir="rtl">للقيام بذلك، نبدأ بتحديد ما على معايير الفروع (child ، أو العميل client) القيام به. وبعبارة أخرى، سننشئ فئة abstract non-instantiable باستخدام method واحدة فقط :</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Criteria;

use Bosnadev\Repositories\Contracts\RepositoryInterface as Repository;
use Bosnadev\Repositories\Contracts\RepositoryInterface;

abstract class Criteria {
  /**
   * @param $model 
   * @param RepositoryInterface $repository 
   * @return mixed 
   */
   public abstract function apply($model, Repository $repository);
}</pre><p dir="rtl">ستحوي هذه الطريقة (method) استعلام معايير يتم تطبيقه في فئة <span style="font-family:courier new,courier,monospace;">Repository</span> ضمن هيئة <span style="font-family:courier new,courier,monospace;">concrete</span>. علينا أيضًا أن نزيد على فئة <span style="font-family:courier new,courier,monospace;">Repository</span> قليلًا لتغطية استعلامات المعايير. لكن قبل ذلك، هيّا ننشئ اتفاقية أخرى لفئة <span style="font-family:courier new,courier,monospace;">Repository</span>.</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Contracts;
use Bosnadev\Repositories\Criteria\Criteria;

/**
 * Interface CriteriaInterface
 * @package Bosnadev\Repositories\Contracts 
 */

interface CriteriaInterface {
  /*** @param bool $status 
   * @return $this 
   */
   public function skipCriteria($status = true);
  /*** @return mixed*/public function getCriteria();
  /*** @param Criteria $criteria* @return $this*/public function getByCriteria(Criteria $criteria);
  /*** @param Criteria $criteria* @return $this*/public function pushCriteria(Criteria $criteria);
  /*** @return $this*/public function applyCriteria();
}</pre><p dir="rtl">يمكننا أن نزيد فاعلية فئة <span style="font-family:courier new,courier,monospace;">Repository</span> بتنفيذ اتفاقية <span style="font-family:courier new,courier,monospace;">CriteriaInterface</span>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace Bosnadev\Repositories\Eloquent;
 
use Bosnadev\Repositories\Contracts\CriteriaInterface;
use Bosnadev\Repositories\Criteria\Criteria;
use Bosnadev\Repositories\Contracts\RepositoryInterface;
use Bosnadev\Repositories\Exceptions\RepositoryException;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Container\Container as App;
 
/**
 * Class Repository
 * @package Bosnadev\Repositories\Eloquent
 */
abstract class Repository implements RepositoryInterface, CriteriaInterface {
 
    /**
     * @var App
     */
    private $app;
 
    /**
     * @var
     */
    protected $model;
 
    /**
     * @var Collection
     */
    protected $criteria;
 
    /**
     * @var bool
     */
    protected $skipCriteria = false;
 
    /**
     * @param App $app
     * @param Collection $collection
     * @throws \Bosnadev\Repositories\Exceptions\RepositoryException
     */
    public function __construct(App $app, Collection $collection) {
        $this-&gt;app = $app;
        $this-&gt;criteria = $collection;
        $this-&gt;resetScope();
        $this-&gt;makeModel();
    }
 
    /**
     * Specify Model class name
     *
     * @return mixed
     */
    public abstract function model();
 
    /**
     * @param array $columns
     * @return mixed
     */
    public function all($columns = array('*')) {
        $this-&gt;applyCriteria();
        return $this-&gt;model-&gt;get($columns);
    }
 
    /**
     * @param int $perPage
     * @param array $columns
     * @return mixed
     */
    public function paginate($perPage = 1, $columns = array('*')) {
        $this-&gt;applyCriteria();
        return $this-&gt;model-&gt;paginate($perPage, $columns);
    }
 
    /**
     * @param array $data
     * @return mixed
     */
    public function create(array $data) {
        return $this-&gt;model-&gt;create($data);
    }
 
    /**
     * @param array $data
     * @param $id
     * @param string $attribute
     * @return mixed
     */
    public function update(array $data, $id, $attribute="id") {
        return $this-&gt;model-&gt;where($attribute, '=', $id)-&gt;update($data);
    }
 
    /**
     * @param $id
     * @return mixed
     */
    public function delete($id) {
        return $this-&gt;model-&gt;destroy($id);
    }
 
    /**
     * @param $id
     * @param array $columns
     * @return mixed
     */
    public function find($id, $columns = array('*')) {
        $this-&gt;applyCriteria();
        return $this-&gt;model-&gt;find($id, $columns);
    }
 
    /**
     * @param $attribute
     * @param $value
     * @param array $columns
     * @return mixed
     */
    public function findBy($attribute, $value, $columns = array('*')) {
        $this-&gt;applyCriteria();
        return $this-&gt;model-&gt;where($attribute, '=', $value)-&gt;first($columns);
    }
 
    /**
     * @return \Illuminate\Database\Eloquent\Builder
     * @throws RepositoryException
     */
    public function makeModel() {
        $model = $this-&gt;app-&gt;make($this-&gt;model());
 
        if (!$model instanceof Model)
            throw new RepositoryException("Class {$this-&gt;model()} must be an instance of Illuminate\\Database\\Eloquent\\Model");
 
        return $this-&gt;model = $model-&gt;newQuery();
    }
 
    /**
     * @return $this
     */
    public function resetScope() {
        $this-&gt;skipCriteria(false);
        return $this;
    }
 
    /**
     * @param bool $status
     * @return $this
     */
    public function skipCriteria($status = true){
        $this-&gt;skipCriteria = $status;
        return $this;
    }
 
    /**
     * @return mixed
     */
    public function getCriteria() {
        return $this-&gt;criteria;
    }
 
    /**
     * @param Criteria $criteria
     * @return $this
     */
    public function getByCriteria(Criteria $criteria) {
        $this-&gt;model = $criteria-&gt;apply($this-&gt;model, $this);
        return $this;
    }
 
    /**
     * @param Criteria $criteria
     * @return $this
     */
    public function pushCriteria(Criteria $criteria) {
        $this-&gt;criteria-&gt;push($criteria);
        return $this;
    }
 
    /**
     * @return $this
     */
    public function  applyCriteria() {
        if($this-&gt;skipCriteria === true)
            return $this;
 
        foreach($this-&gt;getCriteria() as $criteria) {
            if($criteria instanceof Criteria)
                $this-&gt;model = $criteria-&gt;apply($this-&gt;model, $this);
        }
 
        return $this;
    }
}
</pre><p dir="rtl">إنشاء معايير جديدة، حيث يمكنك الآن أن ترتب مستودعاتك بسهولة أكبر. لست بحاجة لأن تكون مستودعاتك مكونة من آلاف الأسطر.</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/criteria_structure.png.16f9a092792d414f6664ef6bd93a037f.png"><img data-fileid="6009" class="ipsImage ipsImage_thumbnailed" alt="criteria_structure.thumb.png.6a2a0a4aa99" src="https://academy.hsoub.com/uploads/monthly_2015_10/criteria_structure.thumb.png.6a2a0a4aa99a827c0e18cc027be221e2.png"></a></p><p dir="rtl">يمكن أن تبدو فئة المعايير لديك كالآتي:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace App\Repositories\Criteria\Films;
use Bosnadev\Repositories\Contracts\CriteriaInterface;
use Bosnadev\Repositories\Contracts\RepositoryInterface as Repository;
use Bosnadev\Repositories\Contracts\RepositoryInterface;

class LengthOverTwoHours implements CriteriaInterface {
  /**
   * @param $model 
   * @param RepositoryInterface $repository 
   * @return mixed 
   */

  public function apply($model, Repository $repository){
    $query = $model-&gt;where('length', '&gt;', 120);
    return $query;
  }
}</pre><h2 dir="rtl">استخدام للمعايير (Criteria) في المتحكّمات (Controllers)</h2><p dir="rtl">الآن وقد صارت لدينا معايير بسيطة، لنرَ كيف يمكننا استخدامها. هناك طريقتان يمكنك اتباعهما لتطبيق المعايير على مستودع. الأولى باستخدام طريقة <span style="font-family:courier new,courier,monospace;">()pushCriteria</span>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace App\Http\Controllers;
use App\Repositories\Criteria\Films\LengthOverTwoHours;
use App\Repositories\FilmRepository as Film;

class FilmsController extends Controller {
  /*** @var Film*/private $film;

  public function __construct(Film $film) {
    $this-&gt;film = $film;
  }

  public function index() {
    $this-&gt;film-&gt;pushCriteria(new LengthOverTwoHours());
    return \Response::json($this-&gt;film-&gt;all());
  }
}</pre><p dir="rtl">هذه الطريقة مفيدة إذا كنت ترغب بتطبيق أكثر من معيار في نفس الوقت، حيث يمكنك رصّها معًا كما تشاء، ولكن إذا رغب بتطبيق معيار واحد فقط، فيمكنك استخدام طريقة <span style="font-family:courier new,courier,monospace;">()getByCriteria</span>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php namespace App\Http\Controllers;
use App\Repositories\Criteria\Films\LengthOverTwoHours;
use App\Repositories\FilmRepository as Film;

class FilmsController extends Controller {
  /**
   * @var Film 
   */
  private $film;
  
  public function __construct(Film $film) {
    $this-&gt;film = $film;
  }
  
  public function index() {
    $criteria = new LengthOverTwoHours();
    return \Response::json($this-&gt;film-&gt;getByCriteria($criteria)-&gt;all());
  }
}</pre><h2 dir="rtl">تثبيت الحزم</h2><p dir="rtl">يمكنك تثبيت هذه الحزمة بإضافة الاعتمادية التالية إلى قسم <span style="font-family:courier new,courier,monospace;">require</span> في ملف <span style="font-family:courier new,courier,monospace;">composer</span> لديك:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">"bosnadev/repositories": "0.*"</pre><p dir="rtl">وتنفيذ <span style="font-family:courier new,courier,monospace;">composer update</span> بعد ذلك،</p><h2 dir="rtl">الخلاصة</h2><p dir="rtl">لاستخدام المستودعات في تطبيقك العديد من الفوائد. من أشياء بسيطة كتقليل تكرار الأكواد ومنعك من ارتكاب أخطاء برمجيّة وجعل تطبيقك أسهل في التكبير والتوسعة، والاختبار، والصيانة.</p><p dir="rtl">من وجهة نظر هندسيّة، فقد تمكنت من عزل الاهتمامات. المتحكّم (controller) لديك ليس بحاجة لأن يعرف كيف وأين تخزَّن البيانات. بسيط وجميل. تجريديّ (Abstract).</p><p dir="rtl">ترجمة وبتصرف للمقال: <a rel="external nofollow" href="https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/">Using Repository Pattern in Laravel 5</a>.</p>
]]></description><guid isPermaLink="false">195</guid><pubDate>Sat, 17 Oct 2015 18:44:10 +0000</pubDate></item><item><title>&#x639;&#x644;&#x627;&#x642;&#x627;&#x62A; Eloquent &#x648;&#x627;&#x644;&#x62A;&#x62D;&#x645;&#x64A;&#x644; &#x627;&#x644;&#x62D;&#x62B;&#x64A;&#x62B; &#x641;&#x64A; Laravel 5</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_10/eager_loading-laravel.png.f4f887157dbc84bcc34da334bb583b53.png" /></p>

<p dir="rtl">قبل أن نذهب إلى الموضوع الرئيسيّ للمقال، سأعطيك لمحة قصيرة عن مشاكل التصميم التي قد تواجهها. لقد اشتكى لي أحد زبائني بأن بعض الصفحات تفتح ببطء شديد. وعندما أقول ببطء شديد، فإنني أعني ذلك! فقررت أن أصحح تلك الصفحة (بعمل debugging)، وما رأيته قد صدمني. لقد أظهر لي قسم الاستعلامات (queries) أن تلك الصفحة كانت تنفَّذ بعد القيام بكم هائل من الاستعلامات تعدّى 16500 استعلامًا!!</p><p dir="rtl" style="text-align: center;"><a href="https://academy.hsoub.com/uploads/monthly_2015_10/eager_loading-laravel.png.bcce7e121e26b467b8ebf67a2c8da498.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="6011" src="https://academy.hsoub.com/uploads/monthly_2015_10/eager_loading-laravel.thumb.png.9c6712d82fc6517efac07bd803c11a46.png" class="ipsImage ipsImage_thumbnailed" alt="eager_loading-laravel.thumb.png.9c6712d8"></a></p><p dir="rtl" style="text-align: center;"> </p><p dir="rtl">لقد وجدت أن جزءًا من النصّ البرمجي هو سبب تلك المشكلة. لقد كانت هناك ثلاث حلقات <span style="font-family:courier new,courier,monospace;">foreach</span> تستعلم عن خاصيّة والخواص الفرعيّة التابعة لها. لقد كانت تعمل جيدًا إلى أن صار في قاعدة البيانات 5500 عنصرًا. وفيما يلي ما كان يحدث:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">$main_object = MainObject::all();

foreach($main_object as $object) {
    echo $object-&gt;some_property;
    foreach($object-&gt;related_object as $related) {
        echo $related-&gt;some_property;
        echo $related-&gt;another_property;
    }
    foreach($object-&gt;another_related as $another) {
        echo $another-&gt;some_property;
        echo $another-&gt;another_property;
    }
}</pre><p dir="rtl">إذا كان الاستعلام <span style="font-family:courier new,courier,monospace;">;()main_object = MainObject::all$</span> يعيد 5500 نتيجة، فستعيد حلقة<span style="font-family:courier new,courier,monospace;"> foreach</span> الأولى ذلك القدر أيضًا، وكذلك بالنسبة للثانية والثالثة. باستخدام ORM، كثيرًا ما يقع المبرمجون في فخّ كتابة استعلامات قواعد بيانات غير كفؤة، وتجعلها ORM أكثر صعوبة في الاكتشاف. تُسمّى هذه المشكلة بمشكلة N+1 (بالإنجليزيّة N+1 problem). وأظن المطور السابق لم يكن على علم بذلك. ولتفادي هذه المشكلة، نستخدم التحميل الحثيث (eager loading).</p><h2 dir="rtl">ما هو التحميل الحثيث؟</h2><p dir="rtl">لتبسيط الأمر، التحميل الحثيث طريقة تُعنى بعمل كل شيء عند الطلب. وهذه الطريقة أيضًا على العكس تمامًا من التحميل الكسول (lazy loading) عندما ننفذ المهام عند الحاجة. يساعدنا التحميل الحثيث على تجنب مشكلات الأداء، كما رأيت في مثالي أعلاه. ستفهم الأمر أكثر من خلال مثال، لذا لنتخيل الوضع التالي:</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/pic1.png.64bfba5f2ac04ea23bc3f199dd6c85d9.png"><img data-fileid="5946" class="ipsImage ipsImage_thumbnailed" alt="pic1.thumb.png.94a71591d05847307fc3f46c8" src="https://academy.hsoub.com/uploads/monthly_2015_10/pic1.thumb.png.94a71591d05847307fc3f46c8b927776.png"></a></p><p dir="rtl">لدينا نموذج علاقة هيئة محسّنة (بالإنجليزيّة: Enhanced Entity Relationship، واختصارًا EER)، بثلاث هيئات، كلّ منها مرتبطة بالأخرى. يمكنك أن تقرأ EER كما يلي: يمكن لكل عضو أن يملك العديد من المحلات، ولكن المحل الواحد ملك لعضو واحد فقط. يمكن للمحل الواحد أن يحوي العديد من المنتجات، ولكن المنتج الواحد لا يكون إلّا في محل واحد.</p><p dir="rtl">الخطوة التالية هي إنشاء نماذج Eloquent لهذه الهيئات:</p><p dir="rtl"><strong>العضو:</strong></p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php 
    namespace App;
    use Illuminate\Database\Eloquent\Model;

    class Member extends Model {
        protected $fillable = ['username', 'email', 'first_name', 'last_name'];
        public function stores() {
            return $this-&gt;hasMany('App\\Store');
        }
    }</pre><p dir="rtl"><strong>المحلّ:</strong></p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php 
    namespace App;
    use Illuminate\Database\Eloquent\Model;

    class Store extends Model {
        protected $fillable = ['name', 'slug', 'site', 'member_id'];
        public function member() {
            return $this-&gt;belongsTo('App\\Member');
        }
        public function products() {
            return $this-&gt;hasMany('App\\Product');
        }
}</pre><p dir="rtl"><strong>المُنتَج:</strong></p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php 
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    
    class Product extends Model {
        protected $fillable = ['name', 'short_desc', 'long_desc', 'price', 'store_id', 'member_id'];
        public function store() {
            return $this-&gt;belongsTo('App\\Store');
        }
    }</pre><p dir="rtl">تخيّل أنك تبني تطبيقًا يسمح لمستخدميك أن يُنشئوا محالّهم التجاريّة الخاصّة. يمكن للمستخدمين –كما هو الحال بالنسبة للمحال الأخرى كلها طبعًا– أن يُنشئوا منتَجات عديدة. وأيضًا، يمكننا أن ننشئ صفحة واحدة تعرض كل المحلات وأفضل المنتجات لكل محلّ. شيء من قبيل هذا:</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/pic2.png.d060dcf16fb0d7fbf9d06b3f899046ab.png"><img data-fileid="5947" class="ipsImage ipsImage_thumbnailed" alt="pic2.thumb.png.3d52edd250bc1561a13fdcd2d" src="https://academy.hsoub.com/uploads/monthly_2015_10/pic2.thumb.png.3d52edd250bc1561a13fdcd2df4b52ff.png"></a></p><p dir="rtl">يمكن أن ينتهي بك المطاف إلى الحصول على شيء كهذا في المتحكّم لديك:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php 
    namespace App\Http\Controllers;
    use App\Repositories\StoreRepository;

    class StoresController extends Controller {
        protected $stores;
        function __construct(StoreRepository $stores) {
            $this-&gt;stores = $stores;
        }
        public function index() {
            $stores = $this-&gt;stores-&gt;all();
            return \View::make('stores.index')-&gt;with('stores', $stores);
        }
    }</pre><p dir="rtl">وفي العرض الذي ستقدم فيه تلك البيانات:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">@foreach($stores as $store)
    &lt;h1&gt;{{ $store-&gt;name }}&lt;/h1&gt;
    &lt;span&gt;Owner: {{ $store-&gt;member-&gt;first_name . ' ' . $store-&gt;member-&gt;last_name }}&lt;/span&gt;&lt;br&gt;
    &lt;h2&gt;Products:&lt;/h2&gt;
    @foreach($store-&gt;products as $product)
        &lt;h3&gt;{{$product-&gt;name}}&lt;/h3&gt;
        &lt;span&gt;{{$product-&gt;short_desc}}&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span&gt;Price: {{$product-&gt;price}}&lt;/span&gt;&lt;br/&gt;
        &lt;?php Debugbar::info('Product displayed'); ?&gt;
    @endforeach
    &lt;br/&gt;========================&lt;br/&gt;
@endforeach</pre><p dir="rtl">والنتيجة كالتالي:</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/pic3.png.06f679a5bf76284e2d1d3fb2534f960e.png"><img data-fileid="5948" class="ipsImage ipsImage_thumbnailed" alt="pic3.thumb.png.81f45d7561a7fe9028cc409f6" src="https://academy.hsoub.com/uploads/monthly_2015_10/pic3.thumb.png.81f45d7561a7fe9028cc409f6f9710b1.png"></a></p><p dir="rtl">ومن اجل هذا المثال، زوّدت قاعدة البيانات بخمس مستخدمين، وثلاثة محالّ، وأربعة منتَجات. يقوم الاستعلام الأول باستدعاء كل المحال من قاعدة البيانات، وهذا هو الجزء +1 من مشكلة N+1. في هذا المثال تحديدًا، حرف N يمثّل عدد المحلات التي أرجعها لنا الاستعلام الأول، حيث أنها تمثل عدد المرات التي سنقوم فيها بالاستعلام <strong>select * from</strong> على جدولي <strong>products</strong> و <strong>members</strong>. وبما أن لدينا 3 محلات، فسنستعلم 3 مرات على جدول المستخدمين، وثلاث مرات على جدول المنتجات. وفي النهاية، قمنا بتنفيذ الاستعلامات بعدد مرات قدره 3+3+1.</p><p dir="rtl">تخيل الآن ما الذي يمكن أن يحدث لو كان لديك 5000 أو 10000 محل؟ سيكون لديك في تلك الحالة عشرة آلاف إلى عشرين ألف استعلام في كل مرة يقوم فيها أحد المستخدمين بزيارة الصفحة. وماذا لو كانت لديك عشرة آلاف أو مئة ألف زيارة كلّ أربع وعشرين ساعة؟ هذا كابوس! من الواضح الآن أن هذا التوجّه مدمّر للأداء. وبغض النظر عن نوع قاعدة البيانات التي تستخدمها، وعن مدى قوة الخادم الذي لديك، فستصل دائمًا إل تلك النقطة التي يقف فيها العتاد القوي لديك عاجزًا. يمكنك أن تحسّن الأداء بعمل cache لهذه الاستعلامات، باستخدام Redis على سبيل المثال. سيؤدي هذا الغرض، ولكن لبعض الوقت فقط. وبتلك الطريقة، أنت فقط تؤجل النهاية الحتميّة التي ستكلّفك الكثير من المال والوقت، وفي الغالب ستفقد بعض الزبائن، أو أنّ قاعدة بياناتك ستضعف كثيرًا.</p><p dir="rtl">وهنا يأتي التحميل الحثيث لينقذك من هذه الورطة. استخدام التحميل الحثيث في Laravel بسيط للغاية. العلاقات التي ترغب أن يتم تحميلها بشكل حثيث تحددها في طريقة <span style="font-family:courier new,courier,monospace;">with</span> كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">$stores = Store::with('member','products')-&gt;get();</pre><p dir="rtl">الآن، بدل استخدام 7 استعلامات، قلّلنا باستخدام التحميل الحثيث عدد الاستعلامات إلى 3 فقط:</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/pic4.png.6516739465830c0c1ee14e65a623e8ed.png"><img data-fileid="5950" class="ipsImage ipsImage_thumbnailed" alt="pic4.thumb.png.6b36cfdc41ebbf5e138ee306e" src="https://academy.hsoub.com/uploads/monthly_2015_10/pic4.thumb.png.6b36cfdc41ebbf5e138ee306ecd55196.png"></a></p><p dir="rtl">وستكون ثلاثة استعلامات حتى ولو كانت لديك عشرة آلاف مدخلة في جدول المحلات. وكما ترى، فإن الاستخدام السليم للتحميل الحثيث يمكن أن يؤدي إلى تحسين أداء تطبيقك بقدر هائل. ولكي نحصل على تحسن للأداء بالفعل، فعلينا أن نوجد فهرسًا لحقل الهويّة <span style="font-family:courier new,courier,monospace;">id</span> في جدولي <strong>members</strong> و <strong>products</strong>. ومع وجود كمّ هائل من السجلات، فإن تنفيذ <span style="font-family:courier new,courier,monospace;">(... ,'in( '1', '2</span> على حقل غير مفهرس سيأخذ وقتًا طويلًا.</p><p dir="rtl">وبعد هذه المقدمة عن التحميل الحثيث، هيا بنا نرى كيف يمكننا أن نستخدم العلاقات مع <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%86%D9%85%D8%B7-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%88%D8%AF%D8%B9-%D9%81%D9%8A-laravel-5-r195/">المستودعات</a>.</p><h2 dir="rtl">تمديد فئة المستودع</h2><p dir="rtl">سأريك طريقة واحدة يمكنك فيها أن تستخدم العلاقات في فئات مستودعات concrete. وهنا مثال عن النتيجة النهائيّة:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">function __construct(StoreRepository $stores) {
    $this-&gt;stores = $stores;
}

public function index() {
    $stores = $this-&gt;stores-&gt;with('member', 'products')-&gt;all();
    ....
}</pre><p dir="rtl">وكما ترى هنا، لدينا طريقة <span style="font-family:courier new,courier,monospace;">with</span> يمكنك أن تسلسل فيها نموذج العلاقات. ستكون هذه الطريقة شبيهة بطريقة <span style="font-family:courier new,courier,monospace;">with</span> في <a target="_blank" rel="external nofollow" href="https://github.com/laravel/framework/blob/5.0/src/Illuminate/Database/Eloquent/Builder.php#L734">Laravel’s Query Builder</a>.</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">public function with($relations) {
    if (is_string($relations)) $relations = func_get_args();
    $this-&gt;with = $relations;
    return $this;
}</pre><p dir="rtl">نحتاج الآن لأن نربط كلّ علاقة من العلاقات التي قمنا بتقديمها بالنموذج:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">protected function eagerLoadRelations() {
    if(!is_null($this-&gt;with)) {
        foreach ($this-&gt;with as $relation) {
            $this-&gt;model-&gt;with($relation);
        }
    }
    return $this;
}</pre><p dir="rtl">وها هو ذا، والشيء الوحيد الذي تبقّى هو أن نحدّث طريقة مستودع<strong> ()all</strong> (وأي شيء آخر ترغب بتحديثه) لاستخدام التحميل الحثيث:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">public function all($columns = array('*')) {
    $this-&gt;applyCriteria();
    $this-&gt;newQuery()-&gt;eagerLoadRelations();
    return $this-&gt;model-&gt;get($columns);
}</pre><p dir="rtl">وكما سبق وذكرت، فيمكنك أن تضيف عدّة علاقات ضمن طريقة <span style="font-family:courier new,courier,monospace;">()with</span>. وفيما يلي مثال على <strong>StoresControler</strong>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;?php 
    namespace App\Http\Controllers;
    use App\Repositories\StoreRepository;

    class StoresController extends Controller {
        protected $stores;
        function __construct(StoreRepository $stores) {
            $this-&gt;stores = $stores;
        }
        public function index() {
            $stores = $this-&gt;stores-&gt;with('member', 'products')-&gt;all();
            return \View::make('stores.index')-&gt;with('stores', $stores);
        }
    }</pre><p dir="rtl">وفي العرض يمكنك أن تعرض البيانات بالطريقة التي تريدها، ولغرض التجربة يكفي هذا:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">@foreach($stores as $store)
    &lt;h1&gt;{{ $store-&gt;name }}&lt;/h1&gt;
    &lt;span&gt;Owner: {{ $store-&gt;member-&gt;first_name . ' ' . $store-&gt;member-&gt;last_name }}&lt;/span&gt;&lt;br&gt;
    &lt;h2&gt;Products:&lt;/h2&gt;
    @foreach($store-&gt;products as $product) 
        &lt;h3&gt;{{$product-&gt;name}}&lt;/h3&gt;
        &lt;span&gt;{{$product-&gt;short_desc}}&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
        &lt;span&gt;Price: {{$product-&gt;price}}&lt;/span&gt;&lt;br/&gt;
        &lt;?php Debugbar::info('Product displayed'); ?&gt;
    @endforeach
    &lt;br/&gt;========================&lt;br/&gt;
@endforeach</pre><p dir="rtl">وكما هو متوقع، لدينا الآن هذه الاستعلامات الثلاثة فقط:</p><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_10/pic5.png.feefe8de0e1908432786b301b08c1778.png"><img data-fileid="5949" class="ipsImage ipsImage_thumbnailed" alt="pic5.thumb.png.61a6a34e29cafd231be676d20" src="https://academy.hsoub.com/uploads/monthly_2015_10/pic5.thumb.png.61a6a34e29cafd231be676d20c9fd4ac.png"></a></p><h1 dir="rtl">الخلاصة</h1><p dir="rtl">يمكنك باستخدام التحميل الحثيث أن تحسّن أداء تطبيقك. وأحيانًا، عندما يكبر التطبيق، حتى التحميل الحثيث ليس كافيًا للحفاظ على أعلى أداء. في الدرس التالي سأريك كيف يمكنك تجميل مستودعاتك لتقوم بعمل cache للاستعلامات من أجل أداء أفضل.</p><p dir="rtl" style="line-height: 22.4px;">ترجمة -وبتصرف- للمقال: <a rel="external nofollow" href="https://bosnadev.com/2015/03/26/using-repository-pattern-in-laravel-5-eloquent-relations-and-eager-loading/">Using Repository Pattern in Laravel 5 - Eloquent Relations and Eager Loading</a>.</p>
]]></description><guid isPermaLink="false">193</guid><pubDate>Thu, 15 Oct 2015 18:22:00 +0000</pubDate></item></channel></rss>
