<?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/4/?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>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x635;&#x648;&#x631; &#x641;&#x64A; 5 Laravel - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x644;&#x62B;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%81%D9%8A-5-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-r172/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.png.ab52ef47eaa0b92d1b7a6fcab21a8ae2.png.210c7e57385888264b6ab0464858747d.png" /></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%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%81%D9%8A-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r164/">إعداد المشروع</a> و<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%81%D9%8A-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r170/">إنشاء توابع وعروض الإنشاء والتخزين والعرض</a>، سوف نقوم في درسنا الأخير اليوم بكتابة الشيفرة البرمجية لتوابع التعديل والتحديث والحذف ومن ثم العروض الموافق لها.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.png.ab52ef47eaa0b92d1b7a6fcab21a8ae2.png.82524e18d09d558d49a0518b2fdc1b7a.png"><img data-fileid="4943" class="ipsImage ipsImage_thumbnailed" alt="laravel5-image-management.thumb.png.5c3f" src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.png.ab52ef47eaa0b92d1b7a6fcab21a8ae2.thumb.png.1979e418ac2339e2a22a8c4b261a3365.png"></a></p><h2>تابع Edit</h2><p>إن توابع وعروض <code>edit</code> و<code>delete</code> غير موجودة لحد الساعة، فلننشئها، سنبدأ بالعمل على <code>edit</code> أولا.<br>عدل على تابع المتحكم:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function edit($id)
{
   $marketingImage = Marketingimage::findOrFail($id);
   return view('marketingimage.edit', compact('marketingImage'));
}</pre><p>مرة أخرى قمنا باستخدام تابع <code>findOrFail</code> وقمنا بإرسال الكائن إلى العرض لأننا نريد أن نقوم بتعبئة الاستمارة مسبقا بالقيم المناسبة من سجلات البيانات.</p><h2>عرض Edit</h2><p>عدل على ملف <span style="font-family:courier new,courier,monospace;"><code>views/marektingimage/edit.blade.php</code></span> ليكون كالتالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@extends('layouts.master')

@section('content')
   {!! Breadcrumb::withLinks(['Home'   =&gt; '/',
                              'marketing images' =&gt; '/marketingimage',
                              "edit $marketingImage-&gt;image_name.$marketingImage-&gt;image_extension"
                               ]) !!}

    &lt;h1&gt;Edit {{ $marketingImage-&gt;image_name. '.' . $marketingImage-&gt;image_extension }} &lt;/h1&gt;
    &lt;hr/&gt;

    @if (count($errors) &gt; 0)
       &lt;div class="alert alert-danger"&gt;
         &lt;strong&gt;Whoops! &lt;/strong&gt; There were some problems with your input. &lt;br&gt; &lt;br&gt;
           &lt;ul&gt;
             @foreach ($errors-&gt;all() as $error)
               &lt;li&gt;{{ $error }} &lt;/li&gt;
             @endforeach
           &lt;/ul&gt;
       &lt;/div&gt;
    @endif

    &lt;div&gt;
       Note: name and path values cannot be changed.  If you wish to change these, then delete and create a new photo:
    &lt;/div&gt;
    &lt;br&gt;


   {!! Form::model($marketingImage, ['route' =&gt; ['marketingimage.update', $marketingImage-&gt;id],
                          'method' =&gt; 'PATCH',
                          'class' =&gt; 'form',
                          'files' =&gt; true]
                          ) !!}

    &lt;!-- image name Form Input --&gt;
    &lt;div&gt;
      &lt;ul&gt;
        &lt;li&gt; &lt;h4&gt;Image Name:   {{ $marketingImage-&gt;image_name. '.' . $marketingImage-&gt;image_extension }}   &lt;/h4&gt; &lt;/li&gt;
        &lt;li&gt; &lt;h4&gt;Image Path:   {{ $marketingImage-&gt;image_path }}  &lt;/h4&gt;  &lt;/li&gt;
        &lt;li&gt; &lt;h4&gt;Mobile Name:   {{ $marketingImage-&gt;mobile_image_name. '.' . $marketingImage-&gt;mobile_extension }}  &lt;/h4&gt;  &lt;/li&gt;
        &lt;li&gt; &lt;h4&gt;Mobile Path:   {{ $marketingImage-&gt;mobile_image_path }}  &lt;/h4&gt; &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- is_something Form Input --&gt;
    &lt;div class="form-group"&gt;
       {!! Form::label('is_active', 'Is Active:') !!}
       {!! Form::checkbox('is_active') !!}
    &lt;/div&gt;

    &lt;!-- is_featured Form Input --&gt;
    &lt;div class="form-group"&gt;
       {!! Form::label('is_featured', 'Is Featured:') !!}
       {!! Form::checkbox('is_featured') !!}
    &lt;/div&gt;

    &lt;!-- form field for file --&gt;
    &lt;div class="form-group"&gt;
       {!! Form::label('image', 'Primary Image') !!}
       {!! Form::file('image', null, array('class'=&gt;'form-control')) !!}
    &lt;/div&gt;

    &lt;!-- form field for file --&gt;
    &lt;div class="form-group"&gt;
       {!! Form::label('mobile_image', 'Mobile Image') !!}
       {!! Form::file('mobile_image', null, array('class'=&gt;'form-control')) !!}
    &lt;/div&gt;

    &lt;div class="form-group"&gt;
       {!! Form::submit('Edit', array('class'=&gt;'btn btn-primary')) !!}
    &lt;/div&gt;

   {!! Form::close() !!}
    &lt;div&gt;
       {!! Form::model($marketingImage, ['route' =&gt; ['marketingimage.destroy', $marketingImage-&gt;id],
       'method' =&gt; 'DELETE',
       'class' =&gt; 'form',
       'files' =&gt; true]
       ) !!}

        &lt;div class="form-group"&gt;
           {!! Form::submit('Delete Photos', array('class'=&gt;'btn btn-danger', 'Onclick' =&gt; 'return ConfirmDelete();')) !!}
        &lt;/div&gt;

       {!! Form::close() !!}
    &lt;/div&gt;
@endsection

@section('scripts')
    &lt;script&gt;
       function ConfirmDelete()
       {
           var x = confirm("Are you sure you want to delete?");
           if (x)
               return true;
           else
               return false;
       }
    &lt;/script&gt;
@endsection</pre><p>لم نسمح للمستخدم بتعديل أسماء الصور أومساراتها لأننا نريدهم أن يقوموا بحذف السجلات والبدء من جديد وإلا سيكون الأمر معقدا عندما نقوم بتعديل الأسماء التي قمنا بحفظها في السجلات وهذا الأمر لا يدخل في نطاق الدرس.</p><p>ماهي الاختلافات الأخرى في الاستمارة ؟ سوف تلاحظ أننا نستخدم حقول أقل وقمنا باستخدام الربط بين النموذج والاستمارة في مساعدي الاستمارة (form helper):</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">{!! Form::model($marketingImage, ['route' =&gt; ['marketingimage.update', $marketingImage-&gt;id],
                                 'method' =&gt; 'PATCH',
                                 'class' =&gt; 'form',
                                 'files' =&gt; true]
) !!}</pre><p>إن مثيل النموذج <code>marketingImage</code><span style="font-family: monospace; line-height: 17.92px;">$</span> مرتبط بالاستمارة لذلك سيتم تعبئة الحقول بشكل مسبق، ولاحظ أننا قمنا أيضا بتحديد <code>marketingImage-&gt;id</code><span style="font-family: monospace; line-height: 17.92px;">$</span> حتى نتمكن من إرسال ذلك إلى تابع المتحكم وتعديل السجل الصحيح.</p><p>ولقد قمنا بتعيين قيمة <code>PATCH</code> إلى <code>method</code> وهذه سوف تتغير تلقائيا لأن HTML لا يدعم <code>PATCH</code>، ولقد قمنا بتعيين قيمة <code>true</code> إلى <code>files</code> حتى نتمكن من إرسال الملفات.</p><p>بقية الشيفرة سهلة وقمنا بشرحها سابقا، لاحظ أننا قمنا بوضع زر للحذف في الأسفل في حالة ما أراد المستخدم الحذف بدل التعديل.<br>عند سير العمل بطريقة عادية، سوف تكون خطوتك القادمة في الغالب الانتقال إلى تابع <strong>update</strong> في <strong>MarketingImagesController</strong> لكننا سنقوم بإنشاء صنف request للتعامل مع سيناريو update.</p><h2>EditImageRequest</h2><p>الفرق في عملية التحقق بين <code>create</code> و <code>update</code> هو أنه عندما تقوم بإنشاء صورة سيكون ملف الصورة إلزاميا على عكس التحديث، لذلك قررت لأجل البساطة والوضوح أن نقوم بإنشاء صنف request منفصل باسم <span style="font-family:courier new,courier,monospace;">EditImageRequest</span> بدلا من وضعه في صنف request واحد.</p><p>المشكلة التي واجهتها هي أنني لا أعرف كيف أجعلها شرطية فعلى أي تابع يجب وضع الصنف، لذلك بدأت في التفكير في الأمر، فبدلا من ذلك، يمكنني أن أقوم بتمرير حقل خفي والذي سوف يُعرف الاستمارة وسوف أقوم بوضع فيه عنصر تحكم منطقي (controlling logic)، فإذا كانت الاستمارة استمارة <code>create</code>، فستكون الصور إلزامية، لكنني في النهاية قررت أنه من الأسهل أن أقوم بعمل صنف منفصل.</p><p>لذلك قم بتنفيذ هذا الأمر من سطر الأوامر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan make:request EditImageRequest</pre><p>ثم قم بتعيين قيمة <code>return true</code> في تابع <strong>authorize</strong> في ذلك الصنف وعدل تابع <code>rules</code> إلى التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function rules()
{
   return [
       'is_active' =&gt; 'boolean',
       'is_featured' =&gt; 'boolean',
       'image' =&gt; 'mimes:jpeg,jpg,bmp,png | max:1000',
       'mobile_image' =&gt; 'mimes:jpeg,jpg,bmp,png | max:1000'
   ];
}</pre><p>قمنا بالفعل بالتحدث عن تابع <code>rules</code> سابقا ولا داعي لإعادة شرحه هنا.</p><h2>تابع Update</h2><p>لنقم الآن بالانتقال إلى تابع update في <strong>MarketingImageController</strong>، عدله كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function update($id, EditImageRequest $request)
{
   $marketingImage = Marketingimage::findOrFail($id);

   $marketingImage-&gt;is_active = $request-&gt;get('is_active');
   $marketingImage-&gt;is_featured = $request-&gt;get('is_featured');

   $this-&gt;formatCheckboxValue($marketingImage);
   $marketingImage-&gt;save();

   if ( ! empty(Input::file('image'))){

       $destinationFolder = '/imgs/marketing/';
       $destinationThumbnail = '/imgs/marketing/thumbnails/';

       $file = Input::file('image');

       $imageName = $marketingImage-&gt;image_name;
       $extension = $request-&gt;file('image')-&gt;getClientOriginalExtension();

       //create instance of image from temp upload
       $image = Image::make($file-&gt;getRealPath());

       //save image with thumbnail
       $image-&gt;save(public_path() . $destinationFolder . $imageName . '.' . $extension)
           -&gt;resize(60, 60)
           // -&gt;greyscale()
           -&gt;save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

   }

   if ( ! empty(Input::file('mobile_image'))) {

       $destinationMobile = '/imgs/marketing/mobile/';
       $mobileFile = Input::file('mobile_image');

       $mobileImageName = $marketingImage-&gt;mobile_image_name;
       $mobileExtension = $request-&gt;file('mobile_image')-&gt;getClientOriginalExtension();

       //create instance of image from temp upload
       $mobileImage = Image::make($mobileFile-&gt;getRealPath());
       $mobileImage-&gt;save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);
   }

   flash()-&gt;success('image edited!');
   return view('marketingimage.edit', compact('marketingImage'));
}</pre><p>دعونا نبدأ بتوقيع التابع:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function update($id, EditImageRequest $request)
{</pre><p>سوف ترى أننا نقوم بسحب مثيل من كائن request الصحيح، وقمنا باستخدام findOrFail في نموذج السجل حتى نتمكن من تعيين القيم من مثيل request، وبعد ذلك قمنا بتهيئة (format) قيم خانة الاختيار (checkbox) ثم حفظناها:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">   $marketingImage = Marketingimage::findOrFail($id);

   $marketingImage-&gt;is_active = $request-&gt;get('is_active');
   $marketingImage-&gt;is_featured = $request-&gt;get('is_featured');

   $this-&gt;formatCheckboxValue($marketingImage);
   $marketingImage-&gt;save();</pre><p>إذا لم تكن الصورة الأولية فارغة، سوف نقوم بالتحديث:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">if ( ! empty(Input::file('image'))){

   $destinationFolder = '/imgs/marketing/';
   $destinationThumbnail = '/imgs/marketing/thumbnails/';

   $file = Input::file('image');

   $imageName = $marketingImage-&gt;image_name;
   $extension = $request-&gt;file('image')-&gt;getClientOriginalExtension();

   //create instance of image from temp upload
   $image = Image::make($file-&gt;getRealPath());

   //save image with thumbnail
   $image-&gt;save(public_path() . $destinationFolder . $imageName . '.' . $extension)
       -&gt;resize(60, 60)
       // -&gt;greyscale()
       -&gt;save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

}</pre><p>ثم سنفعل نفس الشيء على صور الهاتف:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">if ( ! empty(Input::file('mobile_image'))) {

   $destinationMobile = '/imgs/marketing/mobile/';
   $mobileFile = Input::file('mobile_image');

   $mobileImageName = $marketingImage-&gt;mobile_image_name;
   $mobileExtension = $request-&gt;file('mobile_image')-&gt;getClientOriginalExtension();

   //create instance of image from temp upload
   $mobileImage = Image::make($mobileFile-&gt;getRealPath());
   $mobileImage-&gt;save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);
}</pre><p>ثم قمنا بتنفيذ <code>flash</code> لـ <code>success</code> وبعد ذلك قمنا بالعودة <code>return</code> وفي حالتنا هذه إلى صفحة التعديل <code>edit</code>، لكن يمكنك تغيير العودة إلى أي صفحة تريدها:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">flash()-&gt;success('image edited!');
return view('marketingimage.edit', compact('marketingImage'));</pre><p>أرجو ملاحظة أنه إذا كنت تقوم بعمل هذا لشركة تطوير، ربما قد تريد أن تجعل هذه الشيفرة أقوى عن طريق التحقق من أن الملف قد تم إنشاءه، وسوف تتعامل مع الأمر بشكل مختلف إذا لم يعمل لبعض الأسباب، لكن كل هذا خارج نطاق الدرس.</p><p>حسنا، الآن آخر خطوة في درسنا.</p><h2>تابع Destroy</h2><p>سوف نحتاج إلى كتابة تابع <strong>destroy</strong> للتعامل مع حذف الصور:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function destroy($id)
{
   $marketingImage = Marketingimage::findOrFail($id);
   $thumbPath = $marketingImage-&gt;image_path.'thumbnails/';

   File::delete(public_path($marketingImage-&gt;image_path).
                            $marketingImage-&gt;image_name . '.' .
                            $marketingImage-&gt;image_extension);

   File::delete(public_path($marketingImage-&gt;mobile_image_path).
                            $marketingImage-&gt;mobile_image_name . '.' .
                            $marketingImage-&gt;mobile_extension);
   File::delete(public_path($thumbPath). 'thumb-' .
                            $marketingImage-&gt;image_name . '.' .
                            $marketingImage-&gt;image_extension);

    Marketingimage::destroy($id);

   flash()-&gt;success('image deleted!');

   return redirect()-&gt;route('marketingimage.index');

}</pre><p>يمكنك أن ترى أننا قمنا باستخدام <code>findOrFail</code> على <code>id</code> الذي تم استلامه عن طريق التوقيع، ثم استخدمنا مساعدي الملف (File helper) لـ Laravel للحذف، وهكذا تحصلنا مرة أخرى على صياغة جميلة لتبين لنا ما نقوم بفعله.<br>قمنا أيضا باستخدام تابع <span style="font-family:courier new,courier,monospace;">()public_path</span> ووضعنا مكونات الصورة داخل ذلك التوقيع، وبعد ذلك قمنا بتكرار نفس الأمر مع كل نوع من الصور مرتبط مع السجل، ثم استخدمنا تابع <span style="font-family:courier new,courier,monospace;">destroy</span> لحذف السجل من قاعدة البيانات، وقمنا بتنفيذ <code>flash</code> لتابع <code>success</code> ومن ثم قمنا بإعادة التوجيه إلى صفحة <code>index</code>، وهاقد انتهينا.</p><h2>خاتمة</h2><p>لقد تعلمنا في <a href="https://academy.hsoub.com/search/?tags=%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9+%D8%A7%D9%84%D8%B5%D9%88%D8%B1+%D9%81%D9%8A+laravel+5">هذه الدروس</a> العديد من الطرق والمفاهيم الجديدة في Laravel، وعلى الرغم من بساطة التطبيق الذي قمنا بعمله إلا أنه سيكون بداية جيدة لاحتراف إدارة الصور في Laravel، وإذا كان لديك أي سؤال أو تعليق، فيسرنا أن نسمعه في التعليقات في الأسفل، وإذا أعجبتك هذه التدوينة، أرجو أن تقوم بمشاركتها مع أصدقاءك.</p><p>ترجمة -وبتصرّف- للدرس <a rel="external nofollow" href="https://laraveltips.wordpress.com/2015/07/29/basic-image-management-part-3/">Basic Image Management Part 3</a> لصاحبه Bill Keck.</p><p>حقوق الصورة البارزة: <a rel="external nofollow" target="_blank" href="http://www.freepik.com/free-vector/polaroid-photo-frames_769601.htm">Designed by Freepik</a>.</p>
]]></description><guid isPermaLink="false">172</guid><pubDate>Sun, 20 Sep 2015 22:44:00 +0000</pubDate></item><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x635;&#x648;&#x631; &#x641;&#x64A; Laravel 5 - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x646;&#x64A;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%81%D9%8A-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r170/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.png.9b31dad0e4068f6e79fb55b83e0ff691.png" /></p>

<p>في الحالة العادية، سوف تقوم بكتابة تابع (<font face="monospace">store method</font>) أولا، ومن ثم تترك عملية التحقق في النهاية حتى يعمل <code>store</code> بشكل جيد، لكن في حالتنا هذه سيكون الأمر معقدا قليلا بما أننا نتعامل مع ملفات منفصلة يجب حفظها، ففي حالة الصور، سوف نحتاج إلى التحقق أولا.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.png.ab52ef47eaa0b92d1b7a6fcab21a8ae2.png"><img data-fileid="4935" class="ipsImage ipsImage_thumbnailed" alt="laravel5-image-management.thumb.png.5c3f" src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.thumb.png.d2102a1617ddf6418c70695a6fe327dc.png"></a></p><h2>صنف Request</h2><p>سوف نبدأ بإنشاء صنف (request class) والذي سيقوم بالتعامل مع عملية التحقق من استمارة الإنشاء. سوف نبدأ بكتابة هذا الأمر على سطر الأوامر:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">php artisan make:request CreateImageRequest</pre><p>هذا الأمر سيقوم بإنشاء الملف ووضعه داخل مجلد <code>app/Http/Requests</code>.</p><p>بعد ذلك، عدل الملف كالتالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;?php
  namespace App\Http\Requests;

  use App\Http\Requests\Request;
  use App\Marketingimage;

  class CreateImageRequest extends Request
  {
    /**
    * Determine if the user is authorized to make this request.
    *
    * @return bool
    */
    public function authorize()
    {
      return true;
    }

    /**
    * Get the validation rules that apply to the request.
    *
    * @return array
    */
    public function rules()
    {
       return [
         'image_name' =&gt; 'alpha_num | required | unique:marketing_images',
         'mobile_image_name' =&gt; 'alpha_num | required | unique:marketing_images',
         'is_active' =&gt; 'boolean',
         'is_featured' =&gt; 'boolean',
         'image' =&gt; 'required | mimes:jpeg,jpg,bmp,png | max:1000',
         'mobile_image' =&gt; 'required | mimes:jpeg,jpg,bmp,png | max:1000'
       ];
    }
}</pre><p>واحد من الأشياء التي أحبها في إطار Laravel هو كيفية تعامله مع عملية التحقق، فإذا كانت هذه المرة الأولى التي ستتعامل فيها مع عملية التحقق، سوف تجد أن هذه العملية بسيطة للغاية.</p><p>لاحظ أننا قمنا بكتابة السطر التالي في تابع <code>authorize</code>:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">return true;</pre><p>هذا السطر سوف يسمح للطلب أن يمر، فإذا وضعنا شرطا عليه فسنستطيع التحكم فيه، فعلى سبيل المثال، يمكننا استخدامه في تسجيل الدخول للأعضاء فقط.</p><p>بعد ذلك لدينا قواعد التابع، الذي سوف يتم فرضها على عملية التحقق في حقول الاستمارة، لن نتعمق أكثر هنا، فإذا أردت المزيد يمكنك الإطلاع على <a rel="external nofollow" href="http://laravel.com/docs/5.1/validation#introduction">توثيق Laravel</a>.</p><p>للتذكير فإننا نفصل ما بين قواعد التّحقق بمحرف <span style="font-family:courier new,courier,monospace;">"</span><span style="font-family:courier new,courier,monospace;">|"</span> ولما نضيف قاعدة "unique" فإننا نُرفقها باسم الجدول الذي يجب أن نبحث فيه (يعني الجدول الذي نرغب في أن يكون السّجل record الذي نقوم بحفظه وحيدًا "unique").</p><p>ومن الطبيعي أننا أننا قمنا بإضافة قيد على حجم الملفات. يمكنك إيجاد قائمة كاملة من قواعد التحقق في <a rel="external nofollow" href="http://laravel.com/docs/5.1/validation#available-validation-rules">الوثائق</a>.</p><h2><span style="font-family:arial,helvetica,sans-serif;">تابع Store</span></h2><p>على أي حال، سوف ننتقل الآن لتابع <code>store</code> في <code>MarketingImageController</code>، عدل التابع كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function store(CreateImageRequest $request)
{
   //create new instance of model to save from form
   $marketingImage = new Marketingimage([
       'image_name'        =&gt; $request-&gt;get('image_name'),
       'image_extension'   =&gt; $request-&gt;file('image')-&gt;getClientOriginalExtension(),
       'mobile_image_name' =&gt; $request-&gt;get('mobile_image_name'),
       'mobile_extension'  =&gt; $request-&gt;file('mobile_image')-&gt;getClientOriginalExtension(),
       'is_active'         =&gt; $request-&gt;get('is_active'),
       'is_featured'       =&gt; $request-&gt;get('is_featured'),

   ]);

   //define the image paths
   $destinationFolder = '/imgs/marketing/';
   $destinationThumbnail = '/imgs/marketing/thumbnails/';
   $destinationMobile = '/imgs/marketing/mobile/';

   //assign the image paths to new model, so we can save them to DB
   $marketingImage-&gt;image_path = $destinationFolder;
   $marketingImage-&gt;mobile_image_path = $destinationMobile;

   // format checkbox values and save model
   $this-&gt;formatCheckboxValue($marketingImage);
   $marketingImage-&gt;save();

   //parts of the image we will need
   $file = Input::file('image');

   $imageName = $marketingImage-&gt;image_name;
   $extension = $request-&gt;file('image')-&gt;getClientOriginalExtension();

   //create instance of image from temp upload
   $image = Image::make($file-&gt;getRealPath());

   //save image with thumbnail
   $image-&gt;save(public_path() . $destinationFolder . $imageName . '.' . $extension)
       -&gt;resize(60, 60)
       // -&gt;greyscale()
       -&gt;save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

   // now for mobile
   $mobileFile = Input::file('mobile_image');

   $mobileImageName = $marketingImage-&gt;mobile_image_name;
   $mobileExtension = $request-&gt;file('mobile_image')-&gt;getClientOriginalExtension();

   //create instance of image from temp upload
   $mobileImage = Image::make($mobileFile-&gt;getRealPath());
   $mobileImage-&gt;save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);


   // Process the uploaded image, add $model-&gt;attribute and folder name
   flash()-&gt;success('Marketing Image Created!');

   return redirect()-&gt;route('marketingimage.show', [$marketingImage]);
}</pre><p>حسنا، دعونا نبدأ بفهم هذه الشفرة الطويلة، سنبدأ مع توقيع الدالة:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function store(CreateImageRequest $request)</pre><p>هذا الجزء واضح، فلقد قمنا فقط بسحب نسخة (instance) من كائن <code>request</code> يحمل الاسم <code>request$</code> وهذا سوف يساعدنا على إنشاء نسخة جديدة للنموذج:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">//create new instance of model to save from form

$marketingImage = new Marketingimage([
   'image_name'        =&gt; $request-&gt;get('image_name'),
   'image_extension'   =&gt; $request-&gt;file('image')-&gt;getClientOriginalExtension(),
   'mobile_image_name' =&gt; $request-&gt;get('mobile_image_name'),
   'mobile_extension'  =&gt; $request-&gt;file('mobile_image')-&gt;getClientOriginalExtension(),
   'is_active'         =&gt; $request-&gt;get('is_active'),
   'is_featured'       =&gt; $request-&gt;get('is_featured'),

]);</pre><p>لاحظ أنني أقوم بالتعليق كثيرا على هذا التابع (method)، لأنه من السهل أن يربكك. على أي حال، قمنا بإنشاء مثيل جديد لـ <code>Marketingimage</code> ووضعنا خصائص النموذج باستخدام مثيل <code>request</code><span style="font-family: monospace; line-height: 17.92px;">$</span>.</p><p>أما البقية الشيفرة، فلقد قُمنا بسحب البيانات من الاستمارة إذا نجحت في عملية التحقق. ثم سوف نحتاج إلى تعريف مسارات الصور:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">//define the image paths

$destinationFolder = '/imgs/marketing/';
$destinationThumbnail = '/imgs/marketing/thumbnails/';
$destinationMobile = '/imgs/marketing/mobile/';</pre><p><strong>ملاحظة</strong>: حاولت أن أجعل هذه الأسماء بديهية قدر الإمكان.<br>بعد ذلك، سوف نقوم بتعيينها إلى النموذج حتى نتمكن من حفظهم في قاعدة البيانات.</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">//assign the image paths to new model, so we can save them to DB

$marketingImage-&gt;image_path = $destinationFolder;
$marketingImage-&gt;mobile_image_path = $destinationMobile;</pre><p>نستطيع فعل هذا بطريقة أخرى، فيمكننا أن نقوم بتقديم معلومات المسار في الاستمارة أو يمكننا تخطي هذا كليا، لكن وجدت أن إبقاء المسار في قاعدة البيانات يجعل العمل مع الصور أسهل عندما نحتاج إلى استخدامها في العروض (views)، وهذا هو سبب استخدامنا هذه الطريقة.<br>ثم سنقوم بتهيئة (format) قيم خانة اختيار ومن ثم نقوم بحفظها:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">// format checkbox values and save model

$this-&gt;formatCheckboxValue($marketingImage);
$marketingImage-&gt;save();
</pre><p>يمكنك أن ترى أنني أقوم بتسليم مثيل النموذج <span style="font-family:courier new,courier,monospace;">marketingImage<span style="line-height: 17.92px;">$</span></span> إلى تابع <span style="font-family:courier new,courier,monospace;">formatCheckboxValue،</span> وهو تابع قمت بعمله للتأكد من أن خانة الاختيار يتم التعامل معها بشكل جيد:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function formatCheckboxValue($marketingImage)
{
   $marketingImage-&gt;is_active = ($marketingImage-&gt;is_active == null) ? 0 : 1;
   $marketingImage-&gt;is_featured = ($marketingImage-&gt;is_featured == null) ? 0 : 1;
}</pre><p>بسبب نوع البيانات في قاعدة البيانات، يمكننا توفير فقط رقمين 0 و 1، لذلك نحتاج إلى التأكد من أننا نقوم بالتحويل بشكل صحيح من خانة الاختيار (checkbox) في الاستمارة (form). لقد قمنا بتسليمها إلى مثيل النموذج ومن ثم سيقوم بوضع الخصائص وفقا لذلك.<br>بعد ذلك نعود إلى تابع <code>store</code>، ونقوم ببساطة بالحفظ:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">$marketingImage-&gt;save();</pre><p>وهذا سوف يهتم بسجلات قاعدة البيانات، ومع ذلك، لانزال بحاجة إلى التعامل مع الملف. في البداية سوف نعمل على بعض أجزاء الصورة التي سنحتاجها:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">//parts of the image we will need

$file = Input::file('image');

$imageName = $marketingImage-&gt;image_name;
$extension = $request-&gt;file('image')-&gt;getClientOriginalExtension();</pre><p>بدلا من ذلك، يمكنك جعل بعض هذه الشفرات في سطر واحد (inline) لكنك ستحصل على سطور طويلة جدا بالإضافة إلى أن إبقائها هكذا أسهل للتتبع والفهم.<br>الآن سوف نحتاج إلى استخدام مكتبة الصور (Image library) لمساعدتنا على الخروج من هنا، سنقوم بإنشاء مثيل لهذه الصورة من الصور المرفوعة:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">//create instance of image from temp upload
$image = Image::make($file-&gt;getRealPath());</pre><p>بعد ذلك، سنقوم بحفظها وإنشاء صورة مصغرة والتي سنقوم بحفظها عن طريق سَلسَلة التوابع (chaining the methods):</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">//save image with thumbnail
$image-&gt;save(public_path() . $destinationFolder . $imageName . '.' . $extension)
   -&gt;resize(60, 60)
   // -&gt;greyscale()
   -&gt;save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);</pre><p>سوف نقوم بتقسيم هذه الشيفرة إلى أجزاء حتى نفهمها بشكل أفضل، أول جزء يقوم بحفظ الصور الأولية:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">$image-&gt;save(public_path() . $destinationFolder . $imageName . '.' . $extension)</pre><p>استخدمنا <span style="font-family:courier new,courier,monospace;">()public_path</span> للوصول إلى المكان الذي يمكننا تعريف فيه مجلد الهدف (مجلد الصور) والذي هو <code>imgs/marekting/</code>.</p><p>بعد ذلك قمنا بسَلسَلة أجزاء الصورة (مسار ملف الصورة) التي نحتاجها وهذا سوف يعطينا كل شيء نحتاجه وسيسهل علينا عملية متابعة الشيفرة البرمجية.</p><p>بما أننا نحتاج أيضا إلى إنشاء صورة مصغرة، قمنا بسَلسَلة ذلك التابع:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">-&gt;resize(60, 60)</pre><p>وهذا السطر سوف ينشئ لنا نسخة بحجم 60 × 60 من الصورة، وإذا أردت تغيير حجم النسخة يمكنك فعل هذا بسهولة بتغيير الأرقام، ويمكنك أيضا إنشاء حقل في الاستمارة للمستخدمين لتحديد ارتفاع و عرض الصور المصغر. (لن نقوم بهذا في هذا الدرس.)</p><p>قمتُ بإرفاق (على شكل تعليق) تابع متسَلسَل لجعل الصورة المصغرة ذات تدرج رمادي، فإذا أردت صور مصغرة بيضاء وسوداء اجعل السطر شيفرة برمجية (عن طريق إزالة //).</p><p>والآن سنقوم بحفظ الصورة المصغرة:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">-&gt;save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);</pre><p>وسنقوم بنفس الشيء لصور الهاتف:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">// create instance of image from temp upload
$mobileImage = Image::make($mobileFile-&gt;getRealPath());
$mobileImage-&gt;save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);</pre><p>يما أنها مثل الصور الأولية لكن بدون صورة مصغرة، سوف نتركها هكذا.</p><p>حسنا، بعد ذلك لدينا رسالة الفلاش (flash message):</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">flash()-&gt;success('Marketing Image Created!');</pre><p>هذه الشيفرة لن تعمل إلا إذا قمت بتثبيت <a rel="external nofollow" href="https://github.com/laracasts/flash">حزمة الفلاش لجفري ويِ (Jefferey Wey)</a> وقمت باستدعائها في عرض (view) الصفحة الرئيسية، وإذا لم تقم بتثبيت هذه الحزمة فلا تكتب هذه الشيفرة.</p><p>في النهاية، بعد حفظ كُل من النموذج وملفات الصور، سوف نقوم بإعادة التوجيه نحو صفحة العرض:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">return redirect()-&gt;route('marketingimage.show', [$marketingImage]);</pre><p>الآن يمكنك تجربة رفع وحفظ الصور وعمل صورة مصغرة وصورة للهاتف عن طريق زيارة الاستمارة في العنوان التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">yourdomain.com/marketingimage/create</pre><p>يمكنك التأكد من إنشاء الصور من خلال النظر إلى المجلدات حيث يُفترض أن تكون الصور.</p><p>سوف ترى أن تابع <code>store</code> يقوم بالكثير من الأشياء، لكن ينقصه آلية للتحقق من الأخطاء، يمكنك فعل هذا لجعل التطبيق أكثر قوة على الرغم من أنني أعتقد أن أمر ليس ضروري.</p><p>بما أن Laravel يقوم بوظيفة جيدة عن طريق فصل استمارة التحقق من تابع <code>store</code>، لن يتوقف التابع إذا فشلت عملية التحقق.<br>حسنا ماذا يمكن أن يفشل أيضا ؟ حسنا ربما تفشل عملية حفظ الملف وهذا يمكن أن يكون بسبب امتلاء النظام، أو بسبب مشاكل في الصلاحيات أو خطأ في كتابة المسارات وأسماء المجلدات.</p><p>هذه الأخطاء صعبة الاكتشاف والتصحيح بسبب أنه ربما قد لا تحصل على رسائل الخطأ المناسبة، وعلى أية حال، هذه هي أشهر الأخطاء إذا أردت اكتشافها وتصحيحها.</p><p>يمكنك أن ترى أنه على الرغم من أنه لا شيء صعب في إدارة الصورة إلا أن الصعوبة موجودة بشكل ما.</p><p>الخطوة المنطقية التالية هي إنشاء تابع <code>show</code> في المتحكم وإنشاء العرض الخاص به.</p><h2>تابع show</h2><p>حسنا، هذه هي شيفرة تابع العرض:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function show($id)
{
   $marketingImage = Marketingimage::findOrFail($id);
   return view('marketingimage.show', compact('marketingImage'));
}</pre><p>هذه الشيفرة واضحة للغاية، يقوم Laravel باسترجاع مثيل النموذج ثم يقوم بإرجاعه إلى العرض view، لاحظ استخدام <code>findOrFail</code> والتي تقوم بإرجاع <code>ModelNotFoundException</code>، والتي يمكنك التعامل معها من خلال ملف <code>Handler.php</code> في <code>app/Exceptions</code>.</p><h2>عرض show</h2><p>حسنا، بعدما انتهينا من التابع ننتقل إلى العرض view:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@extends('layouts.master')

@section('content')
  {!! Breadcrumb::withLinks(['Home'   =&gt; '/',
      'marketing images' =&gt; '/marketingimage',
      "show $marketingImage-&gt;image_name.$marketingImage-&gt;image_extension"
   ]) !!}

  &lt;div&gt;
    {{ $marketingImage-&gt;image_name }} :  &lt;br&gt;
    &lt;img src="/imgs/marketing/{{ $marketingImage-&gt;image_name . '.' .
         $marketingImage-&gt;image_extension . '?'. 'time='. time() }}"&gt;
  &lt;/div&gt;

  &lt;div&gt;
     {{ $marketingImage-&gt;image_name }} - thumbnail :  &lt;br&gt;
     &lt;img src="/imgs/marketing/thumbnails/{{ 'thumb-' . $marketingImage-&gt;image_name . '.' .
$marketingImage-&gt;image_extension . '?'. 'time='. time() }}"&gt;
  &lt;/div&gt;

  &lt;div&gt;
    {{ $marketingImage-&gt;mobile_image_name }} - mobile :  &lt;br&gt;
    &lt;img src="/imgs/marketing/mobile/{{ $marketingImage-&gt;mobile_image_name . '.' .
$marketingImage-&gt;mobile_extension . '?'. 'time='. time() }}"&gt;
  &lt;/div&gt;
@endsection</pre><p><strong>ملاحظة</strong>: يمكنك إزالة مساعدات <code>Breadcrumb</code> إذا لم تكن تستخدم تلك الحزمة.</p><p>لم نجعل الواجهة الأمامية فاخرة هنا، قمنا فقط بعمل صفحة بسيطة لإظهار الصور. وبما أننا أرسلنا مثيل <code>marketingImage$</code> إلى المتحكم، فإننا استخدمنا تركيبة blade لاستدعاء اسم الصورة:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">{{ $marketingImage-&gt;image_name }}</pre><p>ثم نقوم بإستدعاء الصور الأولية:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint"> &lt;img src="/imgs/marketing/{{ $marketingImage-&gt;image_name . '.' . $marketingImage-&gt;image_extension .
'?'. 'time='. time() }}"&gt;</pre><p>سترى أننا استخدمنا تركيبة blade <font face="monospace"> </font>طباعة اسم الصورة وامتدادها والتي هي مسجلة في قاعد البيانات، وبإبقاء الامتداد في قاعدة البيانات يمكننا استخدام امتدادات مختلفة بدلا من فرض استخدام jpg. على سبيل المثال.</p><p>سوف تلاحظ أيضا أننا أضفنا:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">'?'. 'time='. time() </pre><p>للحصول على متغير، وهذا الأمر سيمنع عملية تخزين المؤقت للصور نظرا لأنه تم إلحاق الوقت في نهاية الرابط. إن التخزين المؤقت للصور يمكن أن يكون مشكلة بالنسبة لإدارة الصور عندما تقوم برفع الصور.</p><p>وبالطبع هذا الأمر اختياري ويمكنك تجاوزه.</p><p>بقية الشيفرة البرمجية تقريبا نفسها مع بعض التغييرات للصور المصغرة والصور الهواتف. لن تكون الصفحة جميلة جدا، لكنها تقوم بالمهمة.<br>والآن إذا كان لديك صورة قمت برفعها لحفظها في قاعدة البيانات، يمكنك مشاهدتها عن طريق الذهاب إلى:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">yourproject.com/marketingimage/1</pre><p>يمكنك تغيير الرقم في النهاية لأن هذا الرقم هو رقم الصورة في سجل البيانات.</p><p>حسنا، بعد ذلك، قبل أن نعمل على <code>edit</code> و <code>update</code>، لنقم ببناء تابع <code>index</code> في المتحكم ثم عرض (index view).</p><h2>تابع index</h2><p>في <code>MarketingImageController</code>، عدل تابع <code>index</code> كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function index()
{
   $images = Marketingimage::all();
   return view('marketingimage.index', compact('images'));
}</pre><p>يمكنك أن ترى أن الشيفرة سهلة للغاية، فلقد قمنا فقط باسترجاع جميع السجلات إلى كائن <code>images</code><span style="font-family: monospace; line-height: 17.92px;">$</span>، والتي يتم تمريرها إلى العرض view عن طريق تابع <code>compact</code>.</p><h2>عرض Index</h2><p>بعد ذلك، سنقوم بتعديل <code>views/marketingimages/index.blade.php</code> كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@extends('layouts.master')

@section('content')
   {!! Breadcrumb::withLinks(['Home' =&gt; '/', 'marketing images' =&gt; '/marketingimage']) !!}
   &lt;br&gt;
   &lt;div&gt;
     &lt;div class="panel panel-default"&gt;
       &lt;!-- Default panel contents --&gt;
       &lt;div class="panel-heading"&gt;List of Marketing Images &lt;/div&gt;
       &lt;div class="panel-body"&gt;
         &lt;a href="/marketingimage/create"&gt; &lt;button type="button" class="btn btn-lg btn-success"&gt;Create New &lt;/button&gt; &lt;/a&gt;
       &lt;/div&gt;

       &lt;!-- Table --&gt;
       &lt;table class="table"&gt;
         &lt;tr&gt;
           &lt;th&gt;Id &lt;/th&gt;
           &lt;th&gt;Name &lt;/th&gt;
           &lt;th&gt;Thumbnail &lt;/th&gt;
           &lt;th&gt;Edit &lt;/th&gt;
           &lt;th&gt;Delete &lt;/th&gt;
         &lt;/tr&gt;
       @foreach($images as $image )
         &lt;tr&gt;
           &lt;td&gt;{{ $image-&gt;id }}  &lt;/td&gt;
           &lt;td&gt;{{ $image-&gt;image_name }} &lt;/td&gt;
           &lt;td&gt; &lt;a href="/marketingimage/{{ $image-&gt;id  }}"&gt;
             &lt;img src="/imgs/marketing/thumbnails/{{ 'thumb-'. $image-&gt;image_name . '.' .
             $image-&gt;image_extension . '?'. 'time='. time() }}"&gt; &lt;/a&gt; 
           &lt;/td&gt;
           &lt;td&gt;&lt;a href="/marketingimage/{{ $image-&gt;id }}/edit"&gt;
             &lt;span class="glyphicon glyphicon-edit"          
                                 aria-hidden="true"&gt; &lt;/span&gt; &lt;/a&gt; 
           &lt;/td&gt;
           &lt;td&gt;{!! Form::model($image, ['route' =&gt; ['marketingimage.destroy', $image-&gt;id],                                'method' =&gt; 'DELETE']) !!}
                        
            &lt;div class="form-group"&gt;
              {!! Form::submit('Delete', array('class'=&gt;'btn btn-danger', 'Onclick' =&gt; 'return ConfirmDelete();')) !!}

            &lt;/div&gt;
            {!! Form::close() !!} &lt;/td&gt;
          &lt;/tr&gt;
        @endforeach
      &lt;/table&gt;
    &lt;/div&gt;
  &lt;/div&gt;
@endsection

@section('scripts')
    &lt;script&gt;
       function ConfirmDelete()
       {
           var x = confirm("Are you sure you want to delete?");
           if (x)
               return true;
           else
               return false;
       }
    &lt;/script&gt;
@endsection</pre><p>لقد بدأنا بتوسيع <code>layouts.master</code> ومن ثم قمنا بفتح <code>content</code> كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@section('content')</pre><p>ومن ثم استخدمنا Breadcrumb. (مرة أخرى، إذا كنت لا تستخدم الحزمة فاحذف هذا السطر.)</p><p>بعد ذلك قمنا باستخدام شيفرات Bootstrap أساسية، والتي حصلنا عليها من <a rel="external nofollow" href="http://getbootstrap.com/">الموقع الرسمي</a>.</p><p>وفي النهاية سنجد جدول داخل مُكوّن panel لـ bootstrap بالإضافة إلى زر لإنشاء صورة جديدة، وأزرار أخرى للتعديل والحذف لكل صورة، وستظهر الصور المصغرة لكل صورة في الجدول.</p><p>سوف ترى في رأسية مُكوّن panel كيف قمنا بالتعامل مع زر <code>create</code>:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;a href="/marketingimage/create"&gt; 
    &lt;button type="button" class="btn btn-lg btn-success"&gt;
        Create New 
    &lt;/button&gt; 
&lt;/a&gt;</pre><p>كل شيء واضح، فالجدول ليس معقدا، لكنه تطلب حلقة <code>foreach</code> لطباعة جميع الصفوف (rows):</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;!-- Table --&gt;
  &lt;table class="table"&gt;
    &lt;tr&gt;
      &lt;th&gt;Id &lt;/th&gt;
      &lt;th&gt;Name &lt;/th&gt;
      &lt;th&gt;Thumbnail &lt;/th&gt;
      &lt;th&gt;Edit &lt;/th&gt;
      &lt;th&gt;Delete &lt;/th&gt;
    &lt;/tr&gt;

@foreach($images as $image )
  &lt;tr&gt;
    &lt;td&gt;{{ $image-&gt;id }}  &lt;/td&gt;
    &lt;td&gt;{{ $image-&gt;image_name }} &lt;/td&gt;
    &lt;td&gt; &lt;a href="/marketingimage/{{ $image-&gt;id  }}"&gt;
      &lt;img src="/imgs/marketing/thumbnails/{{ 'thumb-'. $image-&gt;image_name . '.' .
        $image-&gt;image_extension . '?'. 'time='. time() }}"&gt; &lt;/a&gt;     
    &lt;/td&gt;
    &lt;td&gt;  &lt;a href="/marketingimage/{{ $image-&gt;id }}/edit"&gt;
       &lt;span class="glyphicon glyphicon-edit" aria-hidden="true"&gt; &lt;/span&gt; &lt;/a&gt; 
    &lt;/td&gt;
    &lt;td&gt;{!! Form::model($image, ['route' =&gt; ['marketingimage.destroy', $image-&gt;id],
                               'method' =&gt; 'DELETE'
                 ]) !!}
     &lt;div class="form-group"&gt;
       {!! Form::submit('Delete', array('class'=&gt;'btn btn-danger', 'Onclick' =&gt; 'return ConfirmDelete();')) !!}

     &lt;/div&gt;
       {!! Form::close() !!} 
    &lt;/td&gt;
  &lt;/tr&gt;
@endforeach
&lt;/table&gt;</pre><p>لا توجد أية صعوبة في الشيفرة، يمكنك أن ترى أنني أضفت مساعدات النموذج form helper حول رابط الحذف <code>delete</code>، وهذا لأسباب أمنية، يجب علينا الحذف باستخدام <code>POST</code> بدل السماح بأن تكون مفتوحة بشكل واسع من خلال استعمال <code>GET</code>.</p><p>سوف تلاحظ أيضا أننا قمنا باستخدام التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">'Onclick' =&gt; 'return ConfirmDelete();'</pre><p>والتي استخدمناها مع الجافاسكربت لفتح صندوق التأكيد confirm box، حتى لا يقوم المستخدمون بحذف شيء عن طريق الخطأ.<br>ثم في <span style="font-family:courier new,courier,monospace;">('section('scripts@</span> أضفنا شيفرات جافاسكربت التالية، وكملاحظة سريعة، افترضنا أنه لديك <span style="font-family: 'courier new', courier, monospace; line-height: 17.92px;">('yeld('scripts@</span> في صفحتك الرئيسية (master page)، وإذا لم يكن لديك هذا السطر، يمكنك ببساطة إرفاق الجافاسكربت قبل <code>endsection@</code> التابعة لـ <span style="font-family: 'courier new', courier, monospace; line-height: 17.92px;">('section('content@</span>.</p><p>هذه هي شيفرة الجافاسكربت:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint"> &lt;script&gt;
   function ConfirmDelete()
   {
       var x = confirm("Are you sure you want to delete?");
       if (x)
           return true;
       else
           return false;
   }
 &lt;/script&gt;</pre><p>شيفرة بسيطة للغاية.</p><p>والآن، يجب أن تحصل على صفحة index تعمل بدون مشاكل، قم بتجربة ذلك عن طريق الذهاب بمتصفحك إلى:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">yourproject.com/marketingimage</pre><p>نُكمل في الجزء الثالث من الدرس إن شاء الله.</p><p>ترجمة -وبتصرّف- للمقال <a rel="external nofollow" href="https://laraveltips.wordpress.com/category/image-management-laravel-5-1-part-2/">Basic Image Management Part 2</a> لصاحبه Bill Keck.</p><p>حقوق الصورة البارزة: <a rel="external nofollow" target="_blank" href="http://www.freepik.com/free-vector/polaroid-photo-frames_769601.htm">Designed by Freepik</a>.</p>
]]></description><guid isPermaLink="false">170</guid><pubDate>Fri, 18 Sep 2015 21:02:00 +0000</pubDate></item><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x635;&#x648;&#x631; &#x641;&#x64A; Laravel - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x623;&#x648;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%81%D9%8A-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r164/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.png.513a9610f14a1756703daf62ac1d5f30.png" /></p>

<p>إدارة الصور هي واحدة من الأشياء التي غالبا ما أجدها صعبة، فأنا معتاد على التعامل مع النماذج وجداول قواعد البيانات، لكن التعامل مع الملفات ليس سهلا بالنسبة لي، فإذا كنت قد بدأت للتو مع Laravel وبدأت تشعر بالصعوبة والضيق، فأنا أشعر بألمك.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.png.547beb5e5abbb439204a8861563b48c7.png"><img data-fileid="4730" class="ipsImage ipsImage_thumbnailed" alt="laravel5-image-management.thumb.png.5c3f" src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-image-management.thumb.png.5c3f96bbe931821ba9f75d1c57cac8f1.png"></a></p><p>لحسن الحظ، أساسيات إدارة الصور في Laravel لن تكون صعبة إذا فهمت بعض الأمور الأساسية.</p><p><strong>ملاحظة</strong>: إذا كنت جديدا في Laravel، فلا أنصحك بالبدء بهذا الدرس، أنصحك بقراءة بعض الدروس والدورات حول Laravel قبل المتابعة.</p><p>سوف تلاحظ أن الدرس طويل لذلك قمت بتقسيمه إلى 3 أجزاء، وسوف تلاحظ أيضا أنني لست بارعا في تصميم الواجهة الأمامية (front-end)، فلذلك فالواجهات التي سنقوم بعملها لن تكون جميلة جدا، يمكنك تزيينها بنفسك لاحقا، فالهدف الأساسي هنا هو تعلم أساسيات إدارة الصور.<br>لذلك على أية حال، ماهي هذه الأساسيات ؟ فكرتُ بالمتطلبات التي قد تحتاجها في تطبيقك وكتبتها في هذه القائمة:</p><ul><li>إنشاء الصور</li><li>تخزين الصور</li><li>تعديل الصور</li><li>تحديث الصور</li><li>إنشاء صور مصغرة</li><li>تعديل صور مصغرة</li><li>إنشاء وتعديل صور الهواتف بشكل منفصل</li></ul><p>بالنسبة للذين اعتادوا على إجراءات المتحكِّمات (controller actions) المريحة، ستظهر الاستمارات عند إجراءات (actions) الإنشاء <code>create</code> والتعديل <code>edit</code> وأما إجراءات التخزين store والتحديث update فوظيفتهم إنشاء وتعديل السجلات والملفات.<br>سنتعامل مع شيئين مهمين عند تعاملنا مع الصور، الشيء الأول هو النموذج الذي يعمل على البيانات مثل اسم الصورة و مسارها، وأما الشيء الثاني فهو ملف الصورة نفسه الذي سوف يتم تخزينه في مجلد الذي سنقوم بإسناده له.</p><h2>تثبيت Intervention</h2><p>سوف نبدأ بتثبيت حزمة <code>Intervention/image</code>، فإذا لم تقُم بذلك، عدل على ملف <code>composer.json</code> وأضف التعليمة التالية في جزء الاستدعاء (require) :</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">"intervention/image": "~2.2"</pre><p>ثم أضف السطر التالي ضمن مصفوفة Providers في ملف <code>app\config\app.php</code> (انتبه للفواصل) :</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">Intervention\Image\ImageServiceProvider::class,</pre><p>في نفس الملف أضف السطرين التاليين لمصفوفة Aliases:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">Intervention\Image\ImageServiceProvider::class,</pre><p>أنصحك بالإطلاع على <a rel="external nofollow" href="http://image.intervention.io/getting_started/installation#laravel">صفحة Intervention</a> للتأكد من الإصدار الأخير للحزمة.<br>في آخر مرة تأكدتُ فيها،كانت تعليمات التَدَخّل تستخدم النمط القديم للإشارة إلى المرجع:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">'Intervention\Image\ImageServiceProvider'</pre><p>يمكنك أن تلاحظ في الأعلى أننا في كلتا الحالتين استخدمنا <code>::class</code> والتي هي ممارسة جيدة تعلمتها من Laracasts.com، فإذا كنت تستخدم على سبيل المثال PHP Storm، فسيكون باستطاعتك الوصول إلى الفئة class الأساسية.</p><p>إن حزمة Intervention تقوم بإعطائنا صياغة (syntax) وطريقة سهلة لصناعة الصور المصغرة بالإضافة إلى الكثير من التوابع (method) الأخرى الرائعة، لذلك سوف نستخدمها في هذا الدرس، ولمزيد من المعلومات حول هذه الحزمة أنصحك بالإطلاع على التوثيق الرسمي.</p><p>لاحظ أيضا أننا سنقوم باستخدام حزمة <code>laravelcollective/html</code> وحزمة <code>patricktalmadge/bootstrapper</code>، ولذلك قم بتثبيتهم قبل أن تتابع الدرس.</p><h2>إنشاء نموذج</h2><p>سوف نبدأ بإنشاء نموذج <code>Marketingimage</code>، يمكننا فعل ذلك عن طريق artisan من سطر الأوامر بكتابة السطر التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">php artisan make:model Marketingimage -m</pre><p>سوف تلاحظ علم <strong><code>m-</code></strong> الذي سيخبر Laravel أنك تريد إنشاء تهجير migration في نفس الوقت، لذلك فهذه الميزة مفيدة للغاية.</p><p>حسنا، قم بتنفيذ الأمر السابق وستحصل على ملف النموذج والمسمى <code>Marketingimage.php</code> مباشرة تحت دليل تطبيقك وستحصل أيضا على ملف التهجير في مجلد <code>database/migrations</code>. دعونا نقوم بتعديل التابع في أعلى ملف التهجير إلى ما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function up()
{
    Schema::create('marketing_images', function(Blueprint $table)
    {
        $table-&gt;increments('id');
        $table-&gt;boolean('is_active')-&gt;default(false);
        $table-&gt;boolean('is_featured')-&gt;default(false);
        $table-&gt;string('image_name')-&gt;unique();
        $table-&gt;string('image_path');
        $table-&gt;string('image_extension', 10);
        $table-&gt;string('mobile_image_name')-&gt;unique();
        $table-&gt;string('mobile_image_path');
        $table-&gt;string('mobile_extension', 10);
        $table-&gt;timestamps();
    });
}</pre><p>أول شيئ يمكنك رؤيته أنني قد غيرت اسم الجدول، فأنا افضل فصل الكلمات في جدول الأسماء بسطر سفلي underscore. أنت حر في اختيار الطريقة التي تعجبك، لكن يجب أن نختار صيغة الجمع لإتباع قواعد Laravel بشكل صحيح. ففي Laravel، النموذج يكتب بصيغة المفرد وأما اسم الجدول فيكتب بصيغة الجمع.</p><p>بعد عمود المعرف الرقمي، قمنا باستخدام عمودين من نوع المنطقي boolean والتي سوف تسمح لنا بمعرفة هل الصورة نشطة أو مميزة، هذه القيود المفيدة سوف تساعد على العمل مع الصور في وقت لاحق.<br>ثم قمنا بإضافة أعمدة الاسم، المسار والامتدادات للصور وصور الهاتف، وهذا سيسمح لنا بالمرونة الكافية إذا أردت حفظ صورة مختلفة للهاتف، وهذا الأمر ضروري لأن تغيير حجم الصورة قد لا ينتج لنا النتائج المرجوة.</p><p>وبما أننا سوف نقوم بإنشاء صور مصغرة من الصور الأصلية، لن نحتاج إلى حفظ أية بيانات لذلك.</p><p>عن طريق حفظ مسار وإمتداد الصورة، سيكون لدينا مرجع سهل نستطيع استخدامه لإظهار الصورة في تطبيقنا، بالإضافة إدارة الصورة في قائمة الصور.</p><p>عدل على التابع ليبدو على النحو التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function down()
{
   Schema::drop('marketing_images');
}</pre><p>بمجرد أن تقوم بذلك، قم بتنفيذ أمر <code>php artisan migrate</code> من سطر الأوامر وتأكد من أن الجدول قد تم إنشاءه.</p><p>بعد هذا، سوف نقوم بتعديل نموذج <code>Marketingimage</code> كما يلي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint"> &lt;?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Marketingimage extends Model
{
    protected $table = 'marketing_images';

    protected $fillable = ['is_active',
                                     'is_featured',
                                    'image_name',
                                    'image_path',
                                    'image_extension',
                                    'mobile_image_name',
                                    'mobile_image_path',
                                    'mobile_extension'
    ];
}</pre><p>سوف تلاحظ أننا قمنا بإخبار النموذج الجدول الذي سيتخذه كمرجع، بالإضافة إلى توفير أعمدة مملوءة تلقائيا، حتى لا نواجه مشكلة الإحالة الكتلية mass-assignment.</p><h2>المتحكم</h2><p>جيد، نحن الآن مستعدين للاستمرار للخطوة القادمة، سنقوم بإنشاء المتحكِّم بإستخدام artisan:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">php artisan make:controller MarketingImageController</pre><p>وبهذا سوف تحصل على متحكِّم في <code>app/Http/Controllers</code> مع التوابع التالية:</p><ul><li>index</li><li>create</li><li>store</li><li>show</li><li>edit</li><li>update</li><li>destroy</li></ul><p>وسوف نستخدم جميع هذه التوابع.<br>وكنصيحة مفيدة للمبتدئين، قُم بوضع السطر التالي في تابع <code>index</code>:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">return 'Here is the index method.';</pre><p>فهذا سوف يعطيك فرصة لتجربة هذا الطريق route. (يستطيع بقية المبرمجين المحترفين تجاوز هذه الخطوة إذا أرادوا)<br>وبعد ذلك، سنقوم بتثبيت الطرق routes. عدل على ملف <code>app/Http/routes.php</code> وأضف التعليمة التالية:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">Route::resource('marketingimage', 'MarketingImageController');</pre><p>سوف ترى أننا قد قمنا بإضافة مورد resource، والذي سوف يقوم بإعطائنا الطرق routes لجميع الإجراءات actions بطريقة مريحة للغاية.<br>حسنا، سوف تستطيع الآن الذهاب إلى yourproject.com/marketingimage وسوف تحصل على النتيجة التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">Here is the index method.</pre><p>الخطوة المنطقية التالية هي إعداد العروض views، أنشئ مجلدا باسم <code>marketingimage</code> أسفل <code>resources/views</code>، ثم أنشئ الملفات الفارغة التالية داخل مجلد <code>marketingimages</code>:</p><ul><li>create.blade.php</li><li>edit.blade.php</li><li>index.blade.php</li><li>show.blade.php</li></ul><h2>إعداد المجلدات</h2><p>سوف نعود إلى تلك الملفات في وقت لاحق، في الوقت الحالي، سنقوم بإنشاء مكان لتخزين صورنا الحالية، سوف أجعل هذا الأمر سهلا، أنشئ مجلدا باسم <code>imgs</code> مباشرة تحت مجلدك العام (public folder)، وبداخل مجلد <code>imgs</code>، أنشئ مجلد <code>marketing</code>، وبداخله أنشئ مجلدا باسم <code>mobile</code> وآخر بإسم <code>thumbnails</code>.<br>الآن قمنا بإنشاء جميع المجلدات للصور.</p><h2>عرض الإنشاء The Create View</h2><p>حسنا، دعونا الآن نتعامل مع عرض الإنشاء The Create View. أضف الأسطر التالية داخل ملف `create.blade.php`:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint"> @extends('layouts.master')
    
    @section('content')
    
        {!! Breadcrumb::withLinks(['Home' =&gt; '/', 'marketing images' =&gt; '/marketingimage', 'create']) !!}
    
         &lt;h1&gt;Upload a Photo &lt;/h1&gt;
    
    
         &lt;hr/&gt;
    
         @if (count($errors) &gt; 0)
    	 &lt;div class="alert alert-danger"&gt;
    	 &lt;strong&gt;Whoops! &lt;/strong&gt; There were some problems with your input. &lt;br&gt; &lt;br&gt;
    	 &lt;ul&gt;
    	     @foreach ($errors-&gt;all() as $error)
    		 &lt;li&gt;{{ $error }} &lt;/li&gt;
    	     @endforeach
    
             &lt;/ul&gt;
             &lt;/div&gt;
    
        @endif
    
    
        {!! Form::open(array('route' =&gt; 'marketingimage.store', 'class' =&gt; 'form', 'files' =&gt; true)) !!}
    
         &lt;!-- image name Form Input --&gt;
         &lt;div class="form-group"&gt;
            {!! Form::label('image name', 'Image name:') !!}
            {!! Form::text('image_name', null, ['class' =&gt; 'form-control']) !!}
         &lt;/div&gt;
    
    
         &lt;!-- mobile_image_name Form Input --&gt;
         &lt;div class="form-group"&gt;
            {!! Form::label('mobile_image_name', 'Mobile Image Name:') !!}
            {!! Form::text('mobile_image_name', null, ['class' =&gt; 'form-control']) !!}
         &lt;/div&gt;
    
    
         &lt;!-- is_something Form Input --&gt;
         &lt;div class="form-group"&gt;
            {!! Form::label('is_active', 'Is Active:') !!}
            {!! Form::checkbox('is_active') !!}
         &lt;/div&gt;
    
         &lt;!-- is_featured Form Input --&gt;
         &lt;div class="form-group"&gt;
            {!! Form::label('is_featured', 'Is Featured:') !!}
            {!! Form::checkbox('is_featured') !!}
         &lt;/div&gt;
    
        &lt;!-- form field for file --&gt;
        &lt;div class="form-group"&gt;
           {!! Form::label('image', 'Primary Image') !!}
           {!! Form::file('image', null, array('required', 'class'=&gt;'form-control')) !!}
        &lt;/div&gt;
    
         &lt;!-- form field for file --&gt;
         &lt;div class="form-group"&gt;
            {!! Form::label('mobile_image', 'Mobile Image') !!}
            {!! Form::file('mobile_image', null, array('required', 'class'=&gt;'form-control')) !!}
         &lt;/div&gt;
    
         &lt;div class="form-group"&gt;
    
            {!! Form::submit('Upload Photo', array('class'=&gt;'btn btn-primary')) !!}
    
         &lt;/div&gt;
    
        {!! Form::close() !!}
    
    @endsection</pre><p>لاحظ أن الشيفرة في الأعلى ليست صعبة ويمكنك فهمها بسهولة دون أن تضطر إلى قراءة الشرح، ولاحظ أيضا أننا نقوم بتوسيع صفحتنا الرئيسية master page، التي بداخلها مجلد المخططات في مجلد العروض. والتي قمنا باستدعائها عن طريق هذه التعليمة:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">@extends('layouts.master')</pre><p>إذا كانت لديك صفحة رئيسية أخرى أو أنها موجودة في مكان مختلف، قم بتعديل ذلك حسب الحاجة، وإذا كنت لا تعرف مفهوم الصفحة الرئيسية master page، قُم بالبحث عن دروس حوله وتعلمه قبل أن تتابع الدرس.<br>إذا كنت لا تستخدم حزمة `Bootstrapper`، قم بحذف السطر التالي:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">{!! Breadcrumb::withLinks(['Home' =&gt; '/', 'marketing images' =&gt; '/marketingimage', 'create']) !!}</pre><p>لاحظ أيضا، لهذا الدرس، قمت بتضمين `if` لطباعة أخطاء الإدخال، لكن في العادة، يجب وضع هذا الجزء في جزئية العرض view partial ومن ثم الإشارة إليه بشيء مثل هذا:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">@include('errors.errors')</pre><p>يمكنك أيضا ملاحظة أننا نستخدم مساعد الاستمارة Form helper من حزمة `laravelcollective/html`، فلقد وجدت أن مساعد الاستمارة مفيد جدا خاصة عند استخدامه لفتح الاستمارة:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">{!! Form::open(array('route' =&gt; 'marketingimage.store', 'class' =&gt; 'form', 'files' =&gt; true)) !!}</pre><p>تستطيع أن ترى أننا قمنا بتضمين <strong><span style="font-family:courier new,courier,monospace;">'files =&gt; 'true</span></strong> والتي تسمح لنا برفع ملفات متعددة.<br>إذا كنت جديدا في استخدام مساعد الاستمارة، فيمكنك ملاحظة أننا لا نحتاج إلى استخدام POST خاصة وأننا لا نحتاج إلى استدعاء رمز CSFR لأنه يتم ذلك تلقائيا.<br>ثم لدينا مدخلات المختلفة للاستمارة، لا شيء مجنون للغاية هنا، ولدينا أيضا `Form::submit` والتي نستخدمها كزر، بالإضافة إلى `Form::close()`.<br>يمكنك أن ترى من مساعد الاستمارة أن الطريق route تم تعيينه إلى `marketingimage.store`، لذلك سوف نعرف من مورد الطريق في `routes.php` أن هذا سوف يأخذنا إلى تابع `store` في `MarketingImageController.php` والذي هو دليل المتحكِّمات.</p><p>نُكمل في الجزء الثاني من الدرس.</p><p>ترجمة -وبتصرّف- للمقال <a rel="external nofollow" href="https://laraveltips.wordpress.com/category/image-management-in-laravel-5-1/">Basic Image Management Part 1</a> لصاحبه Bill Keck.</p><p>حقوق الصورة البارزة: <a rel="external nofollow" href="http://www.freepik.com/free-vector/polaroid-photo-frames_769601.htm">Designed by Freepik</a>.</p>
]]></description><guid isPermaLink="false">164</guid><pubDate>Sat, 12 Sep 2015 22:37:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642; &#x642;&#x627;&#x626;&#x645;&#x629; &#x645;&#x647;&#x627;&#x645; &#x628;&#x633;&#x64A;&#x637; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Laravel 5 - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x631;&#x627;&#x628;&#x639;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%82%D8%A7%D8%A6%D9%85%D8%A9-%D9%85%D9%87%D8%A7%D9%85-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B9-r162/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.png.91810aae3aa781b73f5384c235c2456c.png" /></p>

<p>حتى الآن تعلمنا <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r149/">كيفية تثبيت وإعداد Laravel</a>، بالإضافة إلى <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r157/">إعداد بعض المشاريع والمهام والموارد المضمّنة</a> و عرضهم على المستخدم، كما أنشأنا <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-r158/">وظائف الإنشاء والتعديل والحذف</a>، وفي هذا الفصل سوف نختم الدرس عن طريق إضافة استمارة التحقق.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.png.d05c813ed2fa77f14964b46eacfd9fc5.png"><img data-fileid="4502" class="ipsImage ipsImage_thumbnailed" alt="laravel5-todo-app.thumb.png.57f28dff002b" src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.thumb.png.57f28dff002b5c24d5a777ced3aa4c12.png"></a></p><h2>استمارة التحقق من جانب الخادم</h2><p>على الرغم من أن استمارات الإنشاء والتعديل تعمل إلا أننا لم نقم بالتحقق من ما يتم إدخاله، وهذا ما سنقوم بعمله اليوم.<br>هنالك طرق متعددة للتعامل مع استمارة التحقق، بعضها أفضل من الآخر، ولهذا التطبيق الصغير نقترح أن نستخدم وظيفة المتحكِّمات <strong><span style="font-family:courier new,courier,monospace;">()validate</span></strong> مع كائن <strong><span style="font-family:courier new,courier,monospace;">Illuminate\Http\Request</span></strong> مثل هذا، في ملف <strong><span style="font-family:courier new,courier,monospace;">app/Http/Controllers/ProjectsController.php/</span></strong>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">// /app/Http/Controllers/ProjectsController.php
     
use Illuminate\Http\Request;
     
class ProjectsController extends Controller {
     
    protected $rules = [		'name' =&gt; ['required', 'min:3'],		'slug' =&gt; ['required'],	]; 
    /**
    * Store a newly created resource in storage.
    *
    * @param \Illuminate\Http\Request $request	 * @return Response
    */


    public function store(Request $request)
    {
    	$this-&gt;validate($request, $this-&gt;rules); 
    	$input = Input::all();
    	Project::create( $input );
     
    	return Redirect::route('projects.index')-&gt;with('message', 'Project created');
    }
     
    /**
    * Update the specified resource in storage.
    *
    * @param  \App\Project $project
    * @param \Illuminate\Http\Request $request	 * @return Response
    */
    public function update(Project $project, Request $request)
    {
    	$this-&gt;validate($request, $this-&gt;rules); 
    	$input = array_except(Input::all(), '_method');
    	$project-&gt;update($input);
     
    	return Redirect::route('projects.show', $project-&gt;slug)-&gt;with('message', 'Project updated.');
    }</pre><p>وأما في ملف <strong><span style="font-family:courier new,courier,monospace;">app/Http/Controllers/TasksController.php/</span></strong>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">// /app/Http/Controllers/TasksController.php
use Illuminate\Http\Request;
     
class TasksController extends Controller {
     
    protected $rules = ['name'        =&gt; ['required', 'min:3'],
                        'slug'        =&gt; ['required'],	
                        'description' =&gt; ['required'],
                       ]; 

   	/**
    * Store a newly created resource in storage.
    *
    * @param  \App\Project $project
    * @param \Illuminate\Http\Request $request	 * @return Response
    */
    public function store(Project $project, Request $request)
    {
    	$this-&gt;validate($request, $this-&gt;rules); 
    	$input = Input::all();
    	$input['project_id'] = $project-&gt;id;
    	Task::create( $input );
     
    	return Redirect::route('projects.show', $project-&gt;slug)-&gt;with('Task created.');
    }
     
    /**
    * Update the specified resource in storage.
    *
    * @param  \App\Project $project
    * @param  \App\Task    $task
    * @param \Illuminate\Http\Request $request	 * @return Response
    */
    public function update(Project $project, Task $task, Request $request)
    {
    	$this-&gt;validate($request, $this-&gt;rules); 
    	$input = array_except(Input::all(), '_method');
    	$task-&gt;update($input);
     
    	return Redirect::route('projects.tasks.show', 
                               [$project-&gt;slug, $task-&gt;slug])-&gt;with('message', 'Task updated.');
    }</pre><p>سوف نحتاج أيضا إلى مكان لعرض أية أخطاء، لذلك قُم بفتح  <strong><span style="font-family:courier new,courier,monospace;">resources/views/app.blade.php/</span></strong> وأضف السطور التالية أسفل <strong><span style="font-family:courier new,courier,monospace;">('yield('content@</span></strong>:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">&lt;div class="content"&gt;
    @if (Session::has('message'))
    	&lt;div class="flash alert-info"&gt;
    		&lt;p&gt;{{ Session::get('message') }}&lt;/p&gt;
    	&lt;/div&gt;
    @endif

    @if ($errors-&gt;any())		
        &lt;div class='flash alert-danger'&gt;
     		@foreach ( $errors-&gt;all() as $error )				
                &lt;p&gt;{{ $error }}&lt;/p&gt;			
            @endforeach		
        &lt;/div&gt;	
    @endif 

   @yield('content')
&lt;/div&gt;</pre><p>إذا أردت قائمة كاملة من قواعد التحقق، أنصحك بزيارة <a rel="external nofollow" href="http://laravel.com/docs/5.0/validation#available-validation-rules">التوثيق الرسمي</a>.<br>من المفترض أن يعمل كل شيء الآن، وإذا كان عكس ذلك، فسوف تقوم <strong><span style="font-family:courier new,courier,monospace;">()this-&gt;validate$</span></strong> بتوجيهك إلى الصفحة الحالية مع الأخطاء التي سوف تظهر على الصفحة.</p><h2>خاتمة</h2><p>لقد قمنا في هذه الدورة بتعلم الكثير من الأشياء حول Laravel، مثل كيفية تثبيت وإعداد Laravel 5 بالإضافة إلى بعض المفاهيم المتقدمة مثل الربط بين الطريق والنموذج route model binding والحماية من CSRF، وعلى الرغم من بساطة التطبيق الذي قمنا به إلا أنه بداية جيدة لكل من يريد احتراف Laravel.</p><p>ترجمة -وبتصرّف- للمقال <a rel="external nofollow" href="https://www.flynsarmy.com/2015/02/creating-a-basic-todo-application-in-laravel-5-part-4/">Creating a Basic ToDo Application in Laravel 5 – Part 4</a>.</p><p>حقوق الصورة البارزة: <a rel="external nofollow" target="_blank" href="http://www.freepik.com/free-vector/checking-task-list-by-hand_760718.htm">Designed by Freepik</a>.</p>
]]></description><guid isPermaLink="false">162</guid><pubDate>Sun, 06 Sep 2015 18:21:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642; Todo List &#x628;&#x633;&#x64A;&#x637; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Laravel 5 - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x644;&#x62B;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-r158/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.png.aec1b1e8e2dc7af4ed9ff88476d201d9.png" /></p>

<p>حتى الآن تعلمنا كيفية <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r149/">تثبيت وإعداد Laravel</a>، بالإضافة إلى أننا قمنا بـ<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r157/">إعداد بعض موارد المشاريع والمهام وعرضهم للمستخدم</a>. في هذا الدرس، سنتعلم كيفية إنشاء وتعديل وحذف الصفحات والإجراءات.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.png.897ee3b4b5b610c29b4a53c23a049cdd.png"><img data-fileid="4474" class="ipsImage ipsImage_thumbnailed" alt="laravel5-todo-app.thumb.png.d151d8c381e3" src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.thumb.png.d151d8c381e3320218f56ba34ba33a5a.png"></a></p><h2>إضافة روابط التصفح</h2><p>قبل أن نفعل أي شيء، سنقوم بإضافة روابط create/edit/delete/back إلى صفحات المشاريع والمهام:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;!-- /resources/views/projects/index.blade.php --&gt;
@extends('app')

@section('content')
    &lt;h2&gt;Projects&lt;/h2&gt;

    @if ( !$projects-&gt;count() )
        You have no projects
    @else
        &lt;ul&gt;
            @foreach( $projects as $project )
                &lt;li&gt;
                    {!! Form::open(array('class' =&gt; 'form-inline', 'method' =&gt; 'DELETE', 'route' =&gt; array('projects.destroy', $project-&gt;slug))) !!}
                        &lt;a href="{{ route('projects.show', $project-&gt;slug) }}"&gt;{{ $project-&gt;name }}&lt;/a&gt;
                        (
                            {!! link_to_route('projects.edit', 'Edit', array($project-&gt;slug), array('class' =&gt; 'btn btn-info')) !!},
                            {!! Form::submit('Delete', array('class' =&gt; 'btn btn-danger')) !!}
                        )
                    {!! Form::close() !!}
                &lt;/li&gt;
            @endforeach
        &lt;/ul&gt;
    @endif

    &lt;p&gt;
        {!! link_to_route('projects.create', 'Create Project') !!}
    &lt;/p&gt;
@endsection

&lt;!-- /resources/views/projects/show.blade.php --&gt;
@extends('app')

@section('content')
    &lt;h2&gt;{{ $project-&gt;name }}&lt;/h2&gt;

    @if ( !$project-&gt;tasks-&gt;count() )
        Your project has no tasks.
    @else
        &lt;ul&gt;
            @foreach( $project-&gt;tasks as $task )
                &lt;li&gt;
                    {!! Form::open(array('class' =&gt; 'form-inline', 'method' =&gt; 'DELETE', 'route' =&gt; array('projects.tasks.destroy', $project-&gt;slug, $task-&gt;slug))) !!}
                        &lt;a href="{{ route('projects.tasks.show', [$project-&gt;slug, $task-&gt;slug]) }}"&gt;{{ $task-&gt;name }}&lt;/a&gt;
                        (
                            {!! link_to_route('projects.tasks.edit', 'Edit', array($project-&gt;slug, $task-&gt;slug), array('class' =&gt; 'btn btn-info')) !!},

                            {!! Form::submit('Delete', array('class' =&gt; 'btn btn-danger')) !!}
                        )
                    {!! Form::close() !!}
                &lt;/li&gt;
            @endforeach
        &lt;/ul&gt;
    @endif

    &lt;p&gt;
        {!! link_to_route('projects.index', 'Back to Projects') !!} |
        {!! link_to_route('projects.tasks.create', 'Create Task', $project-&gt;slug) !!}
    &lt;/p&gt;
@endsection</pre><p>هذه الشفرة البرمجية مفهومة، الصعوبة تكمن في رابط الحذف، متحكِّمات الموارد تتطلب إرسال وظيفة HTTP DELETE، وهذا لا يمكن أن يتم مع رابط عادي، لذلك يتطلب نموذج يتم تقديمه إلى طريق route محدد. للمزيد من المعلومات قُم بزيارة <a rel="external nofollow" href="http://laravel.com/docs/controllers#resource-controllers">إجراءات يتم التحكم بها عن طريق متحكِّمات الموارد</a>.</p><h2>إنشاء صفحات الإضافة والتعديل</h2><p>بعد الانتهاء من صفحات عرض قائمة المشاريع، نحتاج إلى إمكانية إضافة وحذف المشاريع والمهام. استمارات الإضافة والحذف ستكون متشابهة كثيرا، لذلك بدلا من تكرارهم، سنقوم بوراثتهم من نموذج واحد.</p><p>سوف نبدأ مع عروض create/edit للمشروع:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;!-- /resources/views/projects/create.blade.php --&gt;
@extends('app')

@section('content')
    &lt;h2&gt;Create Project&lt;/h2&gt;

    {!! Form::model(new App\Project, ['route' =&gt; ['projects.store']]) !!}
        @include('projects/partials/_form', ['submit_text' =&gt; 'Create Project'])
    {!! Form::close() !!}
@endsection

&lt;!-- /resources/views/projects/edit.blade.php --&gt;
@extends('app')

@section('content')
    &lt;h2&gt;Edit Project&lt;/h2&gt;

    {!! Form::model($project, ['method' =&gt; 'PATCH', 'route' =&gt; ['projects.update', $project-&gt;slug]]) !!}
        @include('projects/partials/_form', ['submit_text' =&gt; 'Edit Project'])
    {!! Form::close() !!}
@endsection</pre><p>قُم بعمل نفس الشيء مع المهام لكن لا تنسَ تحديث الطرق (routes):</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;!-- /resources/views/tasks/create.blade.php --&gt;
@extends('app')

@section('content')
    &lt;h2&gt;Create Task for Project "{{ $project-&gt;name }}"&lt;/h2&gt;

    {!! Form::model(new App\Task, ['route' =&gt; ['projects.tasks.store', $project-&gt;slug], 'class'=&gt;'']) !!}
        @include('tasks/partials/_form', ['submit_text' =&gt; 'Create Task'])
    {!! Form::close() !!}
@endsection

&lt;!-- /resources/views/tasks/edit.blade.php --&gt;
@extends('app')

@section('content')
    &lt;h2&gt;Edit Task "{{ $task-&gt;name }}"&lt;/h2&gt;

    {!! Form::model($task, ['method' =&gt; 'PATCH', 'route' =&gt; ['projects.tasks.update', $project-&gt;slug, $task-&gt;slug]]) !!}
        @include('tasks/partials/_form', ['submit_text' =&gt; 'Edit Task'])
    {!! Form::close() !!}
@endsection</pre><p>الآن توجد عدة مفاهيم جديدة:</p><h3>إضافة جزئية</h3><p>الاستمارة تتطلب عدة وسوم، <span style="line-height: 1.6;">وبدلا من ذلك سنقوم بتقسيمها من جزئية _form ونضعها مباشرة في العرض، استمارة Add هي من نوع POST ترسل البيانات إلى طريق <strong><span style="font-family:courier new,courier,monospace;">projects.store</span></strong> واستمارة Edit هي من نوع PATCH وترسل البيانات إلى <strong><span style="font-family:courier new,courier,monospace;">projects.update</span></strong>. قد يبدوا هذا معقدا ومبهم لكن هذه هي الطريقة التي تعمل بها المتحكِّمات.</span></p><form>لاحظ أننا استخدمنا <strong><span style="font-family:courier new,courier,monospace;">()Form::model</span></strong>، وتسمى هذه <a rel="external nofollow" href="http://laravel.com/docs/html#form-model-binding">نموذج الاستمارة الملزمة</a> و ليس لدى هذه أهمية كبيرة الآن، فهي تُستخدم للتعبئة التلقائية وسوف نحتاجها في وقت لاحقا عندما نضيف الحقول باستخدام <strong><span style="font-family:courier new,courier,monospace;">()Form::input</span></strong>.<h3>الحماية من CSRF:</h3><p>مساعدي الاستمارة (Form helpers) توفر العديد من الوظائف مجانا، فإذا ذهبت إلى <span style="font-family:courier new,courier,monospace;">projects/create/</span> ورأيت مصدر الصفحة ستجد شيئا مشابها لهذا:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&lt;form method="POST" action="http://l4todo.localhost.com/projects" accept-charset="UTF-8"&gt;
    &lt;input name="_token" type="hidden" value="Y8uOo7SeD5tQZExezDf5a7UwiYR4P6qIHEUKJNxI"&gt;
&lt;/form&gt;</pre><p>هل ترى حقل <strong><span style="font-family:courier new,courier,monospace;">token_</span></strong> ؟ هذا هو الرمز المميز لـ CSRF مُنشئ تِلقائيا بواسطة استدعاء <strong><span style="font-family:courier new,courier,monospace;">{{ ()Form::model }}</span></strong> الذي يمنع ثغرة CSRF. يكفي أن نقول أن هذا شيئ مفيد وأننا لم نقم بأي شيئ للحصول عليه.</p><h2>إنشاء استمارة التعديل</h2><p>نحن بحاجة إلى ترميز (markup) الاستمارة للمشاريع والمهام، وبفضل نموذج الاستمارة الملزمة يمكننا فقط استخدام <a rel="external nofollow" href="http://laravel.com/docs/html#text">مساعدي الاستمارة</a> في Laravel لإخراج كافة الحقول التي نحتاجها.</p><pre data-pbcklang="html" data-pbcktabsize="" class="html ipsCode prettyprint">&lt;!-- /resources/views/projects/partials/_form.blade.php --&gt;
&lt;div class="form-group"&gt;
    {!! Form::label('name', 'Name:') !!}
    {!! Form::text('name') !!}
&lt;/div&gt;
&lt;div class="form-group"&gt;
    {!! Form::label('slug', 'Slug:') !!}
    {!! Form::text('slug') !!}
&lt;/div&gt;
&lt;div class="form-group"&gt;
    {!! Form::submit($submit_text, ['class'=&gt;'btn primary']) !!}
&lt;/div&gt;


&lt;!-- /resources/views/tasks/partials/_form.blade.php --&gt;
&lt;div class="form-group"&gt;
    {!! Form::label('name', 'Name:') !!}
    {!! Form::text('name') !!}
&lt;/div&gt;

&lt;div class="form-group"&gt;
    {!! Form::label('slug', 'Slug:') !!}
    {!! Form::text('slug') !!}
&lt;/div&gt;

&lt;div class="form-group"&gt;
    {!! Form::label('completed', 'Completed:') !!}
    {!! Form::checkbox('completed') !!}
&lt;/div&gt;

&lt;div class="form-group"&gt;
    {!! Form::label('description', 'Description:') !!}
    {!! Form::textarea('description') !!}
&lt;/div&gt;

&lt;div class="form-group"&gt;
    {!! Form::submit($submit_text) !!}
&lt;/div&gt;</pre><p>هذا كل شيئ، سوف تستطيع الأن التصفح في صفحات الإضافة والتعديل، الأمر كان سهلا للغاية.</p><h2>جعل الاستمارات تعمل</h2><p>لدينا استمارات الإضافة والتعديل للمشروع و المهام، بالإضافة إلى استمارة مُضللة لحذفهم، الآن يجب علينا أن نجعلهم يعملون لأداء مهامهم.</p><p>أولا، أضف هذا في أعلى المتحكِّمات:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">use Input;
use Redirect;</pre><p>والآن لوظائف store و update و destroy:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">// ProjectsController
public function store()
{
    $input = Input::all();
    Project::create( $input );

    return Redirect::route('projects.index')
                          -&gt;with('message', 'Project created');
}

public function update(Project $project)
{
    $input = array_except(Input::all(), '_method');
    $project-&gt;update($input);

    return Redirect::route('projects.show', $project-&gt;slug)
                          -&gt;with('message', 'Project updated.');
}

public function destroy(Project $project)
{
    $project-&gt;delete();

    return Redirect::route('projects.index')-&gt;with('message', 'Project deleted.');
}

// TasksController
public function store(Project $project)
{
    $input = Input::all();
    $input['project_id'] = $project-&gt;id;
    Task::create( $input );

    return Redirect::route('projects.show', $project-&gt;slug)
                          -&gt;with('message', 'Task created.');
}

public function update(Project $project, Task $task)
{
    $input = array_except(Input::all(), '_method');
    $task-&gt;update($input);

    return Redirect::route('projects.tasks.show', [$project-&gt;slug, $task-&gt;slug])
                          -&gt;with('message', 'Task updated.');
}

public function destroy(Project $project, Task $task)
{
    $task-&gt;delete();

    return Redirect::route('projects.show', $project-&gt;slug)-&gt;with('message', 'Task deleted.');
}</pre><p>الشفرة البرمجية في الأعلى مفهومة ولا داعي لشرحها.<br>إذا قمت الآن بتقديم إحدى الاستمارات فسوف تحصل على خطأ MassAssignmentException: _token، <a rel="external nofollow" href="http://laravel.com/docs/eloquent#mass-assignment">فالإحالة الكتلية</a> تحدث عندما تقوم بتمرير مصفوفة بيانات إلى <strong><span style="font-family:courier new,courier,monospace;">()Model::create</span></strong> أو <strong><span style="font-family:courier new,courier,monospace;">()Model::update</span></strong> من المتحكِّمات بدل من وضع حقل واحد في نفس الوقت، ولإصلاح هذا، قم ببساطة بإضافة خاصية guarded إلى كل نموذج.</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">class Project extends Model {

    protected $guarded = [];


class Task extends Model {

    protected $guarded = [];</pre><h3>رسائل الفلاش</h3><p>سوف تلاحظ من الشفرة السابقة أننا استخدمنا دالة<span style="font-family:courier new,courier,monospace;"> <strong>()with</strong></span>، وهذه الدالة تقوم بتمرير متغير فلاش (يستخدم لمرة واحدة) للجلسة session والتي يمكن قراءتها عند تحميل الصفحة التالية.<br>والآن نحتاج إلى التأكد من تلك الرسالة وعرضها على المستخدم. قُم بفتح <span style="font-family:courier new,courier,monospace;">resources/views/app.blade.php/</span> وأضف التالي:</p><pre data-pbcklang="html" data-pbcktabsize="" class="html ipsCode prettyprint">...

&lt;div class="content"&gt;
    @if (Session::has('message'))       
       &lt;div class="flash alert-info"&gt;          
         &lt;p&gt;{{ Session::get('message') }}&lt;/p&gt;        
       &lt;/div&gt;  
    @endif 
    
    @yield('content')
&lt;/div&gt;

...</pre><p>حاول إنشاء مشروع، هذه الرسالة ستظهر مهما حدّثت الصفحة وستذهب بعد فترة.</p><h2>خاتمة</h2><p>اليوم قمنا بأشياء مثيرة للغاية، فلقد أضفنا استمارات الإضافة والتعديل والحذف وتعلمنا حول CSRF و نموذج الاستمارة الملزمة بالإضافة إلى تعلمنا المزيد حول blade و الدوال.<br>كل شيئ الآن يعمل، يمكن تجربة التطبيق وإنشاء وتعديل وحذف المهام والمشاريع، وفي أي وقت يمكنك كتابة الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">php artisan migrate:refresh –seed </pre><p>وسوف يتم إعادة تعيين قواعد البيانات.<br>في المرحلة القادمة والتي ستكون النهائية سوف نقوم <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%82%D8%A7%D8%A6%D9%85%D8%A9-%D9%85%D9%87%D8%A7%D9%85-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B9-r162/">بالتحقق من الاستمارات</a>.</p><p>ترجمة -وبتصرّف- للمقال <a rel="external nofollow" href="https://www.flynsarmy.com/2015/02/creating-a-basic-todo-application-in-laravel-5-part-3/">Creating a Basic ToDo Application in Laravel 5 – Part 3</a>.</p><p>حقوق الصورة البارزة: <a rel="external nofollow" target="_blank" href="http://www.freepik.com/free-vector/checking-task-list-by-hand_760718.htm">Designed by Freepik</a>.</p></form>
]]></description><guid isPermaLink="false">158</guid><pubDate>Fri, 04 Sep 2015 09:11:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642; Todo List &#x628;&#x633;&#x64A;&#x637; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Laravel 5 - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x646;&#x64A;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r157/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.png.515c9355a803fc7408cad60c4d9e0826.png" /></p>

<p>بعد أن انتهينا من <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r149/">إعداد قواعد البيانات والطرق (routes)</a>، سوف نتحدث في هذا الجزء عن المتحكِّمات (Controllers)، النماذج (مع العلاقات)، والعروض views. (بما في ذلك نظام blade ومخططات المحتوى).</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" style="line-height: 22.4px;" href="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.png.09c597723dd29dc3fef9ac05192f2c2a.png"><img data-fileid="4396" class="ipsImage ipsImage_thumbnailed" alt="laravel5-todo-app.png" src="https://academy.hsoub.com/uploads/monthly_2015_09/laravel5-todo-app.thumb.png.d4a713455449bd76fd6e5e8d8ef12c51.png"></a></p><h2>مساعدات النماذج Form Helpers في Laravel</h2><p>بعد كل هذه الإعدادات، إذا ذهبنا الآن (في المتصفح) إلى <span style="font-family:courier new,courier,monospace;"><code>projects/</code></span> فسوف نحصل على صفحة فارغة فما هو السبب؟ حسنا، لنكتشف ذلك، قم بتنفيذ الأمر <strong><span style="font-family:courier new,courier,monospace;"><code>php artisan route:list</code></span></strong> على سطر الأوامر مرة أخرى وأنظر إلى هذا السطر:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">+--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+
| Domain | Method   | URI                                    | Name                   | Action                                          | Middleware |
+--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+
|        | GET|HEAD | projects                               | projects.index         | App\Http\Controllers\ProjectsController@index   |            |
+--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+</pre><p>يبدو أن رابط <strong><span style="font-family:courier new,courier,monospace;"><code>projects/</code></span></strong> يقوم بتحميل الوظيفة Index الخاصة بـ ProjectsController، لذلك سنقوم بفتح <strong><span style="font-family:courier new,courier,monospace;"><code>app/Http/controllers/ProjectsController.php/</code></span></strong> وسنقوم بتحديث التابع (method) لنقوم بربطه إلى عرض سوف نقوم بإنشائه. قم بإضافة السطر <strong><span style="font-family:courier new,courier,monospace;">;('</span></strong><code><strong><span style="font-family:courier new,courier,monospace;">return view('projects.index</span></strong></code> إلى الوظيفة <strong><span style="font-family:courier new,courier,monospace;">()</span></strong><code><strong><span style="font-family:courier new,courier,monospace;">index</span></strong></code> كالتالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function index()
{
    return view('projects.index');
}</pre><p>بما أننا نستخدم في هذا الدرس <a rel="external nofollow" href="http://laravel.com/docs/5.0/templates#blade-templating">نظام Blade للقَوْلَبة</a> سنقوم بإنشاء ملف <strong><span style="font-family:courier new,courier,monospace;"><code>resources/views/projects/index.blade.php/</code></span></strong> وسنكتب نص قصير داخله، ثم سنقوم مرة أخرى بالذهاب إلى <span style="font-family:courier new,courier,monospace;"><strong><code>projects/</code></strong></span> في المتصفح، إذا كان كل شيء يعمل جيدا فسوف تجد النص الذي كتبته بالأعلى.<br>والآن قُم بنفس الشيء لتابع المتحكِّم <code>create</code> عن طريق إضافة السطر <span style="font-family:courier new,courier,monospace;"><strong>;('<code>return view('projects.create</code></strong></span> إلى التابع <span style="font-family:courier new,courier,monospace;"><strong>()</strong></span><code><span style="font-family:courier new,courier,monospace;"><strong>create</strong></span></code> كالتالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function create()
{
    return view('projects.create');
}</pre><p>إن إظهار محتويات العرض view هو أمر رائع، لكن ماذا لو كنا نملك أكثر من صفحة واحدة في موقعنا ؟ في هذه الحالة، سوف نحتاج إلى قالب ثابت لجميع الصفحات، أي أننا نحتاج إلى عرض محتويات العرض view داخل قالب HTML بسيط، وسنقوم بهذا عن طريق <a rel="external nofollow" href="http://laravel.com/docs/5.0/templates#blade-templating">مخططات المتحكِّمات</a>.</p><p>من أجل عمل مخططات المتحكِّمات سنقوم بالخطوات التالية:</p><ul><li>إنشاء مخطط العرض، وبما أن Laravel توفر لنا واحدة جيدة تدعى <span style="font-family:courier new,courier,monospace;"><strong><code>app.blade.php</code></strong></span> لذلك سنوفر الوقت وسنقوم بإستخدامها. لاحظ أن قرب أسفل المخطط هنالك سطر <strong><span style="font-family:courier new,courier,monospace;">('<code>@yield('content</code></span></strong> وهذه دالة ستقوم بتحميل محتوانا الحالي.</li><li><p>الإشارة إلى مخططك في عرضك view باستخدام <span style="font-family:courier new,courier,monospace;"><strong>('<code>extends('app@</code></strong></span> ولفها عن طريق كتلة <span style="font-family:courier new,courier,monospace;"><strong>('<code>section('content@</code></strong></span>، مثل التالي:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">@extends('app')

@section('content')

This is my /resources/views/projects/index.blade.php file!
@endsection
</pre></li></ul><p>سنقوم الآن بتنفيذ هذه الخطوات بإنشاء عروض <span style="font-family:courier new,courier,monospace;"><code>show.blade.php</code></span> و <span style="font-family:courier new,courier,monospace;"><code>create.blade.php</code></span> و <span style="font-family:courier new,courier,monospace;"><code>index.blade.php</code></span> في مجلد <code><span style="font-family:courier new,courier,monospace;"><strong>resources/views/projects/</strong></span></code> مع الشيفرات (markup) المذكورة أعلاه وقُم بتغيير اسم الملف إذا كان الأمر ضروريا، ثم قُم بعمل تحديث للصفحة <code><span style="font-family:courier new,courier,monospace;"><strong>projects/</strong></span></code> في متصفحك، وسوف ترى هيكل <span style="font-family:courier new,courier,monospace;"><strong><code>app.blade.php</code></strong></span> حول محتويات عرضك (view).</p><h2>الربط بين الطريق (route) والنموذج</h2><p>سيوفر Laravel بشكل افتراضي معرف رقمي ID للعديد من توابع متحكِّمات الموارد مثل <span style="font-family:courier new,courier,monospace;">()</span><code><span style="font-family:courier new,courier,monospace;">show</span></code> و <span style="font-family:courier new,courier,monospace;">()</span><code>edit</code> و <span style="font-family:courier new,courier,monospace;">()</span><code>update</code> و <span style="font-family:courier new,courier,monospace;">()</span><code>destroy</code>، وهذا الأمر سيضيف العديد من الشيفرات الجاهزة (boilerplate) التي نحتاج إلى كتابتها، مثل الحصول على مثيل النموذج والتأكد من وجودها وغيرها. ولهذا سوف نستخدم إحدى مميزات Laravel والتي تدعى <a rel="external nofollow" href="http://laravel.com/docs/5.0/routing#route-model-binding">الربط بين الطريق و النموذج</a> route model binding، فبدل من توفير متغير <span style="font-family:courier new,courier,monospace;"><code>id$</code></span>، سوف نقوم بإعطاء الوظيفة (method) كائن <span style="font-family:courier new,courier,monospace;"><code>project$</code></span> أو <span style="font-family:courier new,courier,monospace;"><code>task$</code></span>.</p><p>قُم بفتح <code><span style="font-family:courier new,courier,monospace;">app/Http/routes.php/</span></code> وأضف هذين السطرين (أول سطرين بعد التعليق):</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">// Provide controller methods with object instead of ID
Route::model('tasks', 'Task');
Route::model('projects', 'Project'); 

// Use slugs rather than IDs in URLs
Route::bind('tasks', function($value, $route) {
    return App\Task::whereSlug($value)-&gt;first();
});

Route::bind('projects', function($value, $route) {
    return App\Project::whereSlug($value)-&gt;first();
});

Route::resource('projects', 'ProjectsController');
Route::resource('projects.tasks', 'TasksController');

</pre><p>وفي <span style="font-family:courier new,courier,monospace;">TasksController</span> و <span style="font-family:courier new,courier,monospace;">ProjectsController</span> (ملفات <span style="font-family:courier new,courier,monospace;">app/Http/Controllers/ProjectsController.php/</span> و <span style="font-family:courier new,courier,monospace;">app/Http/Controllers/TasksController.php/</span>) قُم باستبدال كل وظيفة (method) مُعرف بمرجع <strong><span style="font-family:courier new,courier,monospace;">id$</span></strong> بـ <strong>task$</strong> أو <span style="font-family:courier new,courier,monospace;"><strong>project$</strong></span> مثل التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">// public function edit($id)
public function edit(Project $project)</pre><p>لا تنسَ إضافة <strong><span style="font-family:courier new,courier,monospace;"><code>use App\Task</code></span></strong> و <span style="font-family:courier new,courier,monospace;"><strong><code>use App\Project</code></strong></span> في أعلى المتحكِّمات حتى نشير إلى هذه النماذج. لا تقلق إذا لم تفهم هذه التغييرات، فسنقوم بعرض الشيفرة البرمجة الكاملة لـ <code>TasksController</code> و <code>ProjectsController</code> لاحقا.<br>وفي هذه المرحلة يمكنك تمرير الكائن (object) إلى عرضه في كل متحكِّم لوظيفة (method) الإظهار والتعديل والتحديث حتى نستطيع استخدامهم لاحقا:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function edit(Project $project)
{
    return view('projects.show', compact('project'));
}</pre><p>سوف يحتاج TasksController إلى بضعة تعديلات طفيفة أخرى، وبما أننا نستخدم الموارد المضمّنة nested resources، سيخبرنا <strong><span style="font-family:courier new,courier,monospace;">php artisan route:list</span></strong> أن جميع طرق task تحتوي على قناع {projects} بالإضافة إلى أن بعضها يستقبل قناع {tasks} أيضا. و كنتيجة لذلك، سيتم تمرير مثيل <code>Project</code> كمُعامل أول لتوابع المتحكِّمات (controller methods)، لذلك قُم بتحديثها وقٌم بتمرير متغير <strong><span style="font-family:courier new,courier,monospace;"><code>project$</code></span></strong> الجديد.<br>إذا لم تفهم خطوات الإضافة لـ <code>TasksController</code> و <code>ProjectsController</code> فهذه هي الشيفرة الكاملة للملفين بعد كل التعديلات:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">// /app/Http/Controllers/ProjectsController.php
&lt;?php namespace App\Http\Controllers;

use App\Project;
use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

class ProjectsController extends Controller {

    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $projects = Project::all();
        return view('projects.index', compact('projects'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {
        return view('projects.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store()
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function show(Project $project)
    {
        return view('projects.show', compact('project'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function edit(Project $project)
    {
        return view('projects.edit', compact('project'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function update(Project $project)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function destroy(Project $project)
    {
        //
    }

}


// /app/Http/Controllers/TasksController.php
&lt;?php namespace App\Http\Controllers;

use App\Project;
use App\Task;
use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

class TasksController extends Controller {

    /**
     * Display a listing of the resource.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function index(Project $project)
    {
        return view('tasks.index', compact('project'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function create(Project $project)
    {
        return view('tasks.create', compact('project'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \App\Project $project
     * @return Response
     */
    public function store(Project $project)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Project $project
     * @param  \App\Task    $task
     * @return Response
     */
    public function show(Project $project, Task $task)
    {
        return view('tasks.show', compact('project', 'task'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Project $project
     * @param  \App\Task    $task
     * @return Response
     */
    public function edit(Project $project, Task $task)
    {
        return view('tasks.edit', compact('project', 'task'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \App\Project $project
     * @param  \App\Task    $task
     * @return Response
     */
    public function update(Project $project, Task $task)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Project $project
     * @param  \App\Task    $task
     * @return Response
     */
    public function destroy(Project $project, Task $task)
    {
        //
    }

}</pre><p>لاحظ أنه إذا قمت بتحديث صفحة <code><strong><span style="font-family:courier new,courier,monospace;">projects/project-1/</span></strong></code> سيبقى كل شيء يعمل.</p><h1>عرض نماذجنا</h1><p>صفحة عرض قائمة المشاريع، حان الآن وقت البدء بعرض المشاريع والمهام، قٌم بفتح <code><strong><span style="font-family:courier new,courier,monospace;">projects/</span></strong></code> في متصفحك. وبالاعتماد على <span style="font-family:courier new,courier,monospace;"><strong><code>php artisan route:list</code></strong></span>، ستكون هذه الصفحة هي صفحة عرض المشاريع، لذلك قُم بفتح <code><strong><span style="font-family:courier new,courier,monospace;">resources/views/projects/index.blade.php/</span></strong></code> وأضف التالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@extends('app')

@section('content')
    &lt;h2&gt;Projects&lt;/h2&gt;
     @if ( !$projects-&gt;count() )
        You have no projects
    @else
        &lt;ul&gt;
            @foreach( $projects as $project )
                &lt;li&gt;&lt;a href="{{ route('projects.show', $project-&gt;slug) }}"&gt;{{ $project-&gt;name }}&lt;/a&gt;&lt;/li&gt;
            @endforeach
        &lt;/ul&gt;
    @endif
@endsection</pre><p>سوف أشرح بعض النقاط في هذه الشفرة البرمجية:</p><ul><li>استخدمنا في هذه الشفرة <a rel="external nofollow" href="http://laravel.com/docs/5.0/templates#other-blade-control-structures">لغة Blade للقَوْلَبة</a>، لذلك فإن <code>if</code> و <code>foreach</code> تتحكم في تدفق flow الدوال بإضافة إلى أنها دالة طباعة (الأقواس المعقوفة المزدوجة).</li><li>تأكدنا إن كان هنالك أي مشروع لعرضه، إن كان هنالك أية مشاريع فسيقوم بعرضها وإن لم يكن تظهر رسالة تخبرك بذلك.</li><li>استدعينا مساعد ()<a rel="external nofollow" href="http://laravel.com/docs/helpers#urls">route</a> مع طريق ذا اسم (يمكنك رؤية قائمة الطرق ذات الاسم عن طريق <span style="font-family:courier new,courier,monospace;"><strong><code>php artisan route:list</code></strong></span>) لربط كل مشروع مع صفحة تفاصيله.</li></ul><p>سوف تحتاج أيضا إلى تمرير متغير <strong><span style="font-family:courier new,courier,monospace;"><code>projects$</code></span></strong> لهذا العرض view وإلا ستحصل على خطأ متغير غير معرف undefined variable error. قُم بفتح <code><strong><span style="font-family:courier new,courier,monospace;">app/Http/controllers/ProjectsController.php/</span></strong></code> وقُم بتحديث الوظيفة <strong><span style="font-family:courier new,courier,monospace;">()<code>index</code></span></strong> إلى:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function index()
{
    $projects = Project::all(); return view('projects.index', compact('projects'));
}</pre><p>قُم بتحديث الصفحة (Refresh) وستجد قائمة من مشاريعك.</p><h1>علاقات النموذج - صفحة تفاصيل المشروع</h1><p>في صفحة تفاصيل المشروع نحتاج إلى عرض قائمة من مهام المشاريع، وللقيام بذلك نحتاج إلى تعريف علاقة "<a rel="external nofollow" href="http://laravel.com/docs/5.0/eloquent#one-to-many">واحد إلى الكثير</a> one-to-many" في نموذج <code>Project</code> للسماح له بالحصول على المهام <code>tasks</code>.</p><p>قُم بفتح <code><span style="font-family:courier new,courier,monospace;">app/Project.php/</span></code> وأضف التابع <span style="font-family:courier new,courier,monospace;"><strong>()<code>tasks</code></strong></span> كالتالي:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function tasks()
{
    return $this-&gt;hasMany('App\Task');
}</pre><p>بشكل عكسي، يمكننا إضافة علاقة "الكثير إلى واحد many-to-one" لنموذج المهام <code>Task</code>:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">public function project()
{
    return $this-&gt;belongsTo('App\Project');
}</pre><p>للتأكد من أنها تعمل اكتب الأمر:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">$ php artisan tinker</pre><p>وستكون النّتيجة كالتي حسب المدخلات:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">&gt;App\Project::whereSlug('project-1')-&gt;first()-&gt;tasks-&gt;count();
5
&gt;App\Project::whereSlug('project-2')-&gt;first()-&gt;tasks-&gt;count();
2
&gt;App\Task::first()-&gt;project-&gt;name;
Project 1</pre><p>ممتاز، يمكننا الآن تحديث عرض <strong><span style="font-family:courier new,courier,monospace;">resources/views/projects/show.blade.php/</span></strong>:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@extends('app')

@section('content')
    &lt;h2&gt;{{ $project-&gt;name }}&lt;/h2&gt;
     @if ( !$project-&gt;tasks-&gt;count() )
        Your project has no tasks.
    @else
        &lt;ul&gt;
            @foreach( $project-&gt;tasks as $task )
                &lt;li&gt;&lt;a href="{{ route('projects.tasks.show', [$project-&gt;slug, $task-&gt;slug]) }}"&gt;{{ $task-&gt;name }}&lt;/a&gt;&lt;/li&gt;
            @endforeach
        &lt;/ul&gt;
    @endif
@endsection</pre><p>اضغط على أي مشروع في صفحة عرض قائمة المشاريع في متصفحك وسوف يتم عرض المشروع مع جميع المهام المرتبطة به.<br>وأخير تَبقى لدينا صفحة عرض المهام (<code><strong><span style="font-family:courier new,courier,monospace;">resources/views/tasks/show.blade.php/</span></strong></code>)، وهذه سهلة للغاية:</p><pre data-pbcklang="php" data-pbcktabsize="" class="php ipsCode prettyprint">@extends('app')

@section('content')
    &lt;h2&gt;
        {!! link_to_route('projects.show', $project-&gt;name, [$project-&gt;slug]) !!} -
        {{ $task-&gt;name }}
    &lt;/h2&gt;

    {{ $task-&gt;description }}
@endsection</pre><p>ملاحظة: كُن حذرا عندما تستخدم علاقات النماذج (models)، فإنه من السهل إنشاء عدد كبير من استعلامات SQL، وتسمى هذه المشكلة بـ "مشكلة N+1".</p><h1>الخاتمة</h1><p>اليوم تعلمنا الكثير من الأشياء الجديدة مثل:</p><ul><li>الربط بين الطريق (route) و النموذج</li><li>النماذج (مع علاقة واحد إلى الكثير one-to-many)</li><li>المتحكِّمات (مع الربط بين الطريق و النموذج)</li><li>العروض (مع لغة blade للقَوْلَبة والمخططات)</li></ul><p>أصبحت الصفحة تعرض لنا قائمة من المشاريع والمهام، وفي الدرس القادم سوف نركز على <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-r158/">تعديل وإضافة وحذف المشاريع والمهام</a>.</p><p>ترجمة -وبتصرّف- للمقال <a rel="external nofollow" href="https://www.flynsarmy.com/2015/02/creating-a-basic-todo-application-in-laravel-5-part-2/">Creating a Basic ToDo Application in Laravel 5 – Part 2</a>.</p><p>حقوق الصورة البارزة: <a rel="external nofollow" target="_blank" href="http://www.freepik.com/free-vector/checking-task-list-by-hand_760718.htm">Designed by Freepik</a>.</p>
]]></description><guid isPermaLink="false">157</guid><pubDate>Wed, 02 Sep 2015 18:54:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642; Todo List &#x628;&#x633;&#x64A;&#x637; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Laravel 5 - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x623;&#x648;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r149/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_08/laravel5-todo-app_(1).png.b49e38714b3e9758dcf054ab8e54a4ac.png" /></p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_08/laravel5-todo-app_(1).png.57c76c0fe12214f761ca211c00caf8e2.png" data-fileid="4082" rel=""><img alt="laravel5-todo-app_(1).thumb.png.e3c2af36" class="ipsImage ipsImage_thumbnailed" data-fileid="4082" src="https://academy.hsoub.com/uploads/monthly_2015_08/laravel5-todo-app_(1).thumb.png.e3c2af36a8e5d12cc00f090169b588b0.png"></a>
</p>

<p>
	<strong>ملاحظة</strong>: هذا الدرس طويل للغاية لذلك سوف يتم تقسيمه إلى أجزاء أصغر، ويمكنك الحصول على الكود المصدري لكل جزء من <a href="https://github.com/Flynsarmy/laravel-5-todo-tutorial" rel="external nofollow">GitHub</a>.
</p>

<p>
	في هذا الدرس سوف نتحدث عن تثبيت Laravel 5 وإعداده وعن بعض التقنيات الجديد كالتهجير migration والبذر seeding.
</p>

<h1>
	قبل أن نبدأ
</h1>

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

<h1>
	هدف المشروع
</h1>

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

<ul>
<li>
		إعداد وتنصيب Laravel.
	</li>
	<li>
		تركيب حزم إضافية لتسهيل عملية التطوير.
	</li>
	<li>
		استخدام التهجير migration والبذر seeds.
	</li>
	<li>
		تعلم كيفية استخدام متحكِّمات الموارد resourceful controllers.
	</li>
	<li>
		تعلم كيفية استخدام العروض views. (بما في ذلك نظام blade ومخططات المحتوى)
	</li>
	<li>
		التعامل مع علاقات النماذج.
	</li>
</ul>
<h1>
	التثبيت
</h1>

<p>
	إن عملية تثبيت Laravel سهلة للغاية بفضل <a href="http://getcomposer.org/doc/00-intro.md#installation-nix" rel="external nofollow">Composer</a>، لذلك سوف نستخدمه في تثبيته.
</p>

<p>
	استخدام Composer
</p>

<p>
	والآن نقوم بتشغيل مثبت Laravel (سوف تحتاج إلى عمل هذا لمرة واحدة فقط):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">composer </span><span class="kwd">global</span><span class="pln"> </span><span class="kwd">require</span><span class="pln"> </span><span class="str">"laravel/installer=~1.1"</span></pre>

<p>
	والآن نقوم بعمل مشروعنا:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">laravel </span><span class="kwd">new</span><span class="pln"> l5todo</span></pre>

<h1>
	الإعداد
</h1>

<p>
	يستخدم Laravel 5 حزمة تدعى <a href="https://github.com/vlucas/phpdotenv" rel="external nofollow">DotEnv</a> تقوم بتخزين المعلومات الحساسة في ملفات ذات صيغة .env والتي يتم تحميلها <a href="http://php.net/manual/en/reserved.variables.environment.php" rel="external nofollow">كمتغيرات</a> PHP عند التشغيل. قد يبدوا لك هذا معقدا لكن بكلمات أخرى، هذا يعني أن فقط الإعدادات الحسّاسة credentials يتم تخزينها في هذه الملفات وأما بقية إعداداتك فيتم تخزينها في ملفات الإعداد العادية.
</p>

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

<p>
	سوف نحتاج إلى قاعدة بيانات، لذلك سنقوم بعمل واحدة ثم سنقوم بنسخ .env.example إلى .env وتحديث البيانات على الشكل التالي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">DB_HOST</span><span class="pun">=</span><span class="pln">localhost
DB_DATABASE</span><span class="pun">=</span><span class="pln">homestead
DB_USERNAME</span><span class="pun">=</span><span class="pln">homestead
DB_PASSWORD</span><span class="pun">=</span><span class="pln">secret</span></pre>

<p>
	في النهاية إذا لم تكن تستخدم MySQL فقُم بفتح <span style="font-family:courier new,courier,monospace;">config/database.php/</span> ثم قٌم بتغيير السطر الافتراضي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="str">'default'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'mysql'</span><span class="pun">,</span></pre>

<p>
	تذكر أن تضيف ملفات بيئة عملك إلى <a href="https://help.github.com/articles/ignoring-files" rel="external nofollow">.gitignore</a> عن طريق إضافة سطر .env.
</p>

<h1>
	خطواتنا الأولى
</h1>

<p>
	كما ذكرنا في الأعلى، سوف يتكون تطبيق قائمة المهام على مشروع أو أكثر كل واحد مع قائمة المهام الخاصة به، ولذلك سوف نحتاج إلى مشروع، نماذج مهام، متحكِّمات، عروض views، التهجير migration، البذور seeds والطرق routes، ولقد قمنا بشرح بعض هذه المصطلحات في بداية الدرس.<br>
	لنبدأ بالتعامل معهم كل واحد على حدة.
</p>

<p>
	التهجير migration
</p>

<p>
	أولا نريد أن نرى مخطط جدولنا، سوف يبدو مثل هذا:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="typ">Projects</span><span class="pln">
</span><span class="pun">+------------+------------------+------+-----+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Field</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Type</span><span class="pln">             </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Null</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Key</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"> id         </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln"> PRI </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> name       </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="lit">255</span><span class="pun">)</span><span class="pln">     </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> slug       </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="lit">255</span><span class="pun">)</span><span class="pln">     </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> created_at </span><span class="pun">|</span><span class="pln"> timestamp        </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> updated_at </span><span class="pun">|</span><span class="pln"> timestamp        </span><span class="pun">|</span><span class="pln"> NO   </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">Tasks</span><span class="pln">
</span><span class="pun">+-------------+------------------+------+-----+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Field</span><span class="pln">       </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Type</span><span class="pln">             </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Null</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Key</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"> id          </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln"> PRI </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> project_id  </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln"> MUL </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> name        </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="lit">255</span><span class="pun">)</span><span class="pln">     </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> slug        </span><span class="pun">|</span><span class="pln"> varchar</span><span class="pun">(</span><span class="lit">255</span><span class="pun">)</span><span class="pln">     </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> completed   </span><span class="pun">|</span><span class="pln"> tinyint</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">       </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> description </span><span class="pun">|</span><span class="pln"> text             </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> created_at  </span><span class="pun">|</span><span class="pln"> timestamp        </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> updated_at  </span><span class="pun">|</span><span class="pln"> timestamp        </span><span class="pun">|</span><span class="pln"> NO   </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+-------------+------------------+------+-----+</span></pre>

<p>
	ثم سوف نقوم بعمل التهجير migration:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">migration create_projects_and_tasks_tables </span><span class="pun">--</span><span class="pln">create</span><span class="pun">=</span><span class="str">"projects"</span></pre>

<p>
	سوف نقوم بعمل كِلا الجدولين بتهجير migration واحد حتى نتمكن من حذفها بترتيب عكسي لتجنب سلامة خرق القيد <a href="http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html" rel="external nofollow">integrity constraint violation</a>، قُم بفتح:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="str">/database/</span><span class="pln">migrations</span><span class="pun">/</span><span class="pln">createprojectsandtasks_tables</span><span class="pun">.</span><span class="pln">php</span></pre>

<p>
	<date>وقُم بتحديث المعلومات حسب الآتي:</date></p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CreateProjectsAndTasksTables</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">'projects'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="str">''</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">'slug'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="str">''</span><span class="pun">);</span><span class="pln">            
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">

        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">            
            $table</span><span class="pun">-&gt;</span><span class="pln">increments</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">integer</span><span class="pun">(</span><span class="str">'project_id'</span><span class="pun">)-&gt;</span><span class="kwd">unsigned</span><span class="pun">()-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">foreign</span><span class="pun">(</span><span class="str">'project_id'</span><span class="pun">)-&gt;</span><span class="pln">references</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">)-&gt;</span><span class="pln">on</span><span class="pun">(</span><span class="str">'projects'</span><span class="pun">)-&gt;</span><span class="pln">onDelete</span><span class="pun">(</span><span class="str">'cascade'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="str">''</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">'slug'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="str">''</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">boolean</span><span class="pun">(</span><span class="str">'completed'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">text</span><span class="pun">(</span><span class="str">'description'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="str">''</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * Reverse the migrations.
     *
     * @return void
     */</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">drop</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">drop</span><span class="pun">(</span><span class="str">'projects'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

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

<p>
	قم بتنفيذ الهجرة migration:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">php artisan migrate</span></pre>

<p>
	إذا قمت الآن بمراجعة قاعدة البيانات، يجب أن تكون الجداول مكتملة.
</p>

<p>
	البذور Seeds
</p>

<p>
	سوف نحتاج إلى بذر المشاريع/المهام ليكون لديك شيء للعمل معه عندما نصل إلى المتصفح، لذلك قم بإنشاء:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="str">/database/</span><span class="pln">seeds</span><span class="pun">/</span><span class="typ">ProjectsTableSeeder</span><span class="pun">.</span><span class="pln">php </span><span class="pun">و</span><span class="pln"> </span><span class="typ">TasksTableSeeder</span><span class="pun">.</span><span class="pln">php </span></pre>

<p>
	كالتالي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="com">// /database/migrations/seeds/ProjectsTableSeeder.php</span><span class="pln">
</span><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">class</span><span class="pln"> </span><span class="typ">ProjectsTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// Uncomment the below to wipe the table clean before populating</span><span class="pln">
        DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'projects'</span><span class="pun">)-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

        $projects </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Project 1'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'project-1'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Project 2'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'project-2'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Project 3'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'project-3'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">

        </span><span class="com">// Uncomment the below to run the seeder</span><span class="pln">
        DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'projects'</span><span class="pun">)-&gt;</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">$projects</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">// /database/migrations/seeds/TasksTableSeeder.php</span><span class="pln">
</span><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">class</span><span class="pln"> </span><span class="typ">TasksTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// Uncomment the below to wipe the table clean before populating</span><span class="pln">
        DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">)-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

        $tasks </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 1'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-1'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My first task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">
            
            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 2'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-2'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My first task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">

            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 3'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-3'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My first task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">

            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 4'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-4'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My second task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">

            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 5'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-5'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My third task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">

            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 6'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-6'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My fourth task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">

            </span><span class="pun">[</span><span class="str">'id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Task 7'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'task-7'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'project_id'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'completed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My fifth task'</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'created_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">,</span><span class="pln"> 
             </span><span class="str">'updated_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">],</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">

        </span><span class="com">//// Uncomment the below to run the seeder</span><span class="pln">
        DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">)-&gt;</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">$tasks</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

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

<p>
	ولا تنسَ إضافة أصناف البذور(seed classes) إلى <span style="font-family:courier new,courier,monospace;">database/seeds/DatabaseSeeder.php/</span> :
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<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">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">

        $this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="str">'ProjectsTableSeeder'</span><span class="pun">);</span><span class="pln">     
        $this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="str">'TasksTableSeeder'</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="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">composer </span><span class="kwd">dump</span><span class="pun">-</span><span class="pln">autoload</span></pre>

<p>
	ثم:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed
</span><span class="com"># أو</span><span class="pln">
php artisan migrate</span><span class="pun">:</span><span class="pln">refresh </span><span class="pun">--</span><span class="pln">seed</span></pre>

<p>
	يجب الآن أن تكون قاعدة البيانات قد تم بذرها.
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">mysql</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">select</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> projects</span><span class="pun">;</span><span class="pln">
</span><span class="pun">+----+-----------+-----------+---------------------+---------------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> id </span><span class="pun">|</span><span class="pln"> name      </span><span class="pun">|</span><span class="pln"> slug      </span><span class="pun">|</span><span class="pln"> created_at          </span><span class="pun">|</span><span class="pln"> updated_at          </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="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Project</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> project</span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Project</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> project</span><span class="pun">-</span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Project</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> project</span><span class="pun">-</span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----+-----------+-----------+---------------------+---------------------+</span><span class="pln">
     
mysql</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">select</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> tasks</span><span class="pun">;</span><span class="pln">
</span><span class="pun">+----+------------+--------+--------+-----------+----------------+---------------------+---------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> id </span><span class="pun">|</span><span class="pln"> project_id </span><span class="pun">|</span><span class="pln"> name   </span><span class="pun">|</span><span class="pln"> slug   </span><span class="pun">|</span><span class="pln"> completed </span><span class="pun">|</span><span class="pln"> description    </span><span class="pun">|</span><span class="pln"> created_at          </span><span class="pun">|</span><span class="pln"> updated_at    </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="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> first task  </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> first task  </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> first task  </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">4</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">4</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> second task </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">5</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">5</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> third task  </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">6</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> fourth task </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">7</span><span class="pln"> </span><span class="pun">|</span><span class="pln">          </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Task</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> task</span><span class="pun">-</span><span class="lit">7</span><span class="pln"> </span><span class="pun">|</span><span class="pln">         </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">My</span><span class="pln"> fifth task  </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2015</span><span class="pun">-</span><span class="lit">02</span><span class="pun">-</span><span class="lit">05</span><span class="pln"> </span><span class="lit">01</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> 
</span><span class="pun">+----+------------+--------+--------+-----------+----------------+---------------------+---------------+</span></pre>

<p>
	النماذج Models
</p>

<p>
	للعمل مع جداول المشاريع والمهام نحتاج إلى نماذج مماثلة، سوف نقوم بإنشائها الآن:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">model </span><span class="typ">Project</span><span class="pln">
php artisan make</span><span class="pun">:</span><span class="pln">model </span><span class="typ">Task</span></pre>

<p>
	كان هذا سهلا <img alt=":)" src="https://academy.hsoub.com/uploads/monthly_2015_02/smile.png.cf72ab87c1aaefd42371e0a7de39cfae.png" title=":)" srcset="https://academy.hsoub.com/uploads/emoticons/smile@2x.png 2x" width="20" height="20"></p>

<p>
	استخدام Artisan – Tinker
</p>

<p>
	الآن لدينا المعلومات في قاعدة البيانات وسيكون من الرائع أن نتعلم حول واحدة من أهم ميزات artisan وهي Tinker الذي يوفر لك سطر أوامر للتعامل مع Laravel، وكمثال، لنستخدمه في معرفة عدد المشاريع في قاعدة البيانات الحالية:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">$ php artisan tinker
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Project</span><span class="pun">::</span><span class="pln">count</span><span class="pun">();</span><span class="pln">    
</span><span class="lit">3</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Task</span><span class="pun">::</span><span class="pln">count</span><span class="pun">();</span><span class="pln">
</span><span class="lit">7</span></pre>

<p>
	وكما ترى يمكن أن يكون Tinker مفيدا للغاية، لذلك سوف نستخدمه عدة مرات في هذه السّلسلة.
</p>

<p>
	المُتحكِّمات Controllers
</p>

<p>
	الآن وصلنا إلى النقطة التي سوف نبدأ بعرض ما صنعناه على المتصفح، وسوف نحتاج إلى إنشاء بعض المتحكِّمات Controllers والطرق Routes. سنبدأ أولا بالمتحكِّمات:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">ProjectsController</span><span class="pln">
php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">TasksController</span></pre>

<p>
	الموارد المُضمّنة
</p>

<p>
	نبدأ بإضافة موارد Project و Task إلى <span style="font-family:courier new,courier,monospace;">app/Http/routes.php/</span> :
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'WelcomeController@index'</span><span class="pun">);</span><span class="pln">

</span><span class="com">//Route::get('home', 'HomeController@index');</span><span class="pln">
</span><span class="com">//</span><span class="pln">
</span><span class="com">//Route::controllers([</span><span class="pln">
</span><span class="com">//  'auth' =&gt; 'Auth\AuthController',</span><span class="pln">
</span><span class="com">//  'password' =&gt; 'Auth\PasswordController',</span><span class="pln">
</span><span class="com">//]);</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'projects'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'ProjectsController'</span><span class="pun">);</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'TasksController'</span><span class="pun">);</span></pre>

<p>
	والآن دعونا نرى إحدى مميزات artisan والمُتمثّلة في route:list، في سطر الأوامر أكتب التالي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln">php artisan route</span><span class="pun">:</span><span class="pln">list</span></pre>

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

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="1" style="">
<span class="pun">+--------+----------+--------------------------+------------------+-------------------------------------------------+------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Domain</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Method</span><span class="pln">   </span><span class="pun">|</span><span class="pln"> URI                      </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Name</span><span class="pln">             </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Action</span><span class="pln">                                          </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Middleware</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------+----------+--------------------------+------------------+-------------------------------------------------+------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> </span><span class="pun">/</span><span class="pln">                        </span><span class="pun">|</span><span class="pln">                  </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\WelcomeController@index    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects                 </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">index   </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@index   </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/</span><span class="pln">create          </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">create  </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@create  </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> POST     </span><span class="pun">|</span><span class="pln"> projects                 </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">store   </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@store   </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">show    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@show    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">edit </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">edit    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@edit    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PUT      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">update  </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@update  </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PATCH    </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</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">App</span><span class="pln">\Http\Controllers\ProjectsController@update  </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> DELETE   </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">destroy </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@destroy </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> tasks                    </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">index      </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@index      </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">/</span><span class="pln">create             </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">create     </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@create     </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> POST     </span><span class="pun">|</span><span class="pln"> tasks                    </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">store      </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@store      </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">            </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">show       </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@show       </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}/</span><span class="pln">edit       </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">edit       </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@edit       </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PUT      </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">            </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">update     </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@update     </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PATCH    </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">            </span><span class="pun">|</span><span class="pln">                  </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@update     </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> DELETE   </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">            </span><span class="pun">|</span><span class="pln"> tasks</span><span class="pun">.</span><span class="pln">destroy    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@destroy    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------+----------+--------------------------+------------------+-------------------------------------------------+------------+</span></pre>

<p>
	ستلاحظ أن كل من projects و tasks هي روابط ذات مستوى عالي، وفي تطبيقنا، المهام تتبع المشاريع، لذلك سيكون من الأفضل للروابط أن تكون مُضمّنة مثل /projects/1/tasks/3 بدلا من /tasks/، وهذا يمكن فعله باستخدام شيء اسمه الموارد المُضمّنة nested resources، وكما هو الحال مع أغلب الأشياء في Laravel، التعديل المطلوب سريع وبسيط، فقط قٌم بفتح /app/Http/routes.php وقٌم بالتعديلات التالية:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="com">// Route::resource('tasks', 'TasksController');</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'projects.tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'TasksController'</span><span class="pun">);</span></pre>

<p>
	هذا كل شيء، قُم بكتابة php artisan route:list لنعلم ماذا لدينا لحد الآن:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="pln"> php artisan route</span><span class="pun">:</span><span class="pln">list
    </span><span class="pun">+--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+</span><span class="pln">
    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Domain</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Method</span><span class="pln">   </span><span class="pun">|</span><span class="pln"> URI                                    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Name</span><span class="pln">                   </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Action</span><span class="pln">                                          </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Middleware</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">+--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> </span><span class="pun">/</span><span class="pln">                                      </span><span class="pun">|</span><span class="pln">                        </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\WelcomeController@index    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects                               </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">index         </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@index   </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/</span><span class="pln">create                        </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">create        </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@create  </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> POST     </span><span class="pun">|</span><span class="pln"> projects                               </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">store         </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@store   </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}</span><span class="pln">                    </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">show          </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@show    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">edit               </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">edit          </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@edit    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PUT      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}</span><span class="pln">                    </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">update        </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@update  </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PATCH    </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</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">App</span><span class="pln">\Http\Controllers\ProjectsController@update  </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> DELETE   </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}</span><span class="pln">                    </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">destroy       </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProjectsController@destroy </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks              </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">index   </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@index      </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks</span><span class="pun">/</span><span class="pln">create       </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">create  </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@create     </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> POST     </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks              </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">store   </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@store      </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">show    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@show       </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> GET</span><span class="pun">|</span><span class="pln">HEAD </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}/</span><span class="pln">edit </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">edit    </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@edit       </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PUT      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">update  </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@update     </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> PATCH    </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln">                        </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@update     </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">|</span><span class="pln">        </span><span class="pun">|</span><span class="pln"> DELETE   </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">/{</span><span class="pln">projects</span><span class="pun">}/</span><span class="pln">tasks</span><span class="pun">/{</span><span class="pln">tasks</span><span class="pun">}</span><span class="pln">      </span><span class="pun">|</span><span class="pln"> projects</span><span class="pun">.</span><span class="pln">tasks</span><span class="pun">.</span><span class="pln">destroy </span><span class="pun">|</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TasksController@destroy    </span><span class="pun">|</span><span class="pln">            </span><span class="pun">|</span><span class="pln">
    </span><span class="pun">+--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+</span></pre>

<p>
	جعل روابط ذات اسم لطيف
</p>

<p>
	الطرق routes الحالية ممتازة لكنها ذات عناوين يمكن تحسينها، مثل هذا العنوان /projects/1/tasks/2، فسيكون من الرائع للزوار أن يتم تغيير المعرف الرقمي ID بالاسم اللطيف للحقول، فمثلا سوف نحصل على /projects/my-first-project/tasks/buy-milk بدلا من /projects/1/tasks/2.
</p>

<p>
	قم بفتح ملف /app/Http/routes.php وضع به التالي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="" style="">
<span class="typ">Route</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">,</span><span class="pln"> $route</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">App</span><span class="pln">\Task</span><span class="pun">::</span><span class="pln">whereSlug</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">)-&gt;</span><span class="pln">first</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'projects'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">,</span><span class="pln"> $route</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">App</span><span class="pln">\Project</span><span class="pun">::</span><span class="pln">whereSlug</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">)-&gt;</span><span class="pln">first</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	هذه الشيفرة سوف تغير السلوك الافتراضي لـ tasks و projects في artisan routes وجعل الروابط ذات إسم لطيف slug.
</p>

<h1>
	خاتمة
</h1>

<p>
	اليوم لقد قمنا بعمل عدة أشياء وهي:
</p>

<ul>
<li>
		تثبيت وإعداد Laravel.
	</li>
	<li>
		إضافة موردان اثنان resources.
	</li>
	<li>
		إنشاء التهجيرات migrations.
	</li>
	<li>
		إضافة بعض بيانات البذور seeds.
	</li>
	<li>
		تكوين هيكل الروابط.
	</li>
</ul>
<p>
	بكلمات أخرى، قمنا اليوم بوضع الأساس التي سوف نعتمد عليه في <a href="https://academy.hsoub.com/search/?tags=laravel5%20todo" rel="">الدروس القادمة</a> من خلال إنشاء جميع العناصر اللازمة حتى تعمل الواجهة الأمامية، ولدينا الآن بعض البيانات في قاعدة البيانات بالإضافة إلى الطرق، في الدرس القادم سوف نبدأ في <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r157/" rel="">الواجهة الأمامية للموقع</a>.
</p>

<p style="line-height: 22.3999996185303px;">
	هنالك بضعة مواقع أخرى لتحصل على المزيد من المعلومات وآخر الأخبار:
</p>

<ul style="line-height: 22.3999996185303px;">
<li>
		<a href="https://twitter.com/laravelphp" rel="external nofollow">The Laravel Twitter feed:</a> أخر الأخبار حول تطورات Laravel.
	</li>
	<li>
		<a href="https://twitter.com/taylorotwell" rel="external nofollow">Taylor Otwell’s Twitter feed</a>: حساب تويتر لمُؤسّس Laravel.
	</li>
	<li>
		<a href="http://laravel.io/" rel="external nofollow">Laravel.io</a>: لمتابعة آخر الأخبار و الدورات من مختلف مواقع الويب، بالإضافة إلى بودكاست أسبوعي يتحدث عن الأفكار والاهتمامات ذات علاقة إلى المنصة.
	</li>
	<li>
		<a href="http://registry.autopergamene.eu/" rel="external nofollow">Laravel Packages Registry</a>: مكان جيد لإيجاد أفضل حزم Laravel.
	</li>
	<li>
		<a href="http://daylerees.com/codebright/the-primers" rel="external nofollow">Code Bright</a>: كتاب إلكتروني مجاني من المؤلف دايلي ريس Dayle Rees.
	</li>
</ul>
<p>
	ترجمة وبتصرف للمقال: <a href="https://www.flynsarmy.com/2015/02/creating-a-basic-todo-application-in-laravel-5-part-1/" rel="external nofollow">Creating a Basic ToDo Application in Laravel 5 – Part 1</a>.
</p>

<p>
	حقوق الصورة البارزة: <a href="http://www.freepik.com/free-vector/checking-task-list-by-hand_760718.htm" rel="external nofollow">Designed by Freepik</a>.
</p>
]]></description><guid isPermaLink="false">149</guid><pubDate>Tue, 25 Aug 2015 21:52:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x627;&#x633;&#x62A;&#x645;&#x627;&#x631;&#x629; &#x627;&#x62A;&#x635;&#x627;&#x644; &#x641;&#x64A; Laravel 5 &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x645;&#x64A;&#x632;&#x629; Form Request</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D8%B3%D8%AA%D9%85%D8%A7%D8%B1%D8%A9-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D9%81%D9%8A-laravel-5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D9%8A%D8%B2%D8%A9-form-request-r128/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_07/larabel5-forms.png.0a2a75b120396723683a85b22cf0dda0.png" /></p>

<p>يوفر Laravel 5 ميزة جديدة تسمى استعلامات الاستمارة Form Requests تساعد في معالجة بيانات الاستمارة والتحقق من صحتها. ستتعلم في هذا الدرس كيفية إنشاء استمارة اتصال في Laravel 5 باستخدام الميزة المذكورة وإمكانيات Laravel في إرسال البريد الإلكتروني. سنعرض طوال الدرس لميزات وحيل تقنية تتعلق بالتطوير على Laravel.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_07/larabel5-forms.png.e52c42be04fc75bb1ff39982d97b4319.png"><img data-fileid="3283" class="ipsImage ipsImage_thumbnailed" alt="larabel5-forms.thumb.png.eeb0527d80110ad" src="https://academy.hsoub.com/uploads/monthly_2015_07/larabel5-forms.thumb.png.eeb0527d80110ad3e92939d22139ae4d.png"></a></p><p>تتكون استمارة الاتصال من ثلاثة حقول هي اسم المستخدم، وعنوان بريده الإلكتروني والرسالة التي يود إرسالها.</p><div class="figure" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_07/01_form_contact.png.785b389d4b3218dae46706118fd8a941.png"><img class="ipsImage ipsImage_thumbnailed" data-fileid="3281" alt="01_form_contact.thumb.png.f9796ad532789d" src="https://academy.hsoub.com/uploads/monthly_2015_07/01_form_contact.thumb.png.f9796ad532789db2aaaeeb8fe7c3f37e.png"></a></div><p><strong>ملحوظة</strong>: يفترض الدرس أن Laravel مثبت وجاهز للعمل.</p><p>نبدأ بإنشاء مشروع Laravel جديد (أسميته <code>academy</code>) ثم الدخول إلى المجلد:</p><pre class="html ipsCode prettyprint" data-pbcktabsize="4" data-pbcklang="html">laravel new academy
cd academy</pre><p>يمكننا إنشاء متحكِّم Controller خاص بمعالجة استمارة الاتصال وعرضها إلا أننا سندمج هذه الوظيفة - للتسهيل - في المتحكِّم الذي يتولى الأمور الإدارية المتعلقة بالتطبيق. سننشئ لهذا الغرض متحكما باسم <code>AboutController</code> ونستخدم إجراءيْ <code>create</code> و<code>store</code> لعرض استمارة الاتصال والتعامل معها (يقدم <code>create</code> الاستمارة عبر <code>GET</code> فيما يقدمها <code>store</code> عبر <code>POST</code>). سيستخدم <code>AboutController</code> إجراءات <code>create </code>،<code>index</code> و<code>store</code> فقط فسنكتفي بإنشاء متحكِّم بسيط عن طريق أمر <code>artisan make:controller</code> على النحو التالي:</p><pre class="html ipsCode prettyprint" data-pbcktabsize="4" data-pbcklang="html">$ php artisan make:controller --plain AboutController

Controller created successfully</pre><p>نضيف كُنْيتيْن Aliases ضمن ملف <code>app/Http/routes.php</code> لتمكين الوصول إلى الاستمارة عبر المسار <code>contact/</code>:</p><pre class="html ipsCode prettyprint" data-pbcktabsize="4" data-pbcklang="html">Route::get('contact', 
  ['as' =&gt; 'contact', 'uses' =&gt; 'AboutController@create']);
Route::post('contact', 
  ['as' =&gt; 'contact_store', 'uses' =&gt; 'AboutController@store']);</pre><p>ينشئ أمر <code>artisan make:controller</code> السابق متحكما خاويا، نتيجة استخدام خيار <code>plain--</code> مع <code>artisan</code>. أي أنه يتوجب علينا إضافة دالتَيْ <code>create</code> و<code>store</code> في متحكم <code>AboutController</code>. عدل على المتحكِّم ليبدو على النحو التالي:</p><pre class="html ipsCode prettyprint" data-pbcktabsize="4" data-pbcklang="html">&lt;?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;

    use App\Http\Requests;
    use App\Http\Controllers\Controller;

    class AboutController extends Controller
    {
        public function create()
        {
          return view('about.contact');
        }
        public function store()
        {
        }
    }</pre><p> </p><p><strong>ملحوظة</strong>: يوجد المتحكم ضمن المسار <code>app/Http/Controllers</code> الموجود ضمن مجلد المشروع. كل المسارات المذكورة في الدرس تُنسَب إلى مجلد المشروع.</p><p>ضبطنا إجراء <code>create</code> ليقدم عرضا View باسم <code>contact.blade.php</code> يوجد ضمن المسار <code>resources/views/about</code>.</p><p>العرض <code>contact.blade.php</code> غير موجود لحد الساعة. فلننشئه.</p><h2 id="إنشاء-استمارة-الاتصال">إنشاء استمارة الاتصال</h2><p>يوفر Laravel ميزات عدة لتصْيِير Rendering استمارات HTML. سنستخدم نظام Blade للقَوْلَبة Templating، المضمن في Laravel، لإنشاء الاستمارة. أنشئ مجلدا باسم <code>about</code> في المسار <code>resources/views/</code> ثم أنشئ داخله ملفا باسم <code>contact.blade.php</code>. وألصق المحتوى التالي:</p><pre class="html ipsCode prettyprint" data-pbcktabsize="4" data-pbcklang="html">&lt;!doctype html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  {!! Html::style('css/form.css') !!}
  &lt;title&gt;Academy Contact&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="page-wrap"&gt;
        &lt;h1&gt;Academy contact&lt;/h1&gt;

        &lt;ul&gt;
            @foreach($errors-&gt;all() as $error)
              &lt;li&gt;{{ $error }}&lt;/li&gt;
            @endforeach
        &lt;/ul&gt;

        &lt;div id="contact-area"&gt;
            {!! Form::open(array('route' =&gt; 'contact_store', 'class' =&gt; 'form')) !!}


            {!! Form::label('Your Name') !!}
            {!! Form::text('name', null, array('required', 'placeholder'=&gt;'Your name')) !!}

            {!! Form::label('Your E-mail Address') !!}
            {!! Form::text('email', null,array('required', 'placeholder'=&gt;'Your e-mail address')) !!}


            {!! Form::label('Message') !!}
            {!! Form::textarea('message', null, array('required', 'id'=&gt;'Message', 'cols'=&gt;'20', 'rows'=&gt;'20','placeholder'=&gt;'Your message')) !!}

            {!! Form::submit('Contact Us!', array('class'=&gt;'submit-button')) !!}

            {!! Form::close() !!}
        
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><p>سنعود لشرح هذه الشفرة بعد قليل.</p><h3 id="تفعيل-مكون-html">1- تفعيل مكون HTML</h3><p>في الاستمارة أعلاه استخدمنا مُنشِئ الاستمارات Form builder الموجود في مكون HTML؛ هذا المكون غير مفعل افتراضيا في Laravel 5. لتفعيله نفذ الخطوات التالية.</p><ul><li><p>عدل على ملف <code>composer.json</code> الموجود في مجلد المشروع وأضف التعليمة التالية ضمن خانة <code>require</code>:</p></li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">"illuminate/html": "~5.0"</pre><p>تصبح خانة <code>require</code> على الهيئة التالية بعد إضافة السطر (انتبه للفاصلة <code>,</code> في نهاية السطر الذي يسبق التعليمة التي أضفناها):</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">"type": "project",
    "require": {
      "php": "&gt;=5.5.9",
      "laravel/framework": "5.1.*",
      "illuminate/html": "~5.0"
    },</pre><ul><li><p>حدث اعتماديات Dependencies المشروع عبر الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">composer update</pre><p> </p></li><li><p>بعد انتهاء التحديث عدل على ملف <code>config/app.php</code> وأضف السطر التالي ضمن مصفوفة <span style="font-family: monospace; line-height: 22.3999996185303px;">Providers </span>(انتبه للفواصل):</p></li></ul><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">'Illuminate\Html\HtmlServiceProvider',</pre><p>في نفس الملف أضف السطرين التاليين لمصفوفة <code>Aliases:</code></p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">'Form'      =&gt; 'Illuminate\Html\FormFacade',
'Html'      =&gt; 'Illuminate\Html\HtmlFacade',</pre><h3 id="شرح-آلية-تصيير-الاستمارة">2- شرح آلية تصيير الاستمارة</h3><p>نعود لشرح طريقة إنشاء الاستمارة الموجودة عبر نظام Blade. نبدأ بأول تعليمة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">{!! Html::style('css/form.css') !!}</pre><p>نطلب من نظام القوالب تحميل ملف CSS لاستخدامه في الصفحة. سيحمَّل ملف CSS في المكان الذي استُدعِيت فيه دالة <code>style</code> التابعة لصنف <code>Html</code> الذي عرَّفناه في الخطوة السابقة ضمن مصفوفة <code>Aliases</code>، هو وصنف <code>Form</code>. انتبه لكتابة اسم الصنف بنفس طريقة تعريفه في المصفوفة (<code>Html</code> وليس <code>HTML</code>). ملف <code>form.css</code> يوجد ضمن مجلد فرعي (باسم <code>css</code>) من مجلد <code>Public</code>. توضع الملفات المتاحة للعموم (مثل CSS وJavaScript) داخل هذا المجلد.</p><p>ننتقل للتعليمتين:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">{!! Form::open(array('route' =&gt; 'contact_store', 'class' =&gt; 'form')) !!}
...
{!! Form::close() !!}</pre><p>تعمل الدالتان <code>Form::open</code> و<code>Form::close()</code> معا من أجل إنشاء وسوم Tags فتح وإغلاق الاستمارة على التوالي. تستقبل دالة <span style="font-family: monospace; line-height: 22.3999996185303px;">Form::open</span> مصفوفة تمثل معطيات إعداد مختلفة؛ مثل كنية<font face="monospace"> </font><span style="font-family: monospace; line-height: 22.3999996185303px;">route</span><code>(الوِجهة) <font face="Helvetica Neue, Helvetica, Arial, sans-serif">التي تشير إلى دالة </font></code><span style="font-family: monospace; line-height: 22.3999996185303px;">store</span> ضمن المتحكم <span style="font-family: monospace; line-height: 22.3999996185303px;">AboutController</span><code>، و</code><span style="font-family: monospace; line-height: 22.3999996185303px;">class</span> التي تشير إلى صنف <code>CSS <font face="Helvetica Neue, Helvetica, Arial, sans-serif">المستخدَم لتنسيق الاستمارة. يُستخدَم إجراء </font></code><span style="font-family: monospace; line-height: 22.3999996185303px;">POST</span> افتراضيا إلا أنه يمكن إبداله ب<span style="font-family: monospace; line-height: 22.3999996185303px;">GET</span> عبر تمريره في المعطى <span style="font-family: monospace; line-height: 22.3999996185303px;">method</span> على النحو التالي <font face="monospace">'method' =&gt; 'post'</font><code>. <font face="Helvetica Neue, Helvetica, Arial, sans-serif">تضيف دالة </font></code><span style="font-family: monospace; line-height: 22.3999996185303px;">Form::open</span> حقلا مخفِيّا عبارة عن رمز <font face="monospace">_token</font> للحماية من هجمات تزوير الطلب عبر الموقع Cross-site request forgery, CSRF.</p><p>ثم يأتي الدور على التعليمات التالية:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;ul&gt;
  @foreach($errors-&gt;all() as $error)
    &lt;li&gt;{{ $error }}&lt;/li&gt;
  @endforeach
&lt;/ul&gt;</pre><p>تستخدم هذه التعليمات لإظهار رسائل تحقق إذا كانت مُدخَلات المستخدم غير مناسبة لطبيعة الحقول (سنعود لها لاحقا، لا تنسها).</p><p>تظهر في ما بعد مجموعة من الدوال من أجل إنشاء حقول الاستمارة: <code>Form::label</code> لإنشاء لصائق Labels الحقول، <code>Form::text</code> لإنشاء حقول نصية، <code>Form::textarea</code> لإنشاء حقول نصية متعددة الأسطر، و<code>Form::submit</code> لإنشاء زر الإرسال. لاحظ أن دالتيْ <code>Form::text</code> و<code>Form::text</code> تحويان معطى باسم خاصية <code>name</code> الخاصة بالحقل (<code>email</code>، <code>name</code> و<code>message</code> على التوالي). أضفنا أيضا لكل حقل تشكيلة من الخيارات مثل أسماء أصناف التنسيقات وخصائص HTML.</p><p>يمكنك بعد حفظ الملف تنفيذ الأمر التالي (من مجلد المشروع) لتشغيل تشغيل خادوم الويب المضمن في Laravel وتجربة النتيجة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">php artisan serve</pre><p>أدخل العنوان <code><a rel="external nofollow" href="http://localhost:8000/contact">http://localhost:8000/contact</a></code> في المتصفح لعرض صفحة الاستمارة.</p><p>ننتقل الآن، بعد إنشاء الاستمارة، لإعداد آلية التعامل مع محتوى الاستمارة وتمكين إرسال المقترحات عبرها.</p><h2 id="إنشاء-استعلام-استمارة-الاتصال">إنشاء استعلام استمارة الاتصال</h2><p>يضيف الإصدار الخامس من Laravel ميزة جديدة تعرف باستعلامات الاستمارة Form Requests؛ تهدف إلى وضع التصريح Authorization والتحقق من البيانات المرسَلة خارج المتحكِّمات وتغليفها ضمن صنف منفصل. نستخدم <code>artisan</code> لإنشاء استعلام Form request على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">$ php artisan make:request ContactFormRequest</pre><p>ينشئ الأمر ملفا باسم <code>ContactFormRequest.php</code> مساره <code>app/Http/Requests/ContactFormRequest.php</code>.</p><p>يبدو هيكل الصنف، بعد حذف التعليقات، كما يلي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class ContactFormRequest extends Request
{
  public function authorize()
  {
    return false;
  }

  public function rules()
  {
     return [
      //
     ];
  }
}</pre><p>تحدد دالة <code>authorize</code> ما إذا كان يُسمح للمستخدم الحالي بالتفاعل مع الاستمارة. نريد أن يكون أي مستخدم قادرا على التفاعل مع الاستمارة، لذا نعدل الدالة لتكون القيمة المُرجَعة <code>true</code> بدلا من <code>false</code>.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public function authorize()
{
  return true;
}</pre><p>تعرِّف دالة <code>rules</code> قواعد التحقق المرتبطة بحقول الاستمارة. الحقول الثلاثة، <code>email</code>، <code>name</code> و<code>message</code> جميعها مطلوبة (<code>required</code>)؛ كما أن حقل البريد الإلكتروني يجب أن يحوي عنوانا بريديا صالحا. نعدل دالة <code>rules</code> لإدراج هذه القواعد.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public function rules()
{
  return [
    'name' =&gt; 'required',
    'email' =&gt; 'required|email',
    'message' =&gt; 'required',
  ];
}</pre><p>توجد مدقِّقات Validators أخرى غير <code>required</code> و<code>email</code> في Laravel للاستخدام عند الحاجة. لاحظ استخدام أكثر من مدقق في نفس الحقل مع الفصل بينها ب<code>|</code> مثل ما فعلنا مع حقل البريد الإلكتروني.</p><p>احفظ ملف <code>ContactFormRequest.php</code> ثم افتح المتحكِّم <code>AboutController</code> (الموجود في المسار <code>app/Http/Controllers/AboutController.php</code>) وعدل دالة <code>store</code> لتصبح على النحو التالي: …</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">use App\Http\Requests\ContactFormRequest;

class AboutController extends Controller {

  public function store(ContactFormRequest $request)
  {

     return \Redirect::route('contact')
           -&gt;with('message', 'Thanks for contacting us!');

  }

}</pre><p>لا تنس إضافة <code>;use App\Http\Requests\ContactFormRequest</code> إلى المتحكم ليمكنه استخدام قواعد المصادقة المعرَّفة في الصنف <code>ContactFormRequest.php</code> الذي سيتولى التحقق من موافقة مُدخَلات المستخدم للقواعد الموضوعة ويظهر رسالة خطأ في حال أخلَّ المستخدم بإحداها. على سبيل المثال، إذا أدخل المستخدم عنوانا بريديا غير صالح فستظهر رسالة الخطأ التالية.</p><div class="figure" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_07/55a269ca4ebed_02___.png.32553a11abada8cfa992f98617787e07.png"><img class="ipsImage ipsImage_thumbnailed" data-fileid="3280" alt="55a269ca7a4be_02___.thumb.png.23ddea0680" src="https://academy.hsoub.com/uploads/monthly_2015_07/55a269ca7a4be_02___.thumb.png.23ddea0680c15db1ab9e98e855360ff6.png"></a></div><p>طبعا لن تظهر رسائل الخطأ من العدم. تتولى مصفوفة <code>errors$</code> المستخدمة في ملف <code>contact.blade.php</code> إظهار هذه الرسائل. هل تذكر هذه الشفرة؟</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">&lt;ul&gt;
@foreach($errors-&gt;all() as $error)
  &lt;li&gt;{{ $error }}&lt;/li&gt;
@endforeach
&lt;/ul&gt;</pre><p> </p><p>نعود إلى <code>ContactFormRequest.php</code>. قد ترغب في إظهار رسالة (شكر مثلا) للمستخدم عند نجاح إرسال الاستمارة. تمكن إضافة رسالة سريعة ضمن دالة <code>store</code>. يضاف المتغير المُمرَّر للدالة تلقائيا إلى متغيرات الجلسة Session في Laravel مما يمكّن من استخدامها عبر الدالة <code>Session::get</code>. يمكِن على سبيل المثال استخدام الشفرة التالية لإظهار محتوى المتغير <code>message</code> في أي عرض (View) أثناء الجلسة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">@if(Session::has('message'))
  &lt;div class="alert alert-info"&gt;
    {{Session::get('message')}}
  &lt;/div&gt;
@endif</pre><p>بقيت خطوة واحدة لتكون الاستمارة جاهزة لإرسال بريد إلكتروني. نحتاج لإعداد مكوِّن البريد في Laravel وإدماج وظيفة تسليم البريد إلى دالة <code>store</code>.</p><h2 id="إعداد-مكون-البريد-في-laravel">إعداد مكوِّن البريد في Laravel</h2><p>يستخدم Laravel حزمة SwiftMailer لتوفير إمكانية إرسال بريد إلكتروني بيسر. كل ما عليك فعله هو ضبط الإعدادات الموجودة في ملف <code>config/mail.php</code>. نذكر في ما يلي بعض الإعدادات الموجودة في الملف.</p><ul><li><code>driver</code>: يدعم Laravel عدة تعريفات بريد مثل SMTP، دالة بريد PHP (mail)، خادوم بريد Sendmail وخدمتَيْ Mailgun وMandrill لتسليم البريد. يجب أن تضبط الإعدادات على التعريف المرغوب بالاختيار بين <code>mailgun</code>، <code>sendmail</code>، <code>mail</code>،<code>smtp </code>و <code>mandrill</code>. </li><li><code>host</code>: تعيين اسم المستضيف لخادوم البريد الإلكتروني (عند استخدام التعريف <code>smtp</code>).</li><li><code>port</code>: تعيين اسم منفَذ خادوم البريد الإلكتروني (عند استخدام التعريف <code>smtp</code>).</li><li><code>from</code>: إذا رغبت في أن تستخدم كل الرسائل المرسَلة نفس العنوان البريدي والاسم للمرسِل فبإمكانك ضبط إعدادات <code>from</code> و<code>address</code> المعرَّفة في هذه المصفوفة.</li><li><code>encryption</code>: يحدد بروتوكول التعميّة Encryption المستخدَم لإرسال البريد الإلكتروني.</li><li><code>username</code>: يعين اسم المستخدم في حال كان التعريف <code>smtp</code>.</li><li><code>password</code>: كلمة سر المستخدم في حال كان التعريف <code>smtp</code>.</li><li><code>sendmail</code>: مسار خادوم Sendmail إذا كانت قيمة <code>driver</code> هي <code>sendmail</code>.</li><li><code>pretend</code>: يطلب هذا الإعداد من Laravl تجاهل التعريف المضبوط وإرسال البريد إلى سجل التطبيق بدلا منه. يناسب التطبيقات التي مازالت قيد التطوير والتجربة.</li></ul><p>نأخذ مثالا لإعداد إرسال البريد في Laravel لاستخدام حساب بريد Google. غير الإعدادات التالية مثل ماهو مبيَّن.</p><ul><li>أعط القيمة <code>smtp</code> للتعريف <code>driver</code>. هذه هي القيمة الافتراضية.</li><li>أبدل قيمة <code>host</code> إلى <code>smtp.google.com</code></li><li>استخدم المنفذ <code>port</code> رقم <code>465</code>.</li><li>أبدل التعميّة <code>encryption</code> إلى <code>ssl</code>.</li><li>استخدم حساب البريد الإلكتروني ضمن إعداد <code>username</code>.</li><li>اكتب كلمة سر حساب البريد الإلكتروني في إعداد <code>password</code>. تذكر أنه يجب، ضمن بيئة عمل فعلية، حفظ هذه المعلومات ومعلومات أخرى حساسة ضمن ملف <code>env.</code> في مشروعك أو في متغير البيئة في الخادوم.</li></ul><p>احفظ التعديلات على ملف <code>config/mail.php</code> ثم عدل المتحكم <code>AboutController</code> ليبدو على النحو التالي:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">public function store(ContactFormRequest $request)
{

  \Mail::send('emails.contact',
    array(
      'name' =&gt; $request-&gt;get('name'),
      'email' =&gt; $request-&gt;get('email'),
      'user_message' =&gt; $request-&gt;get('message')
   ), function($message)
   {
     $message-&gt;from('wj@wjgilmore.com');
     $message-&gt;to('wj@wjgilmore.com', 'Admin')-&gt;subject('Academy Feedback');
   });

  return \Redirect::route('contact')-&gt;with('message', 'Thanks for contacting us!');

}</pre><p>الدالة <code>Mail::send</code> هي المسؤولة عن ابتداء عملية تسليم البريد، وتستقبل ثلاثة معطيات. يحدد المعطى الأول اسم العرض (View) المستخدم لقالب جسم (محتوى) البريد الإلكتروني. المعطى الثاني هو مصفوفة بالبيانات المتاحة للاستخدام في جسم البريد الإلكتروني. البيانات المتاحة في حالتنا هي تلك القادمة من استمارة الاتصال عبر الكائن <code>request$</code>. يمنح المعطى الثالث إمكانية تحديد خيارات إضافية للبريد الإلكتروني مثل المرسِل، المستقبِل والموضوع.</p><p>سنحتاج لإنشاء العرض الذي توجد به محتويات البريد. لذا سننشئ ملفا باسم <code>contact.blade.php</code> في المسار <code>resources/views/emails</code>. طبعا يمكنك تغيير اسم ومجلد العرض؛ إن فعلت فلا تنس التعديل على المتحكم <code>AboutController</code> بما يوافقك تغييراتك.</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">You received a message from academy.hsoub.com:

&lt;p&gt;
  Name: {{ $name }}
&lt;/p&gt;

&lt;p&gt;
  {{ $email }}
&lt;/p&gt;

&lt;p&gt;
  {{ $user_message }}
&lt;/p&gt;</pre><p><strong>ملحوظة:</strong> يوجد سجل التطبيق في المسار <code>storage/logs/laravel.log</code>. عند إعطاء القيمة <code>true</code> ل<code>pretend</code> ستحاكي إرسال بريد دون أن ترسله فعليا وسيظهر سطر يشبه التالي في السجل:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">[2015-07-12 11:34:51] local.INFO: Pretending to mail message to: wj@wjgilmore.com</pre><p>عُد، بعد حفظ التعديلات، إلى استمارة الاتصال؛ اكتب بيانات صحيحة ضمن حقول الاستمارة وأرسلها. يجب أن تصل الرسالة إلى البريد الموجود في دالة <code>to</code> (أي <code>wj@wjgilmore.com</code> في المثال).</p><p>قد تواجه مشاكل مع إعدادات Gmail بسبب التقييدات على تطبيقات الطرف الثالث في Gmail. راجع <a rel="external nofollow" href="https://myaccount.google.com/security">إعدادات حساب Google</a> في هذه الحالة.</p><h2 id="خاتمة">خاتمة</h2><p>اخترنا عرض جميع المخرجات المذكورة في هذا الدرس باللغة الإنجليزية للتركيز على الخاصية المشروحة. إن أردت توطين Localization المثال واستخدام اللغة العربية فيمكنك كتابة العبارات العربية مباشرة في ملفات القوالب لكن ستبقى رسائل الخطأ باللغة الإنجليزية ويجب عليك إدراج رسائل خطأ خاصة بالعربية.</p><p>على العموم يُنصَح، لمن أراد توفير قابلية التوطين بسهولة، بعدم كتابة المُخرجات مباشرة في الشفرة Hard code بل إنشاء ملف بسلاسل المحارف Strings المستخدمة واستدعاء ملف اللغة المناسبة عن طريق دالة الترجمة <code>trans</code>. يُنشَأ مجلد لكل لغة مدعومة ضمن المسار <code>resources/lang</code> الذي يوجد فيه افتراضيا مجلد للغة الإنجليزية <code>en</code> به ملفات بالعبارات المستخدمة افتراضيا.</p><p>ترجمة بتصرف لمقال <a rel="external nofollow" href="http://www.easylaravelbook.com/blog/2015/02/09/creating-a-contact-form-in-laravel-5-using-the-form-request-feature/">Creating a Contact Form in Laravel 5 Using the Form Request Feature</a> لصاحبه <a href="https://twitter.com/wjgilmore" rel="external nofollow">Jason Gilmore </a></p>
]]></description><guid isPermaLink="false">128</guid><pubDate>Tue, 14 Jul 2015 13:56:00 +0000</pubDate></item><item><title>&#x62A;&#x647;&#x62C;&#x64A;&#x631; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; (migrations) &#x639;&#x644;&#x649; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/migration/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_02/laravel.jpg.6ca068c54db8463e3cebd54a8fc73f18.jpg" /></p>
<p>تخيّل معي الوضع التالي. أنت عضو في فريق تطوير تطبيق باستخدام <strong>Laravel 4</strong>. يستخدم أعضاء الفريق <a rel="external nofollow" href="http://www.arabicgit.com/">git</a> لإدارة إصدارات التطبيق وفي كل مرة يقوم عضو من أعضاء الفريق بإضافة خصائص أو إدخال تعديلات جديدة على المشروع يقوم بإيداع التغييرات في مُستودع التطبيق. إلى هنا يبدو الوضع عاديا (بل مثاليا) لكن ماذا لو قام أحد أعضاء الفريق بإدخال تعديل يتطلب إضافة جداول جديدة إلى قاعدة البيانات أو تعديل حقول وحذف أخرى، فما الحل هنا؟ هل يستطيع git مثلا أن يفي بالغرض؟ أم أنه سيتم تصدير قاعدة البيانات في كل مرة ويُطلب من كل عضو في الفريق استيرادها؟ ماذا عن البيانات التي تحتويها قاعدة البيانات؟ وهل يجب فعلا أن نتخلص من قاعدة البيانات القديمة واستبدالها بأخرى في كل مرة؟</p><p>إن كنت تستخدم إطار عمل <strong>لارافل</strong> فالحل يكمن في استخدام التهجير <strong>migrations</strong> والذي يُعتبر نظاما لإدارة الإصدارات الخاصة بقواعد البيانات، حيث أنه لن تعود هناك حاجة إلى إنشاء أي جداول أو إضافة حقول والتعديل عليها بشكل مُباشر/يدوي، وإنما يتم وصف تلك الجداول وحقولها بصيغة تجعل من التعامل مع قواعد البيانات أسهل.<br>قد يبدو الأمر مُعقّدا بعض الشيء، لكنه في حقيقة الأمر بسيط، وبمُجرد أن تفهم آلية عمله وتشرع في استخدامه حتى تستغرب كيف ضيعت كل الوقت السابق في إدارة قواعد البيانات يدويا. خاصية migrations مُفيدة لك حتى ولو كنت تعمل على مشروعك بشكل فردي.</p><p>بطبيعة الحال ستحتاج إلى إنشاء قاعدة بيانات للمشروع، ومن ثم التعديل على ملف <span style="font-family:'courier new', courier, monospace;"><code>app/config/database.php</code></span> بما يتوافق مع ذلك.</p><h2>إنشاء ملفات migrations</h2><p>لإنشاء ملف migration جديد نحتاج إلى استخدام <span style="font-family:'courier new', courier, monospace;">artisan</span> لتنفيذ الأمر <span style="font-family:'courier new', courier, monospace;"><code>migration:make</code></span> على النحو التالي مع استبدال اسم عملية التهجير بما يتوافق مع ما تقوم به (بطبيعة الحال ستحتاج إلى تنفيذ هذا الأمر بسطر الأوامر لما تكون داخل مُجلد المشروع):</p><pre class="php ipsCode prettyprint">php artisan migrate:make create_users_table</pre><p>سيقوم laravel بإنشاء ملف جديد داخل مُجلد <span style="font-family:'courier new', courier, monospace;"><code>app/database/migrations</code></span> يحمل الاسم الذي حددته في الأمر السابق ( <span style="font-family:'courier new', courier, monospace;"><code>create_users_table</code></span>) مسبوقا بترقيم يُمثل تاريخ إنشائه حتى يتسنى لـ laravel معرفة الترتيب الذي يجب اتباعه لدى تنفيذ التهجيرات.<br>يُفضل استخدام أسماء للتهجيرات تدل على ما تقوم به. ففي المثال السابق أردنا إنشاء عملية تهجير جديدة لإنشاء جدول مُستخدمين، وبالتالي كان الاسم <span style="font-family:'courier new', courier, monospace;"><code>create_users_table</code></span>.<br>ينتج عن تنفيذ الأمر السابق ملف يحتوي:</p><pre class="php ipsCode prettyprint">&lt;?php

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

class CreateUsersTable extends Migration {

/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}

}</pre><p> </p><p><span style="font-size:14px;">كما هو ظاهر هنا فإن الصنف <span style="font-family:'courier new', courier, monospace;"><code>CreateUsersTable</code></span> يحتوي على دالتين الأولى <span style="font-family:'courier new', courier, monospace;"><code>up</code></span> والتي تُبين ما الذي يجب القيام به لدى تنفيذ التهجير، والثانية <span style="font-family:'courier new', courier, monospace;"><code>down</code></span> والتي نُحدد فيها ما الذي يجب القيام به لدى إلغاء التهجير في حال ما إذا أردنا العودة بقاعدة البيانات إلى الحالة التي كانت عليها قبل تنفيذ التهجير.</span></p><p>هذا الملف لا يُحدد أي جدول نعمل عليه أو نرغب في إنشاءه. يُمكن إضافة ذلك يدويا، كما أنه يُمكن القيام بذلك عبر تحديد اسم الجدول لدى تنفيذ أمر إنشاء عملية التهجير وذلك باستخدام <span style="font-family:'courier new', courier, monospace;"><code>--create</code></span> التي تُحدد اسم الجدول الذي نرغب في إنشاءه أو <span style="font-family:'courier new', courier, monospace;"><code>--table</code></span> التي تُحدد اسم الجدول الذي نرغب في التعديل عليه. فمثلا لو حذفنا عملية التهجير السابقة ورغبنا في إعادة إنشاء أخرى مع تحديد اسم الجدول فسيكون ذلك على النحو التالي:</p><pre class="php ipsCode prettyprint">php artisan migrate:make create_users_table --create=users</pre><p>والذي سينتج عنه ملف مثل الملف السابق، لكن هذه المرة نجد أن دالتي <code>up</code> و <span style="font-family:'courier new', courier, monospace;"><code>down</code></span> تحتويان أوامر أولية:</p><pre class="php ipsCode prettyprint">&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('user', function(Blueprint $table)
   {
      $table-&gt;increments('id');
      $table-&gt;timestamps();
     });
   }

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

}

</pre><p> </p><p>لاحظ هنا أن <span style="font-family:'courier new', courier, monospace;">users</span> هي اسم الجدول المُراد إنشاؤه والذي يكون عادة جمع اسم الـ model الذي تتعامل معه (بمعنى إن كان  user هو اسم الـ model فسيكون اسم الجدول الخاص به user<strong>s</strong>)</p><p><span style="font-size:14px;">أما لو أردنا التعديل على نفس الجدول السابق وإضافة حقل جديد إليه فيكفي تنفيذ الأمر التالي:</span></p><pre class="php ipsCode prettyprint">php artisan migrate:make add_votes_to_user_table --table=users</pre><h2> تنفيذ عمليات التهجير</h2><p>إلى حد الآن كل ما قمنا به هو إنشاء ملفات التهجير، حيث أنك لو تحققت من قاعدة البيانات لوجدتها فارغة. لتنفيذ عمليات التهجير نستعمل الأمر</p><pre class="php ipsCode prettyprint">php artisan migrate</pre><p>وبعد ذلك ستلاحظ ظهور جدول جديد على قاعدة البيانات.<br>أما لو رغبت في التراجع عن آخر عملية تهجير (أو بالأحرى عن آخر جملة تهجيرات تم تنفيذها مع بعض) فإننا نستعمل الأمر:</p><pre class="php ipsCode prettyprint">php artisan migrate:rollback</pre><p>وفي حال ما إذا رغبت في التراجع عن جميع عمليات التهجير والرجوع إلى الحالة الأولى لقاعدة البيانات فإن الأمر التالي كفيل بالقيام بذلك:</p><pre class="php ipsCode prettyprint">php artisan migrate:reset</pre><p>ويُمكن أيضا استخدام الأمر التالي للتخلص من جميع عمليات التهجير وإعادة تنفيذها من جديد بشكل مُباشر بعد ذلك:</p><pre class="php ipsCode prettyprint">php artisan migrate:refresh</pre><h2>أنواع الحقول</h2><p>رأينا في الفقرة السابقة بأن عمليات التهجير تسمح لنا بإنشاء معرف <span style="font-family:'courier new', courier, monospace;"><code>autoincrement</code></span> إضافة إلى حقلي <span style="font-family:'courier new', courier, monospace;"><code>created_at</code></span> و <span style="font-family:'courier new', courier, monospace;"><code>updated_at</code></span> بفضل دالة <span style="font-family:'courier new', courier, monospace;"><code>timestamps</code></span>. يسمح Laravel بإنشاء شتى أنواع الحقول التي قد تحتاجها في مشروعك إلى جانب إضافة خصائص للحقول وإعطائها قِيمًا أوليّة. المثال التالي يُبين بعض هذه الحقول والخصائص:</p><pre class="php ipsCode prettyprint">$user-&gt;string('name', 64);
$user-&gt;integer('age')-&gt;nullable();
$user-&gt;boolean('active')-&gt;default(1);
$user-&gt;integer('role_id')-&gt;unsigned();
$user-&gt;text('bio');</pre><p>والذي يقوم  بإنشاء:</p><ul><li>حقل <span style="font-family:'courier new', courier, monospace;"><code>name</code></span> يكون نصيا يكون أقصر من أو يُساوي 64 محرفا.</li><li>حقل <span style="font-family:'courier new', courier, monospace;"><code>age</code></span> يكون رقميا، كما أنه يقبل القيمة NULL</li><li>حقل <span style="font-family:'courier new', courier, monospace;"><code>active</code></span> يكون منطقيا ويحمل قيمة أولية 1</li><li>حقل <span style="font-family:'courier new', courier, monospace;"><code>role_id</code></span> رقميا ويكون موجبا</li><li>حقل <span style="font-family:'courier new', courier, monospace;"><code>bio</code></span> يكون نصيا</li></ul><p>بإمكان الاطلاع على جميع أنواع الحقول المُمكنة من <a rel="external nofollow" href="http://laravel.com/docs/schema#adding-columns">هنا</a></p><h2>حذف الحقول</h2><p>ستحتاج إلى حذف الحقول في دالة <span style="font-family:'courier new', courier, monospace;"><code>down</code></span> ويتم ذلك على النحو التالي:</p><pre class="php ipsCode prettyprint">Schema::table('users', function($table)
{
   $table-&gt;dropColumn('votes');
});</pre><h2>بذر قواعد البيانات database seeding</h2><p>المقصود ببذر قواعد البيانات هو إدخال البيانات الأولية التي نحتاجها لتجربة التطبيق. بالرغم من أن تطبيقك يسمح بإنشاء مُستخدمين جدد فإنك سترغب في استخدام مُستخدمين تجريبيين في كل مرة تُحدث تغييرات في التطبيق، وإنشاء عدد من المُستخدمين يدويا في كل مرة مضيعة للوقت. الحل يكمن في إعلام Laravel بالبيانات الأولية التي ترغب في بذر قاعدة البيانات بها بعد إنشائها ويتم ذلك عبر إنشاء ملفات بذر داخل مُجلد <span style="font-family:'courier new', courier, monospace;"><code>app/database/seeds</code></span> يحتوي الأوامر التي يجب تنفيذها.<br>مثال على ملف بذر يقوم بإضافة مُستخدم جديد:</p><pre class="php ipsCode prettyprint">class UserTableSeeder extends Seeder {

   public function run()
   {
      DB::table('users')-&gt;delete();
      User::create(array('email' =&gt; 'foo@bar.com'));
   }

}
</pre><p>لتنفيذ عملية البذر التي قمنا بإنشائها فإننا نستخدم الأمر التالي:</p><pre class="php ipsCode prettyprint">php artisan db:seed --class=UserTableSeeder</pre><p>وإن كان لديك أكثر من ملف بذر وترغب في تنفيذها كاملة بأمر واحد فإنه يكفي القيام بذلك عبر تحديد أسماء عمليات البذر المُراد تنفيذها في صنف/ملف <span style="font-family:'courier new', courier, monospace;"><code>DatabaseSeeder</code></span> الذي ستجده داخل مُجلد <span style="font-family:'courier new', courier, monospace;"><code>app/database/seeds</code></span> على النحو التالي:</p><pre class="php ipsCode prettyprint">class DatabaseSeeder extends Seeder {

   public function run()
   {
      $this-&gt;call('UserTableSeeder');
      $this-&gt;call('PostTableSeeder');
   }
}</pre><p><span style="font-size:14px;">وبعد ستحتاج إلى تنفيذ الأمر</span></p><pre class="php ipsCode prettyprint">php artisan db:seed</pre><p>الذي سيقوم بقراءة الملف واستدعاء عمليات البذر بشكل مُتوال<br>بإمكانك أيضا تنفيذ عمليات البذر مُباشرة بعد تحديث عمليات التهجير على الشكل التالي:</p><pre class="php ipsCode prettyprint">php artisan migrate:refresh --seed</pre><h2>توليد بيانات تجريبية باستخدام Faker</h2><p>بالرغم من أن هذه الخُطوة ليست ضرورية، إلا أنه في الكثير من الحالات ستحتاج إلى بيانات تجريبية أقرب ما تكون إلى البيانات الحقيقية للتجريب عليها. فمثلا سترغب في استخدام أسماء مُستخدمين "حقيقيين" وعناوين بريد إلكتروني، وعناوين منازل، إضافة إلى أسماء المُدن وأرقام هواتف وما إلى ذلك. بطبيعة الحال فإنه بالإمكان الاكتفاء بملفات البذر وإدخال تلك البيانات بطريقة شبه يدوية، إلا أن هناك حلا آخر يُسهّل عليك ذلك إن استعنت بمكتبة Faker للحصول على هذه البيانات.<br>بداية سنحتاج إلى "تنصيب" Faker وذلك على النحو التالي:<br>قم بالتعديل على ملف <span style="font-family:'courier new', courier, monospace;"><code>composer.json</code></span> وإضافة التالي:</p><pre class="php ipsCode prettyprint">"require-dev":{
"fzaninotto/faker": "1.5.*@dev"
},</pre><p>أو قم بإضافة <code> "<span style="font-family:'courier new', courier, monospace;">fzaninotto/faker": "1.5.*@dev"</span></code> إن كان حقل <span style="font-family:'courier new', courier, monospace;"><code>require-dev</code></span> مُتوفرا في الملف.<br>بعدها قم بتنفيذ الأمر <span style="font-family:'courier new', courier, monospace;"><code>php artisan update</code></span> ليقوم <span style="font-family:'courier new', courier, monospace;">artisan</span> بتحميل الملفات المطلوبة.<br>في غالب الأحوال ستحتاج إلى إنشاء مُستخدم غير عشوائي إلى جانب البيانات التجريبية، وعليه يُفضل إنشاؤه أولا قبل توليد البيانات العشوائية.</p><pre class="php ipsCode prettyprint">$user = User::create(array(
   'username' =&gt; 'djug',
   'first_name' =&gt; 'Youghourta',
   'last_name' =&gt; 'Benali',
   'email' =&gt; 'djug@someNewProject.com',
   'password' =&gt; Hash::make('MySuperPassword')
));

$faker = Faker\Factory::create();

for ($i = 0; $i &lt; 25; $i++)
{
   $user = User::create(array(
   'username' =&gt; $faker-&gt;userName,
   'first_name' =&gt; $faker-&gt;firstName,
   'last_name' =&gt; $faker-&gt;lastName,
   'email' =&gt; $faker-&gt;email,
   'password' =&gt; Hash::make('Password')
));
</pre><p><span style="font-size:14px;">في هذا المثال قمنا بإنشاء 25 مُستخدم يحملون أسماء بشر (وليس مُجرد حروف عشوائية) إضافة إلى عناوين بريد إلكتروني.</span></p><p>تسمح مكتبة Faker بتوليد شتى أنواع الحقول التي قد تحتاجها والتي يُمكن الحصول على نُسخ مُوطنة ومُترجمة منها، فمثلا يُمكن توليد أسماء عربية وعناوين فرنسية وما إلى ذلك.<br>للمزيد حول مكتبة Faker قم بإلقاء نظرة على<a rel="external nofollow" href="https://github.com/fzaninotto/Faker"> مُستودع المشروع على github</a><br>وللمزيد حول جميع أنواع العمليات التي يُمكن القيام بها على الهجرات: <a rel="external nofollow" href="http://laravel.com/docs/schema">Schema Builder</a></p>
]]></description><guid isPermaLink="false">1</guid><pubDate>Sun, 07 Sep 2014 22:31:00 +0000</pubDate></item></channel></rss>
