Skip to main content

الدرس الثامن: بناء صفحة تعديل في الLaravel 5

الجزء 8: أستخدام الForm component

في هذا الجزء سنتعلم كيف نستخدم الForm component طريقة تنزيله وتهيئته والعمل معه وأضافة حقول داخل الForm وكيف نعمل Form Model Binding اي يمكن تضمين الكائن مع الForm واضافة معلوماته داخل حقول ال  Form بتطبيق عملي على صفحة تعديل الخبر edit

الLaravel ذكية لتمييز بين الparameter المزودة في الدالة, حيث الorder غير مهم مثلاً:
عند أنشاء توجيه للURL التالية في ملف الroutes.php :

get(‘news/{slug}’,’NewsContorller@show’);

وفي ملف ال NewsController.php في دالة الshow تلاحظ ترتيب قيم الparameter غير مهم:

Public function show($slug , news $news){}
Public function show(news $news , $slug){}


وكذلك من مميزات الlaravel امكانية عمل method injection  للكائن, كما تلاحظ في الدالتين اعلاه استخدمنا Eloquent Model الذي هو news $news ك parameter  , وكذلك سنستخدمة عند انشاء دالة جديدة لتعديل الأخبار اي سيصبح لدينا ثلاث دوال تستخدم نفس الEloquent Model (‘News’)  عن طريق عمل Method Injection للدالة بهذا الشكل:

Public function index(news $news){}
Public function show(news $news , $slug){}
Public function edit(news $news , $slug){}


يمكن تقليص الكود عن طريق انشاء دالة انشائية للClass نفسه, بدل استدعاء الEloquent Model (‘News’)  ثلاث مرات , سنستدعيه مرة واحدة فقط في دالة ال__construct  كالأتي:

 Private $news;
Public function index(news $news){
   $this->news = $news
}

وبهذا سنحذف الEloquent Model(‘News’) من الدوال الثلاث وسنشير له فقط داخل الدالة لأنه سبق وتم انشاءهُ في دالة ال__construct كالأتي:
Public function index(){
$this->news->get();
}
Public function show($slug){
$this->news->whereSlug($slug)->first();
}
Public function edit($slug){
$this->news->whereSlug($slug)->first();
}

والأن سأقوم بأنشاء دالة لتعديل الأخبار, اول شيء يجب عمل توجيه لتلك الدالة في ملف routes.php:
get(‘news/{slug}/edit’,’NewsContorller@edit’);

  وبعدها الroutes.php  سيقوم بتوجيهنا لدالة edit الموجودة في ملف NewsController , سأنشأ تلك الدالة كالأتي:
Public function edit($slug){
$news = $this->news->whereSlug($slug)->first();
return view(‘news.edit’,compact(‘news’);
}


والController  بدوره سيسترجع الواجهة edit مع تمرير كائن الnews المراد التعديل عليه.

والأن للجزء الهام لهذا اليوم, انشاء الForm الذي عن طريقه سنعدل بيانات الخبر, يمكن ذلك بالطريقة العادية والمباشرة عند طريق كتابة كود الHTML الخاص بالForm , ولكن بما اننا نستعمل Laravel  يمكن استخدام عنصر الForm الذي سيسهل طريقة كتابة الكود, قبل استخدام الForm Component يتوجب علينا ادخال الPackage  الخاص بذلك العنصر وتهيئته للعمل معه,

لأدراج ذلك العنصر عن طريق استخدام الComposer:
ملاحظة: قبل كل شيء يوجد خطأ باستخدام الComposer في انظمة الWindows عند طلب الPackage من http://packgist.org يحدث فشل بفتح الأتصال عن طريق http الا عن طريق https يمكن تعديل ذلك بكتابة الكود التالي في ملف الcomposer.json الموجود في ملف المشروع:
    "repositories": [
      {
         "type":"composer",
         "url" :"https://packagist.org"
      },
      {"packagist":false}
      ],





وبعد ذلك يمكنك طلب الForm component عن طريق كتابة الأمر التالي في نافذة الأوامر وبأستخدام الcomposer:

C:\Users\Administrator\Desktop\Second_app\second_app>composer require illuminate/html

ملاحظة: يجب تطبيق الأمر اعلاه على الملف الذي يحتوي على ملفات المشروع لأن الForm component سيدرج ضمن مجلد الVendor



الخطوة الأخيرة الواجب عملها قبل استخدام الForm component  في الViews وهي تهيئة ذلك العنصر للأستخدام عن طريق اضافة الأسطر البرمجية التالية في ملف config\app.php:
ضمن الService Providers ادرج الكود التالي:
'Illuminate\Html\HtmlServiceProvider',


وضمن الأسماء المستعارة aliases للClasses ادخل الكود البرمجي التالي:
'Form'      => 'Illuminate\Html\FormFacade',



وبذلك انتهى تحميل الForm Component وتمت تهيئته للعمل معهJ

في الواجهة الخاصة بتعديل الأخبار edit.blade.php يمكن استخدام الForm component  بأبسط صورة كالأتي:
{{Form::open()}}
{{Form::close()}}

ولكن عند زيارة صفحة تعديل لأحد الأخبار يظهر التالي!!!


السبب لأن الأقواس المزدوجة تعمل على الهروب من HTML TAG لغرض امني , لكن في حالتنا هذه نريد الHTML TAG  أن تعمل وليس الهروب منها , يمكن ذلك بكتابة الكود اعلاه بالشكل التالي:
{!! Form::open() !!}
{!! Form::close() !!}
حيث استبدلت احد الأقواس بعلامتين تعجب معناها انا اعرف ماذا افعل لا تهرب من الHTML TAG J
الناتج كالأتي:


السؤال المحير الأن اين الFORM؟!
الجواب: بما ان الForm لا يحتوي على Fields مثل Text  و الTextarea وغيرها فلا يتم اظهار شيء ولكن ماخلف الصفحة الكود موجود للForm:



والأن لأدراج العناصر في الForm مثل الtext والSubmit والTextarea وغيرها يمكنك معرفة ذلك من الFormBuilder.php الموجود في المسار التالي:
C:\Users\Administrator\Desktop\Second_app\second_app\vendor\illuminate\html

لندرج بعض العناصر الرئيسية لتعديل احد اخبار الموقع:
نحتاج الى Text field لتعديل اسم الخبر title
نحتاج الى Textarea field لتعديل محتوى الخبر content
نحتاج الى Submit button لحفظ التغيير

يوجد شيء جداً مهم يجب معرفته وهو كيفية نضمن الكائن الذي يتوجب تعديله في الForm وهذا يسمى ب Form Model binding , الفائدة منه نستطيع من الكائن ادراج قيمه في الحقول,
والكود البرمجي لعمل ذلك في غاية السهولة فقط اشر الى استخدام الmodel:
{!! Form::model($news) !!}
ملاحظة: في الكود اعلاه سيتم تضمين الكائن في الForm وكذلك سيفتح الTag  الخاص بعمل الForm
كما حددنا سابقاً الحقول المراد ادراجها في الForm
  Text field for title
{!! Form::text('title') !!}
 Textarea field for content
{!! Form::textarea('content') !!}
Submit button
{!! Form::submit('Update') !!}

والكود البرمجي النهائي سيكون بالشكل التالي:



ماذا سيحدث عن زيارة صفحة تعديل احد الأخبار؟! لنجرب ذلك:


سنرى بأن الحقول ملئُت بصورة تلقائية بخصائص الكائن الذي ضمن داخل الForm والسبب لأن خصائص الكائن له تسميه حقول نفس تسمية الحقول name  في الForm


في اي حقل من حقول الForm مثل الText اول قيمة تكون هي اسم الحقل, ثاني قيمة تكون قيمة الحقل لاحظ اذا كتبت قيمة معينة ستستبدل قيمة الكائن بهذه القيمة في هذه الحالة اجعلها null , ثالث قيمة خصائص properties او سمات attributes الHTML 5 مثلأً يمكن اضافة class لهذا الحقل في القيمة الثالثة كالأتي:

{!! Form::text('title',null,['class'=>'form_txt']) !!}
{!!Form::textarea('content',null,['class'=>'form_txtA']) !!}


قمت بتعديل الStyle :
.form_txt, .form_txtA{
  padding: 10px;
  border: 1px solid #ddd;
  font-family:'Arial','Helvetica';
  color:#777;
  font-size:15px;
  display:block;
}
.form_txt{
  width: 320px;
  height: 20px;
  margin-bottom: 10px;
}
.form_txt:focus, .form_txtA:focus{
color:#000;
}



الناتج بعد عمل الstyle:



بقى لدينا شيء واحد فقط وهو الى اين سنتجه اذا ضغطنا على زر update؟!
طبعاً في الForm component الURL الأفتراضية ستكون موجهة لصفحة ذاتها وبطريقة الPOST
لتعديل الURL مثلاُ عند الضغط على زر الupdate اريد توجيهي للخبر ذاته مع تحديث الخبر المعدل ونوع الطريقة request method تكون PATCH
الجواب سيكون في غاية السهولة فقط عدل قيمتين عند تضمين الModel  مع الForm  كالأتي:
{!!Form::model($news,['url'=>'news/'.$news>slug,'method'=>'PATCH']) !!}

حيث ان الURL تشير الى الخبر ذاته كالأتي: /news/{slug} هذا التوجيه موجود داخل ملف الroutes.php  ولكن طريقة طلبه Request Method تكون GET وليس PATCH؟!! حيث اذا ضغطت على الزر سيظهر خطأ عن وجود توجيه لURL مع طريقة طلبه بPATCH الغير موجودة في الroutes.php
الحل بأضافة هذا التوجيه في ملف الroutes.php  كالأتي:
patch('news/{slug}','NewsController@update');
ملاحظة: المتصفحات لا تعرف الRequest method  من نوع patch والlaravel يعمل على انشاء حقل خفي مع أعطاء قيمة الPATCH كالأتي:
<input name="_method" type="hidden" value="PATCH">


والأن تم انشاء التوجية وعمل الForm بقي شيء واحد وهو عمل الدالة في الNewsController.php التي ستطلب قيم الكائن الجديدة من الحقول وتخزينها كقيم جديدة لذلك الكائن.
سأقوم بأنشاء الدالة في ملف NewsController وسأسترجع قيمة توضح ان توجيهي صحيح عند الضغط على زر update:
public function update($slug)
    {
        return 'yes it\'s working !!';
    }

والأن لمعرفة كيفية طلب القيم من حقول الForm فقط للتوضيح سأستخدم دالة الdebug :
Die in dump dd():
public function update($slug)
    {
        dd(\Request::all());
        dd(\Request::input());
        dd(\Request::get('title'));
    }
حيث عند استخدام الclass  request مع دالة الall ستسترجع كل القيم داخل الform بمصفوفة KEY => VALUE
وعند استخدام ال request class مع دالة الinput ستسترجع كل قيم الأدخال  بمصفوفة KEY => VALUE
وعند استخدام الrequest class مع دالة الget ستسترجع قيمة واحدة فقط المحدد اسمها name


الغرض من استخدام الRequest class اعلاه هو لمعرفة كيفية استخدامه لأسترجاع القيم من الform في الدالة التالية,
والأن لنكمل كود دالة الupdate في الNewsController لاحظ عند الضغط على زرupdate تكون الURL المحددة بهذا الشكل:
News/{slug}
قيمة الslug قد تم تمريرها للroutes.php والذي بدوره اما ان يقوم بتحويلها لدالة update مباشرة او قد نعمل Route model binding ونسترجع الكائن مباشرة ولكن للسهولة سأقوم بتحويل تلك القيمة مباشرةً اي ان في دالة الupdate يجب تحديد parameter تستقبل الslug وايضاً عمل method injection  للRequest class الذي سيسترجع قيم من الForm وبهذا يصبح لدينا قيمتين داخل دالة الupdate
public function update($slug, Request $request)
    {
    }

ثاني شيء نسترجع الكائن حسب قيمة الSlug  والذي سنعدل حقوله لاحقاً:

$news = $this->news->whereSlug($slug)->first();



ملاحظة: لا تنسى عمل ال__construct :
private $news;
public function __construct(news $news)
{
     return $this->news = $news;   
}






والجزء الأخير هو بتعديل كل حقل للكائن حسب المسترجع عن طريق الكائن $request كالأتي وبعدها تحويلنا للnews page:
$news->title = $request->get('title');
$news->content = $request->get('content');
$news->save();
       
return redirect('news');

يصبح الكود النهائي لدالة الupdate:
public function update($slug, Request $request)
    {
        $news = $this->news->whereSlug($slug)->first();
        $news->title = $request->get('title');
        $news->content = $request->get('content');
        $news->save();
       
        return redirect('news');
       
    }



والنتيجة عند عمل تعديل كالأتي:




كما لاحظت في دالة الupdate قمت بتحديد كل حقل من الكائن $news مع تجديده بقيمة مسترجعة من حقل  الForm  
يوجد طريقة ادراج كل قيم الForm مع قيم الكائن عن طريق استخدام دالة fill:

$news->fill(['title'=>$request->get('title'),'content'=>$request->get('content')]);


ولكن عند عمل تحديث لخبر معين سيظهر خطاً  MassAssignmentException
 سبب هذا الخطأ اننا نمرر كل الحقول دفعة واحدة لقاعدة البيانات والLaravel  تحمينا من هذا النوع من الأختراقات الذي قد يكون مصحوب بكود استرجاع بيانات او وضع بيانات حساسة!!!
ولحل ذلك قم بتحديد اي من الحقول التي ستعتبر fillable اي قابلة للملأ عن طريق اضافة  الحقول التي تعتبر fillable في ملف news eloquent model:

protected $fillable = ['title','content'];


ملاحظة: اذا قم بتحديد الحقل title في الnews eloquent model ك fillable field اذاً باقي المعلومات التي سيدرجها المستخدم سيتم اهمالها فقط الحقل الذي مع اسم title سيتم ادراجه.

وكذلك يوجد طريقة اسهل لكتابة الكود اعلاه وهي:

$news->fill($request->input())->save();


وبهذا سيختصر كود دالة الupdate ليصبح بهذا الشكل:

public function update($slug, Request $request)
{
        $news = $this->news->whereSlug($slug)->first();
        $news->fill($request->input())->save();
        return redirect('news');
}





والأن ننهي الجزء لهذا اليوم بأضافة كود التحقق في واجهة الshow.blade.php ما اذا كان الكائن $news يحتوي على معلومات واذا لم يحتوي على معلومات لا يتم اظهار كود الHTML  حوله:
@if($news->content)
<article class="news_content"> {!! nl2br($news->content) !!} </article>
@endif
وكذلك سأضيف رابطين داخل اي صفحة خبر في show.blade.php:
<a href="/news">Back to News</a><br />
<a href="/news/{{ $news->slug }}/edit">Edit this News</a>

Comments

Popular posts from this blog

PART #2: Registration and Login System Tutorial Using PHP and MYSQL

PART #2: Registration and Login System Tutorial Using PHP and MYSQL Registration and login system using PHP and MySQL database, in this part you will do the following: 1- Creating the registration page. 2- Validating the registration form. 3- Sending the activation link on successful registration. note: you can find the mailserver tool here: [MailServerTool] Good luck. PHP,Mysql,Programming,web development,How to,Technology,web programming,web project ideas,safaa al-hayali,saf3al2a,Registration and login,Registration and login in php,php and mysql login system,registration system using php and mysql,login and register php,login and register php with database,database,php tutorial,learn php,tutorial

How To Play .srt Subtitles File in Windows Media Player

How To Play .srt Subtitles File in Windows Media Player links: https://sourceforge.net/projects/wmpsub/ wmp,.srt Subtitles File in Windows Media Player,How To Play .srt Subtitles File in Windows Media Player,How To,Safaa Al-Hayali,saf3al2a,srt subtitle in WMP,Windows,Windows Media Player,media,.ass,local subtitles

Virtual Box : How to Increase Disk Size - Windows

How to increase disk size or disk storage in oracle virtual box the command you have to use: vboxmanage.exe modifymedium "[YourPathToVdiFileOfYourVirtualMachine]" --resize [NUMBER] virtual,box,vbox,oracle,partition,size,disk,increase,resize,windows,10,microsoft,vdi,vboxmanage,configuration,Safaa AL-Hayali,saf3al2a,Oracle,VirtualBox,How to,windows 10