إنشاء استمارة اتصال في Laravel 5 باستخدام ميزة Form Request


محمد أحمد العيل

يوفر Laravel 5 ميزة جديدة تسمى استعلامات الاستمارة Form Requests تساعد في معالجة بيانات الاستمارة والتحقق من صحتها. ستتعلم في هذا الدرس كيفية إنشاء استمارة اتصال في Laravel 5 باستخدام الميزة المذكورة وإمكانيات Laravel في إرسال البريد الإلكتروني. سنعرض طوال الدرس لميزات وحيل تقنية تتعلق بالتطوير على Laravel.

larabel5-forms.thumb.png.eeb0527d80110ad

تتكون استمارة الاتصال من ثلاثة حقول هي اسم المستخدم، وعنوان بريده الإلكتروني والرسالة التي يود إرسالها.

01_form_contact.thumb.png.f9796ad532789d

ملحوظة: يفترض الدرس أن Laravel مثبت وجاهز للعمل.

نبدأ بإنشاء مشروع Laravel جديد (أسميته academy) ثم الدخول إلى المجلد:

laravel new academy
cd academy

يمكننا إنشاء متحكِّم Controller خاص بمعالجة استمارة الاتصال وعرضها إلا أننا سندمج هذه الوظيفة - للتسهيل - في المتحكِّم الذي يتولى الأمور الإدارية المتعلقة بالتطبيق. سننشئ لهذا الغرض متحكما باسم AboutController ونستخدم إجراءيْ create وstore لعرض استمارة الاتصال والتعامل معها (يقدم create الاستمارة عبر GET فيما يقدمها store عبر POST). سيستخدم AboutController إجراءات create ،index وstore فقط فسنكتفي بإنشاء متحكِّم بسيط عن طريق أمر artisan make:controller على النحو التالي:

$ php artisan make:controller --plain AboutController

Controller created successfully

نضيف كُنْيتيْن Aliases ضمن ملف app/Http/routes.php لتمكين الوصول إلى الاستمارة عبر المسار contact/:

Route::get('contact', 
  ['as' => 'contact', 'uses' => 'AboutController@create']);
Route::post('contact', 
  ['as' => 'contact_store', 'uses' => 'AboutController@store']);

ينشئ أمر artisan make:controller السابق متحكما خاويا، نتيجة استخدام خيار plain-- مع artisan. أي أنه يتوجب علينا إضافة دالتَيْ create وstore في متحكم AboutController. عدل على المتحكِّم ليبدو على النحو التالي:

<?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()
        {
        }
    }

 

ملحوظة: يوجد المتحكم ضمن المسار app/Http/Controllers الموجود ضمن مجلد المشروع. كل المسارات المذكورة في الدرس تُنسَب إلى مجلد المشروع.

ضبطنا إجراء create ليقدم عرضا View باسم contact.blade.php يوجد ضمن المسار resources/views/about.

العرض contact.blade.php غير موجود لحد الساعة. فلننشئه.

إنشاء استمارة الاتصال

يوفر Laravel ميزات عدة لتصْيِير Rendering استمارات HTML. سنستخدم نظام Blade للقَوْلَبة Templating، المضمن في Laravel، لإنشاء الاستمارة. أنشئ مجلدا باسم about في المسار resources/views/ ثم أنشئ داخله ملفا باسم contact.blade.php. وألصق المحتوى التالي:

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  {!! Html::style('css/form.css') !!}
  <title>Academy Contact</title>
</head>
<body>
    <div id="page-wrap">
        <h1>Academy contact</h1>

        <ul>
            @foreach($errors->all() as $error)
              <li>{{ $error }}</li>
            @endforeach
        </ul>

        <div id="contact-area">
            {!! Form::open(array('route' => 'contact_store', 'class' => 'form')) !!}


            {!! Form::label('Your Name') !!}
            {!! Form::text('name', null, array('required', 'placeholder'=>'Your name')) !!}

            {!! Form::label('Your E-mail Address') !!}
            {!! Form::text('email', null,array('required', 'placeholder'=>'Your e-mail address')) !!}


            {!! Form::label('Message') !!}
            {!! Form::textarea('message', null, array('required', 'id'=>'Message', 'cols'=>'20', 'rows'=>'20','placeholder'=>'Your message')) !!}

            {!! Form::submit('Contact Us!', array('class'=>'submit-button')) !!}

            {!! Form::close() !!}
        
        </div>
    </div>
</body>
</html>

سنعود لشرح هذه الشفرة بعد قليل.

1- تفعيل مكون HTML

في الاستمارة أعلاه استخدمنا مُنشِئ الاستمارات Form builder الموجود في مكون HTML؛ هذا المكون غير مفعل افتراضيا في Laravel 5. لتفعيله نفذ الخطوات التالية.

  • عدل على ملف composer.json الموجود في مجلد المشروع وأضف التعليمة التالية ضمن خانة require:

"illuminate/html": "~5.0"

تصبح خانة require على الهيئة التالية بعد إضافة السطر (انتبه للفاصلة , في نهاية السطر الذي يسبق التعليمة التي أضفناها):

"type": "project",
    "require": {
      "php": ">=5.5.9",
      "laravel/framework": "5.1.*",
      "illuminate/html": "~5.0"
    },
  • حدث اعتماديات Dependencies المشروع عبر الأمر:

    composer update

     

  • بعد انتهاء التحديث عدل على ملف config/app.php وأضف السطر التالي ضمن مصفوفة Providers (انتبه للفواصل):

'Illuminate\Html\HtmlServiceProvider',

في نفس الملف أضف السطرين التاليين لمصفوفة Aliases:

'Form'      => 'Illuminate\Html\FormFacade',
'Html'      => 'Illuminate\Html\HtmlFacade',

2- شرح آلية تصيير الاستمارة

نعود لشرح طريقة إنشاء الاستمارة الموجودة عبر نظام Blade. نبدأ بأول تعليمة:

{!! Html::style('css/form.css') !!}

نطلب من نظام القوالب تحميل ملف CSS لاستخدامه في الصفحة. سيحمَّل ملف CSS في المكان الذي استُدعِيت فيه دالة style التابعة لصنف Html الذي عرَّفناه في الخطوة السابقة ضمن مصفوفة Aliases، هو وصنف Form. انتبه لكتابة اسم الصنف بنفس طريقة تعريفه في المصفوفة (Html وليس HTML). ملف form.css يوجد ضمن مجلد فرعي (باسم css) من مجلد Public. توضع الملفات المتاحة للعموم (مثل CSS وJavaScript) داخل هذا المجلد.

ننتقل للتعليمتين:

{!! Form::open(array('route' => 'contact_store', 'class' => 'form')) !!}
...
{!! Form::close() !!}

تعمل الدالتان Form::open وForm::close() معا من أجل إنشاء وسوم Tags فتح وإغلاق الاستمارة على التوالي. تستقبل دالة Form::open مصفوفة تمثل معطيات إعداد مختلفة؛ مثل كنية route(الوِجهة) التي تشير إلى دالة store ضمن المتحكم AboutController، وclass التي تشير إلى صنف CSS المستخدَم لتنسيق الاستمارة. يُستخدَم إجراء POST افتراضيا إلا أنه يمكن إبداله بGET عبر تمريره في المعطى method على النحو التالي 'method' => 'post'. تضيف دالة Form::open حقلا مخفِيّا عبارة عن رمز _token للحماية من هجمات تزوير الطلب عبر الموقع Cross-site request forgery, CSRF.

ثم يأتي الدور على التعليمات التالية:

<ul>
  @foreach($errors->all() as $error)
    <li>{{ $error }}</li>
  @endforeach
</ul>

تستخدم هذه التعليمات لإظهار رسائل تحقق إذا كانت مُدخَلات المستخدم غير مناسبة لطبيعة الحقول (سنعود لها لاحقا، لا تنسها).

تظهر في ما بعد مجموعة من الدوال من أجل إنشاء حقول الاستمارة: Form::label لإنشاء لصائق Labels الحقول، Form::text لإنشاء حقول نصية، Form::textarea لإنشاء حقول نصية متعددة الأسطر، وForm::submit لإنشاء زر الإرسال. لاحظ أن دالتيْ Form::text وForm::text تحويان معطى باسم خاصية name الخاصة بالحقل (email، name وmessage على التوالي). أضفنا أيضا لكل حقل تشكيلة من الخيارات مثل أسماء أصناف التنسيقات وخصائص HTML.

يمكنك بعد حفظ الملف تنفيذ الأمر التالي (من مجلد المشروع) لتشغيل تشغيل خادوم الويب المضمن في Laravel وتجربة النتيجة:

php artisan serve

أدخل العنوان http://localhost:8000/contact في المتصفح لعرض صفحة الاستمارة.

ننتقل الآن، بعد إنشاء الاستمارة، لإعداد آلية التعامل مع محتوى الاستمارة وتمكين إرسال المقترحات عبرها.

إنشاء استعلام استمارة الاتصال

يضيف الإصدار الخامس من Laravel ميزة جديدة تعرف باستعلامات الاستمارة Form Requests؛ تهدف إلى وضع التصريح Authorization والتحقق من البيانات المرسَلة خارج المتحكِّمات وتغليفها ضمن صنف منفصل. نستخدم artisan لإنشاء استعلام Form request على النحو التالي:

$ php artisan make:request ContactFormRequest

ينشئ الأمر ملفا باسم ContactFormRequest.php مساره app/Http/Requests/ContactFormRequest.php.

يبدو هيكل الصنف، بعد حذف التعليقات، كما يلي:

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class ContactFormRequest extends Request
{
  public function authorize()
  {
    return false;
  }

  public function rules()
  {
     return [
      //
     ];
  }
}

تحدد دالة authorize ما إذا كان يُسمح للمستخدم الحالي بالتفاعل مع الاستمارة. نريد أن يكون أي مستخدم قادرا على التفاعل مع الاستمارة، لذا نعدل الدالة لتكون القيمة المُرجَعة true بدلا من false.

public function authorize()
{
  return true;
}

تعرِّف دالة rules قواعد التحقق المرتبطة بحقول الاستمارة. الحقول الثلاثة، email، name وmessage جميعها مطلوبة (required)؛ كما أن حقل البريد الإلكتروني يجب أن يحوي عنوانا بريديا صالحا. نعدل دالة rules لإدراج هذه القواعد.

public function rules()
{
  return [
    'name' => 'required',
    'email' => 'required|email',
    'message' => 'required',
  ];
}

توجد مدقِّقات Validators أخرى غير required وemail في Laravel للاستخدام عند الحاجة. لاحظ استخدام أكثر من مدقق في نفس الحقل مع الفصل بينها ب| مثل ما فعلنا مع حقل البريد الإلكتروني.

احفظ ملف ContactFormRequest.php ثم افتح المتحكِّم AboutController (الموجود في المسار app/Http/Controllers/AboutController.php) وعدل دالة store لتصبح على النحو التالي: …

use App\Http\Requests\ContactFormRequest;

class AboutController extends Controller {

  public function store(ContactFormRequest $request)
  {

     return \Redirect::route('contact')
           ->with('message', 'Thanks for contacting us!');

  }

}

لا تنس إضافة ;use App\Http\Requests\ContactFormRequest إلى المتحكم ليمكنه استخدام قواعد المصادقة المعرَّفة في الصنف ContactFormRequest.php الذي سيتولى التحقق من موافقة مُدخَلات المستخدم للقواعد الموضوعة ويظهر رسالة خطأ في حال أخلَّ المستخدم بإحداها. على سبيل المثال، إذا أدخل المستخدم عنوانا بريديا غير صالح فستظهر رسالة الخطأ التالية.

55a269ca7a4be_02___.thumb.png.23ddea0680

طبعا لن تظهر رسائل الخطأ من العدم. تتولى مصفوفة errors$ المستخدمة في ملف contact.blade.php إظهار هذه الرسائل. هل تذكر هذه الشفرة؟

<ul>
@foreach($errors->all() as $error)
  <li>{{ $error }}</li>
@endforeach
</ul>

 

نعود إلى ContactFormRequest.php. قد ترغب في إظهار رسالة (شكر مثلا) للمستخدم عند نجاح إرسال الاستمارة. تمكن إضافة رسالة سريعة ضمن دالة store. يضاف المتغير المُمرَّر للدالة تلقائيا إلى متغيرات الجلسة Session في Laravel مما يمكّن من استخدامها عبر الدالة Session::get. يمكِن على سبيل المثال استخدام الشفرة التالية لإظهار محتوى المتغير message في أي عرض (View) أثناء الجلسة:

@if(Session::has('message'))
  <div class="alert alert-info">
    {{Session::get('message')}}
  </div>
@endif

بقيت خطوة واحدة لتكون الاستمارة جاهزة لإرسال بريد إلكتروني. نحتاج لإعداد مكوِّن البريد في Laravel وإدماج وظيفة تسليم البريد إلى دالة store.

إعداد مكوِّن البريد في Laravel

يستخدم Laravel حزمة SwiftMailer لتوفير إمكانية إرسال بريد إلكتروني بيسر. كل ما عليك فعله هو ضبط الإعدادات الموجودة في ملف config/mail.php. نذكر في ما يلي بعض الإعدادات الموجودة في الملف.

  • driver: يدعم Laravel عدة تعريفات بريد مثل SMTP، دالة بريد PHP (mail)، خادوم بريد Sendmail وخدمتَيْ Mailgun وMandrill لتسليم البريد. يجب أن تضبط الإعدادات على التعريف المرغوب بالاختيار بين mailgun، sendmail، mail،smtp و mandrill
  • host: تعيين اسم المستضيف لخادوم البريد الإلكتروني (عند استخدام التعريف smtp).
  • port: تعيين اسم منفَذ خادوم البريد الإلكتروني (عند استخدام التعريف smtp).
  • from: إذا رغبت في أن تستخدم كل الرسائل المرسَلة نفس العنوان البريدي والاسم للمرسِل فبإمكانك ضبط إعدادات from وaddress المعرَّفة في هذه المصفوفة.
  • encryption: يحدد بروتوكول التعميّة Encryption المستخدَم لإرسال البريد الإلكتروني.
  • username: يعين اسم المستخدم في حال كان التعريف smtp.
  • password: كلمة سر المستخدم في حال كان التعريف smtp.
  • sendmail: مسار خادوم Sendmail إذا كانت قيمة driver هي sendmail.
  • pretend: يطلب هذا الإعداد من Laravl تجاهل التعريف المضبوط وإرسال البريد إلى سجل التطبيق بدلا منه. يناسب التطبيقات التي مازالت قيد التطوير والتجربة.

نأخذ مثالا لإعداد إرسال البريد في Laravel لاستخدام حساب بريد Google. غير الإعدادات التالية مثل ماهو مبيَّن.

  • أعط القيمة smtp للتعريف driver. هذه هي القيمة الافتراضية.
  • أبدل قيمة host إلى smtp.google.com
  • استخدم المنفذ port رقم 465.
  • أبدل التعميّة encryption إلى ssl.
  • استخدم حساب البريد الإلكتروني ضمن إعداد username.
  • اكتب كلمة سر حساب البريد الإلكتروني في إعداد password. تذكر أنه يجب، ضمن بيئة عمل فعلية، حفظ هذه المعلومات ومعلومات أخرى حساسة ضمن ملف env. في مشروعك أو في متغير البيئة في الخادوم.

احفظ التعديلات على ملف config/mail.php ثم عدل المتحكم AboutController ليبدو على النحو التالي:

public function store(ContactFormRequest $request)
{

  \Mail::send('emails.contact',
    array(
      'name' => $request->get('name'),
      'email' => $request->get('email'),
      'user_message' => $request->get('message')
   ), function($message)
   {
     $message->from('wj@wjgilmore.com');
     $message->to('wj@wjgilmore.com', 'Admin')->subject('Academy Feedback');
   });

  return \Redirect::route('contact')->with('message', 'Thanks for contacting us!');

}

الدالة Mail::send هي المسؤولة عن ابتداء عملية تسليم البريد، وتستقبل ثلاثة معطيات. يحدد المعطى الأول اسم العرض (View) المستخدم لقالب جسم (محتوى) البريد الإلكتروني. المعطى الثاني هو مصفوفة بالبيانات المتاحة للاستخدام في جسم البريد الإلكتروني. البيانات المتاحة في حالتنا هي تلك القادمة من استمارة الاتصال عبر الكائن request$. يمنح المعطى الثالث إمكانية تحديد خيارات إضافية للبريد الإلكتروني مثل المرسِل، المستقبِل والموضوع.

سنحتاج لإنشاء العرض الذي توجد به محتويات البريد. لذا سننشئ ملفا باسم contact.blade.php في المسار resources/views/emails. طبعا يمكنك تغيير اسم ومجلد العرض؛ إن فعلت فلا تنس التعديل على المتحكم AboutController بما يوافقك تغييراتك.

You received a message from academy.hsoub.com:

<p>
  Name: {{ $name }}
</p>

<p>
  {{ $email }}
</p>

<p>
  {{ $user_message }}
</p>

ملحوظة: يوجد سجل التطبيق في المسار storage/logs/laravel.log. عند إعطاء القيمة true لpretend ستحاكي إرسال بريد دون أن ترسله فعليا وسيظهر سطر يشبه التالي في السجل:

[2015-07-12 11:34:51] local.INFO: Pretending to mail message to: wj@wjgilmore.com

عُد، بعد حفظ التعديلات، إلى استمارة الاتصال؛ اكتب بيانات صحيحة ضمن حقول الاستمارة وأرسلها. يجب أن تصل الرسالة إلى البريد الموجود في دالة to (أي wj@wjgilmore.com في المثال).

قد تواجه مشاكل مع إعدادات Gmail بسبب التقييدات على تطبيقات الطرف الثالث في Gmail. راجع إعدادات حساب Google في هذه الحالة.

خاتمة

اخترنا عرض جميع المخرجات المذكورة في هذا الدرس باللغة الإنجليزية للتركيز على الخاصية المشروحة. إن أردت توطين Localization المثال واستخدام اللغة العربية فيمكنك كتابة العبارات العربية مباشرة في ملفات القوالب لكن ستبقى رسائل الخطأ باللغة الإنجليزية ويجب عليك إدراج رسائل خطأ خاصة بالعربية.

على العموم يُنصَح، لمن أراد توفير قابلية التوطين بسهولة، بعدم كتابة المُخرجات مباشرة في الشفرة Hard code بل إنشاء ملف بسلاسل المحارف Strings المستخدمة واستدعاء ملف اللغة المناسبة عن طريق دالة الترجمة trans. يُنشَأ مجلد لكل لغة مدعومة ضمن المسار resources/lang الذي يوجد فيه افتراضيا مجلد للغة الإنجليزية en به ملفات بالعبارات المستخدمة افتراضيا.

ترجمة بتصرف لمقال Creating a Contact Form in Laravel 5 Using the Form Request Feature لصاحبه Jason Gilmore



3 اشخاص أعجبوا بهذا


تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن