Laravel/validation

من موسوعة حسوب
مراجعة 19:47، 13 أكتوبر 2018 بواسطة تسنيم-ولهازي (نقاش | مساهمات) (أنشأ الصفحة ب' == التحقق (validation) == == مقدّمة == يوفّر Laravel عدّة طرق مختلفة للتحقّق من صحّة البيانات الواردة للت...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

التحقق (validation)

مقدّمة

يوفّر Laravel عدّة طرق مختلفة للتحقّق من صحّة البيانات الواردة للتطبيقك. يستخدم صنف وحدة التحكّم الأساسي في Laravel الخاصيّة ValidatesRequests التي توفّر طريقة ملائمة للتحقق من صحة الطلب HTTP الوارد بمجموعة متنوّعة من قواعد التحقق الفعّالة.

بداية سريعة في التحقّق

لمعرفة المزيد عن ميزات التحقق الفعالة في Laravel ، دعنا نلقي نظرة على مثال كامل من التحقق من صحّة استمارة وعرض رسائل الخطأ على المستخدم.

تعريف المسارات

لنفترض أولًا أنّ لدينا المسارات التالية المحدّدة في ملفّنا routes/web.php:

Route::get('post/create', 'PostController@create');

Route::post('post', 'PostController@store');

سيعرض المسار GET استمارة للمستخدم لإنشاء منشور مدوّنة جديد بينما سيخزّن المسار POST منشور المدونة الجديد في قاعدة البيانات.

إنشاء وحدة التحكّم

فلنلقي في الخطوة التالية نظرة على وحدة تحكم بسيطة تتعامل مع هذه المسارات. سنترك التابع store فارغًا حاليًّا:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     *  إظهار الاستمارة لإنشاء منشور مدوّنة جديد
     *
     * @return Response
     */
    public function create()
    {
        return view('post.create');
    }

    /**
     * إنشاء منشور مدوّنة جديد
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
       // تحقّق وتخزّن المنشور الجديد ...
    }
}

كتابة منطق التحقّق

نحن الآن مُستعدّون لملء التابع store بالمنطق للتحقق من مشاركة المدوّنة الجديدة. لذلك، سنستخدم التابع validate المقدّم من الكائن Illuminate\Http\Request. إذا نجحت قواعد التحقّق، ستواصل التعليمات البرمجيّة التنفيذ بشكل طبيعي؛ ولكن في حالة فشل التحقق من الصحّة، سيُطرح استثناء وتُرسل استجابة الخطأ المناسبة إلى المستخدم تلقائيًا. ستُنشئ في حالة طلب HTTP تقليدي استجابة إعادة توجيه، في حين تُرسل استجابة JSON لطلبات AJAX.

لفهم التابع validate بشكل أفضل، فلنعد مرّة أخرى إلى التابع store :

/**
 *  تخزين منشور المدوّنة الجديد
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

   // منشور المدونة صالح ...
}

كما ترى نُمرّر قواعد التحقق المرغوبة للتابع validate. ومرّة أخرى، إذا فشل التحقّق من الصحّة، ستُنشئ الاستجابة المناسبة تلقائيًا. إن نجحت عمليّة التحقّق، ستستمر وحدة تحكّمنا في العمل بشكل طبيعي.

التوقف عند أوّل فشل تحقّق

قد ترغب أحيانًا في إيقاف تشغيل قواعد التحقق من صحّة خاصيّة (attribute) ما بعد أول فشل في التحقّق. للقيام بذلك، عيّن القاعدة bail على السمة:

$request->validate([
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

في هذا المثال، إذا فشلت القاعدة unique مع الخاصيّة title، لن يتحقّق من القاعدة max. سيتم التحقق من القواعد بالترتيب الذي عُيّنت عليه.

ملاحظة حول الخاصيات المتداخلة

تستطيع تحديد معاملاتك 'المتداخلة"، إن احتوى طلبك HTTP عليها، في قواعد تحقّقك باستخدام الصيغة "نقطة":

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'author.name' => 'required',
    'author.description' => 'required',
]);

عرض أخطاء التحقق

لكن ماذا لو لم تتجاوز معاملات الطلب الوارد قواعد التحقق المحددة؟ كما ذكرنا سابقًا، سيُعيد Laravel توجيه المستخدم تلقائيًا إلى موقعه السابق. بالإضافة إلى ذلك، ستومض جميع أخطاء التحقق تلقائيًا إلى الجلسة.

مرة أخرى، لاحظ أننا لم نضطر لربط رسائل الخطأ صراحة بالواجهة في مسارنا GET. ويرجع ذلك لتحقّق Laravel من وجود أخطاء في بيانات الجلسات وربطها تلقائيًا بالواجهة إذا كانت متوفرة. سيكون المتغيّر ‎$errors نسخة من Illuminate\Support\MessageBag. لمزيد من المعلومات حول العمل مع هذا الكائن راجع توثيقه.

ملاحظة: يرتبط المتغيّر errors$ بالواجهة عبر البرمجيّة الوسيطة Illuminate\View\Middleware\ShareErrorsFromSession التي تُوفّرها مجموعة برمجيّات web الوسيطة. عند تطبيق هذه البرمجيّة الوسيطة، سيصبح المتغيّر ‎$errors متاحًا دائمًا في واجهاتك مما يتيح لك افتراض أن المتغيّر ‎$errors مُعرّف دائمًا ويمكن استخدامه بأمان.

إذًا في مثالنا هذا سيُعاد توجيه المستخدم إلى تابع وحدة تحكّمنا create عند فشل عملية التحقق مما يسمح لنا بعرض رسائل الخطأ في الواجهة:

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- Create Post Form -->

ملاحظة حول الحقول الاختيارية

يحتوي Laravel افتراضيًّا على البرمجيّتين الوسيطتين TrimStrings و ConvertEmptyStringsToNull في مكدّس برمجيّات تطبيقك الوسيطة العامة. تورد قائمة هذه البرمجيّات الوسيطة في المكدس من طرف الصنف App\Http\Kernel. وبسبب هذا، ستحتاج غالبًا لوضع علامة على حقول طلبك "الاختيارية" كقيمة nullable إن لم تُرد أن يعتبر المحقّق القيم null غير صالحة. على سبيل المثال:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
    'publish_at' => 'nullable|date',
]);

نُحدّد في هذا المثال أن الحقل publish_at يكون إما ذو قيمة null أو تاريخ صالح. إن لم يُضف المُحدّد nullable لتعريف القاعدة، سيعتبر المُدقّق القيمة null غير صالحة.

طلبات وتحقّق AJAX

في هذا المثال استخدمنا نموذجًا تقليديًا لإرسال البيانات إلى التطبيق. ولكن العديد من التطبيقات تستخدم طلبات AJAX. عند استخدام التابع validate أثناء طلب AJAX ، لن يُولّد Laravel استجابة إعادة توجيه. بدلاً من ذلك، يُولّد Laravel استجابة JSON تحتوي على جميع أخطاء التحقق من الصحة. ستُرسل هذه الاستجابة JSON برمز حالة HTTP 422.

التحقّق من صحّة طلب استمارة

إنشاء طلبات الاستمارة

قد ترغب في إنشاء "طلب استمارة" من أجل سيناريوهات التحقق الأكثر تعقيدًا. طلبات الاستمارات هي أصناف طلبات مخصّصة تحتوي على منطق التحقق من الصحة. لإنشاء صنف طلب استمارة، استخدم الأمر make:request Artisan CLI:

php artisan make:request StoreBlogPost

سيوضع الصنف المُنشئ في المُجلّد app/Http/Requests. إن لم يوجد هذا الدليل، سيُنشأ عند تنفيذ الأمر make:request . فلنضف بعض قواعد التحقق إلى التابع rules:

/**
 * احصل على قواعد التحقق من الصحة التي تنطبق على الطلب.
 *
 * @return array
 */
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

ملاحظة: تستطيع كتابة أي تلميح على النوع تحتاج إليه ضمن توقيع التابع rules. سيُستبان تلقائيًا عبر حاوي خدمات Laravel. كيف إذن تُقيّم قواعد التحّقق؟ كل ما عليك فعله هو التلميح على نوع الطلب في تابع وحدة تحكّمك. يُتحقّق من صحّة طلب الالاستمارة الوارد قبل مناداة تابع وحدة التحكّم ممّا يعني أنه لا حاجة لكركبة وحدة تحكّمك بأي منطق للتحقّق من الصحة:

/**
 * تخزين منشور المدونة الوارد.
 *
 * @param  StoreBlogPost  $request
 * @return Response
 */
public function store(StoreBlogPost $request)
{
   // الطلب الوارد صالح...
  // جلب بيانات الإدخال الصالحة ...

    $validated = $request->validated();
}

في حالة فشل التحقّق من الصحّة، ستُولّد استجابة إعادة توجيه لإعادة إرسال المستخدم لموقعه السابق. كما ستُموّض (flash) الأخطاء للجلسة كي تكون متاحة للعرض. إن كان الطلب طلب AJAX، ستُردّ استجابة HTTP برمز الحالة 422 للمستخدم بما في ذلك تمثيل JSON لأخطاء التحقق من الصحة.

إضافة خطافات لاحقة إلى طلبات النموذج (Adding After Hooks To Form Requests)

إن رغبت في إضافة خطاف "لاحق" إلى طلب نموذج، تستطيع استخدام التابع withValidator. يستقبل هذا التابع أداة التحقق المبنية بالكامل ممّا يسمح لك بمناداة أي من توابعها قبل تقييم قواعد التحقق من الصحة:

/**
 * إعداد نسخة المُحقّق 
 *
 * @param  \Illuminate\Validation\Validator  $validator
 * @return void
 */
public function withValidator($validator)
{
    $validator->after(function ($validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}

تخويل طلبات الاستمارة (Authorizing Form Requests)

يحتوي صنف طلب الاستمارة أيضًا على تابع authorize. تستطيع التحقق ضمن هذا التابع ما إذا امتلك المستخدم المصادق عليه فعلًا سلطة تحديث مورد معيّن. يمكنك على سبيل المثال، تحديد ما إذا كان المستخدم يملك بالفعل تعليق مدوّنة يحاول تحديثه:

/**
 * حدد ما إذا كان المستخدم مخولًا لعمل هذا الطلب.
 *
 * @return bool
 */
public function authorize()
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}

نظرًا لأن جميع طلبات الاستمارات تُوسّع صنف طلب Laravel الأساسي، نستطيع استخدام التابع user للوصول إلى المستخدم المصادق عليه حاليًا. لاحظ أيضًا مناداة التابع route في المثال أعلاه. يمنحك هذا التابع إمكانيّة الوصول إلى معاملات URI المحدّدة في المسار المُنادى، مثل المعامل {comment} في المثال التالي:

Route::post('comment/{comment}');

إن ردّ التابع authorize القيمة false، ستُردّ استجابة HTTP مع رمز حالة 403 تلقائيًّا ولن يُنفّذ تابع وحدة تحكّمك. إذا كنت تخطط لوضع منطق تخويل (authorization logic) في جزء آخر من تطبيقك، عليك رد القيمة true من التابع authorize:

/**
 * حدد إذا كان المستخدم مخولًا لعمل هذا الطلب أو لا.
 *
 * @return bool
 */
public function authorize()
{
    return true;
}

ملاحظة: تستطيع كتابة أي تلميح على النوع تحتاج إليه ضمن توقيع التابع authorize. ستُستبان تلقائيًا عبر حاوي خدمات Laravel.

تخصيص رسائل الخطأ

يمكنك تخصيص رسائل الخطأ المستخدمة من طرف طلب الاستمارة عن طريق إعادة تعريف التابع messages. يجب أن يردّ هذا التابع مصفوفة من أزواج خاصيّة / قاعدة ورسائل الخطأ المطابقة لها:

/**
 * احصل على رسائل خطأ قواعد التحقق المُعرّفة .
 *
 * @return array
 */
public function messages()
{
    return [
        'title.required' => 'A title is required',
        'body.required'  => 'A message is required',
    ];
}

إنشاء مُتحقّقي الصحّة يدويًّا (Manually Creating Validators)

إن لم ترغب باستخدام التابع validate في الطلب، تستطيع إنشاء نسخة من متحقّق الصحّة يدويًا باستخدام واجهة Validator الساكنة. يُولّد التابع make في الواجهة الساكنة نسخة مُتحقّق جديدة:

<?php

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * تخزين مشاركة مدوّنة جديدة.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
            return redirect('post/create')
                        ->withErrors($validator)
                        ->withInput();
        }

        // Store the blog post...
    }
}

أوّل مُتغيّر وسيط يمرّر إلى التابع make هو البيانات تحت التحقّق من الصحة. المتغيّر الوسيط الثاني هو قواعد التحقق التي يجب تطبيقها على البيانات.

بعد فحص فشل التحقّق من صحة الطلب، تستطيع استخدام التابع withErrors لتمويض رسائل الخطأ للجلسة. عند استخدام هذا التابع، سيُشارك المتغيّر ‎$errors تلقائيًا مع واجهاتك بعد إعادة التوجيه ممّا يسمح لك بعرضها  بسهولة على المستخدم. يقبل التابع withErrors مُتحقّق و MessageBag أو array (مصفوفة) PHP.

إعادة التوجيه التلقائيّة

إن رغبت في إنشاء نسخة مُتحقّق يدويًا مع الاستفادة من إعادة التوجيه التلقائية التي يقّدمها تابع الطلبات validate، تستطيع مناداة التابع validate على نسخة مُتحقّق موجودة. سيُعاد توجيه المستخدم تلقائيًا إذا فشل التحقق من الصحّة أو في حالة طلب AJAX ستُرد استجابة JSON:

Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();

حقائب الأخطاء المسمّاة (Named Error Bags)

قد ترغب في تسمية MessageBag من الأخطاء إن امتلكت عدّة استمارات على صفحة واحدة، ممّا يسمح لك باسترداد رسائل الخطأ الخاصة باستمارة معيّنة. مرّر اسمًا ما كالمتغيّر الوسيط الثاني إلى withErrors:

return redirect('register')
            ->withErrors($validator, 'login');

يمكنك بعدها الوصول إلى نسخة MessageBag المسمّاة من المتغيّر errors$:

{{ $errors->login->first('email') }}

خطاف التحقق من الصحة اللاحق (After Validation Hook)

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

$validator = Validator::make(...);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add('field', 'Something is wrong with this field!');
    }
});

if ($validator->fails()) {
    //
}

التعامل مع رسائل الخطأ

ستحصل، بعد مناداة التابع errors على نسخة Validator على نسخة Illuminate\Support\MessageBag والتي تحتوي على مجموعة متنوّعة من التوابع الملائمة للعمل مع رسائل الخطأ. يمثّل أيضًا المتغيّر ‎$errors المتاح تلقائيًّا لجميع الواجهات نسخة من الصنف MessageBag.

استرداد أول رسالة خطأ بالحقل (Retrieving The First Error Message For A Field)

استخدم التابع first لاسترداد أول رسالة خطأ لحقل معيّن:

$errors = $validator->errors();

echo $errors->first('email');

استخدم التابع get إن أردت استرداد مصفوفة تحتوي جميع رسائل حقل معين:

foreach ($errors->get('email') as $message) {
   //
}

إن كنت تتحقق من حقل مصفوفة بالاستمارة، تستطيع استرداد جميع الرسائل لكل عنصر من عناصر المصفوفة على حدة باستخدام الحرف *:

foreach ($errors->get('attachments.*') as $message) {
   //
}

التحقق من وجود الرسائل بالحقل

يمكن استخدام التابع has للتأكّد من وجود أي رسائل خطأ بحقل معيّن:

if ($errors->has('email')) {
   //
}

رسائل الخطأ المخصّصة

تستطيع عند اللزوم استخدام رسائل خطأ مخصّصة للتحقق من الصحة بدلًا من الرسائل الافتراضية. توجد عدّة طرق لتحديد الرسائل المخصّصة. أولًا، تستطيع تمرير الرسائل المخصّصة كالمتغيّر الوسيط الثالث للتابع Validator::make:

$messages = [
    'required' => 'The :attribute field is required.',
];

$validator = Validator::make($input, $rules, $messages);

سيُستبدل في هذا المثال النص البديل (placeholder) المسمّى attribute: بالاسم الفعلي للحقل تحت التحقق. يمكنك أيضًا الاستفادة من النصوص البديلة (place-holder) الأخرى في رسائل التحقق من الصحة. على سبيل المثال:

$messages = [
    'same'    => 'The :attribute and :other must match.',
    'size'    => 'The :attribute must be exactly :size.',
    'between' => 'The :attribute value :input is not between :min - :max.',
    'in'      => 'The :attribute must be one of the following types: :values',
];

تحديد رسالة مخصّصة لخاصيّة معيّنة

قد ترغب أحيانًا في تحديد رسائل خطأ مخصّصة لحقل معيّن فقط. تستطيع استخدام التدوين "نقطة". حدّد أولًا اسم الخاصيّة، متبوعًا بالقاعدة:

$messages = [
    'email.required' => 'We need to know your e-mail address!',
];

تحديد الرسائل المخصّصة في ملفات اللغة

في معظم الحالات، ستُحدّد غالبًا رسائلك المخصّصة في ملف لغة بدلًا من تمريرها مباشرة إلى المتحقّق Validator. أضف رسائلك إلى المصفوفة custom في ملف اللغة resources/lang/xx/validation.php.

'custom' => [
    'email' => [
        'required' => 'We need to know your e-mail address!',
    ],
],

تحديد خاصيّات مخصّصة في ملفات اللغة

إن رغبت في استبدال الجزء attribute: من رسالة تحقّقك باسم خاصيّة مخصصة تستطيع تحديد الاسم المخصص في المصفوفة attributes لملف لغتك resources/lang/xx/validation.php:

'attributes' => [
    'email' => 'email address',
],

قواعد التحقّق المتاحة

تجد أدناه قائمة بجميع قواعد التحقق المُتوفّرة ووظيفتها:

Accepted

Active URL

After (Date)

After Or Equal (Date)

Alpha

Alpha Dash

Alpha Numeric

Array

Bail

Before (Date)

Before Or Equal (Date)

Between

Boolean

Confirmed

Date

Date Equals

Date Format

Different Digits

Digits Between

Dimensions (Image Files)

Distinct E-Mail

Exists (Database)

File

Filled

Greater Than

Greater Than Or Equal

Image (File)

In

In Array

Integer

IP Address

JSON

Less Than

Less Than Or Equal

Max

MIME Types

MIME Type By File Extension

Min

Not In

Not Regex

Nullable

Numeric

Present

Regular Expression

Required

Required If

Required Unless

Required With

Required With All

Required Without

Required Without All

Same

Size

String

Timezone

Unique (Database)

URL