التحقق (validation) في Laravel

من موسوعة حسوب

يوفّر 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

accepted

يجب أن تكون قيمة الحقل قيد التحقّق yes ،on ،1،  أو true. يفيد ذلك في التحقق من قبول "شروط الخدمة".

Active_url

يجب على الحقل قيد التحقّق أن يكون تسجيلًا A أو AAAA حسب التابع dns_get_record PHP.

After:date

يجب أن تكون قيمة الحقل تحت التحقّق بعد تاريخ معيّن. ستُمرّر التواريخ إلى الدالّة strtotime PHP:

'start_date' => 'required|date|after:tomorrow'

تستطيع تحديد حقل آخر لتقارن التاريخ معه بدلًا من تمرير سلسلة تاريخ لتقيّمها strtotime:

'finish_date' => 'required|date|after:start_date'

After_or_equal:date

يجب أن تكون قيمة الحقل تحت التحقق لاحقة أو مُساوية للتاريخ المحدّد. راجع القاعدة After لمزيد من المعلومات.

Alpha

يجب أن يكون محتوى الحقل تحت التحقق أبجديًّا بالكامل.

Alpha_dash

يمكن للحقل تحت التحقّق أن يحتوي على حروف أبجديّة أو رقميّة (alphanumeric) إضافةً إلى شرطات (dashes) وشرطات سفلية (underscore).

Alpha_num

يجب أن يتكّون محتوى الحقل تحت التحقق من أحرف أبجديّة ورقميّة.

Array

يجب أن يكون الحقل تحت التحقق مصفوفة PHP array.

bail

إيقاف العمل بقواعد التحقق من الصحّة بعد فشل التحقّق الأوّل.

before:date

يجب أن تكون قيمة الحقل تحت التحقّق سابقة للتاريخ المحدّد. ستُمرّر التواريخ للدالّة strtotime PHP.

before_or_equal:date

يجب أن تكون قيمة الحقل تحت التحقّق سابقة أو مساوية للتاريخ المحدّد. ستُمرّر التواريخ للدالّة strtotime PHP.

between:min,max

يجب أن يكون حجم الحقل تحت التحقق بين الحدّين الأدنى min والأقصى max. تقيّم السلاسل النصيّة والقيم العدديّة (numerics) والمصفوفات والملفات حسب نفس القاعدة size.

boolean

يجب أن يكون ممكنًا وضع قيمة منطقيّة (boolean) بالحقل تحت التحقّق. الإدخالات المقبولة هي true و false و 1 و 0 و "1" و "0".

Confirmed

يجب أن يكون للحقل تحت التحقق حقل مطابق foo_confirmation. إذا كان الحقل تحت التحقق كلمة سر password مثلا، يجب أن يوجد حقل مطابق password_confirmation في الإدخالات.

date

يجب أن يكون الحقل تحت التحقق تاريخًا صالحًا وفقًا للدالّة strtotime PHP.

date_equals:date

يجب أن تساوي قيمة الحقل تحت التحقق للتاريخ المحدّد. ستُمرّر التواريخ للدالّة strtotime PHP.

date_format:format

يجب أن يطابق تنسيق الحقل تحت التحقّق التنسيق المحدد. عليك استخدام إما date أو date_format عند التحقق من صحة الحقل لا كليهما.

different:field

يجب أن تكون قيمة الحقل تحت التحقق مختلفة عن field.

digits:value

يجب أن تكون قيمة الحقل تحت التحقق رقميّة (numeric) ويجب أن يكون طولها value.

digits_between:min,max

يجب أن يكون طول الحقل تحت التحقق بين الحدّين الأدنى min والأقصى max المحدّدين.

dimensions

يجب أن يكون الملف تحت التحقّق صورة تلتزم بقيود الأبعاد المُحدّدة بمعاملات القاعدة:

'avatar' => 'dimensions:min_width=100,min_height=200'

القيود المتاحة هي: min_width ،max_width ،min_height ،max_height ،width ،height ،ratio. يجب تمثيل قيد النسبة (ratio) كالعرض مقسومًا على الطول. يمكن تحديد هذا إمّا بكسر مثل 3/2 أو عدد عشري (float) مثل 1.5:

'avatar' => 'dimensions:ratio=3/2'

تستطيع استخدام التابع Rule::dimensions بما أنّ هذه القاعدة تتطلّب عدّة متغيّرات وسيطة لبنائها بسلاسة:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'avatar' => [
        'required',
        Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
    ],
]);

distinct

يجب أن يخلو الحقل تحت التحقق من أي قيم مكررة عند العمل بالمصفوفات.

'foo.*.id' => 'distinct'

email

يجب تنسيق الحقل تحت التحقّق كعنوان بريد إلكتروني.

Exists:table,column

يجب أن يوجد الحقل تحت التحقّق في جدول قاعدة بيانات المحدّد.

الاستخدام الأساسي للقاعدة Exists

'state' => 'exists:states'

إن لم يُحدّد الخيار column سيُستخدام اسم الحقل.

تحديد اسم عمود مخصص

'state' => 'exists:states,abbreviation'

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

'email' => 'exists:connection.staff,email'

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

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function ($query) {
            $query->where('account_id', 1);
        }),
    ],
]);

file

يجب أن يكون الحقل تحت التحقق ملفًا محمّلًا بنجاح.

filled

يجب ألّا يكون الحقل تحت التحقق فارغًا إن وُجد.

gt:field

يجب أن يكون الحقل تحت التحقّق أكبر من الحقل المحدّد field. يجب أن يكون الحقلان من نفس النوع. تُقيّم السلاسل النصيّة، والقيم العدديّة، والمصفوفات، والملفات حسب نفس القاعدة size.

Gte:field

يجب أن يكون الحقل تحت التحقق من الصحّة أكبر أو مساوي للحقل المحدّد field. يجب أن يكون الحقلان من نفس النوع. تُقيّم السلاسل النصيّة، والقيم العدديّة، والمصفوفات، والملفات حسب نفس القاعدة size.

image

يجب أن يكون الحقل تحت التحقق صورة (jpeg أو png أو bmp أو gif أو svg).

..,in:foo,bar

يجب تضمين الحقل تحت التحقق من الصحة في قائمة القيم المحدّدة. وبما أنّ هذه القاعدة تتطلب منك غالبًا أن تستخدم التابع implode على المصفوفة (يجمِع التابع implode‎ عناصر مصفوفة لتشكِّل سلسلةً نصيةً)، تستطيع استخدام التابع Rule::in لإنشاء القاعدة بسلاسة:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'zones' => [
        'required',
        Rule::in(['first-zone', 'second-zone']),
    ],
]);

in_array:anotherfield

يجب أن يوجد محتوى الحقل تحت التحقق ضمن قيم حقل آخر anotherfield.

integer

يجب أن يكون الحقل تحت التحقق عددًا صحيحًا طبيعيًّا.

ip

يجب أن يكون الحقل تحت التحقّق عنوان IP.

ipv4

يجب أن يكون الحقل تحت التحقق من الصحة عنوان IPv4.

ipv6

يجب أن يكون الحقل تحت التحقق من الصحة عنوان IPv6.

json

يجب أن يكون الحقل تحت التحقّق سلسلة JSON صالحة.

lt:field

يجب أن تكون قيمة الحقل تحت التحقق أصغر من قيمة الحقل المحدّد field. يجب أن يكون الحقلان من نفس النوع. تُقيّم السلاسل النصيّة، والقيم العدديّة، والمصفوفات، والملفات حسب نفس القاعدة size.

lte:field

يجب أن تكون قيمة الحقل تحت التحقق أقل أو مساوية لقيمة الحقل المحدّد field. يجب أن يكون الحقلان من نفس النوع. تُقيّم السلاسل النصيّة، والقيم العدديّة، والمصفوفات، والملفات حسب نفس القاعدة size.

max:value

يجب أن تكون قيمة الحقل تحت التحقق أقل من القيمة المحدّدة value. تُقيّم السلاسل النصيّة، والقيم العدديّة، والمصفوفات، والملفات حسب نفس القاعدة size.

...,mimetypes:text/plain

يجب أن يُطابق الملف تحت التحقق أحد الأنواع MIME المحدّدة:

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

لتحديد النوع MIME للملف المُحمّل، ستُقرأ محتويات الملف وسيحاول الإطار تخمين النوع MIME والذي قد يكون مختلفًا عن نوع MIME الذي قدّمه العميل.

...,mimes:foo,bar

يجب أن يحتوي الملف تحت التحقّق على نوع MIME يتوافق مع إحدى الإضافات المدرجة.

الاستخدام الأساسي للقاعدة MIME

'photo' => 'mimes:jpeg,bmp,png'

تتحقق هذه القاعدة بالفعل من نوع MIME للملف بقراءة محتوياته ثم تخمين النوع MIME رغم أنك تحتاج فقط لتحديد الامتدادات.

يمكن العثور على قائمة كاملة لأنواع MIME وامتداداتها المقابلة في الموقع التالي:https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

Min:value

يجب أن يكون للحقل تحت التحقق حد قيمة أدنى value. تُقيّم السلاسل النصيّة، والقيم العدديّة، والمصفوفات، والملفات حسب نفس القاعدة size.

...,not_in:foo,bar

يجب ألّا يوجد الحقل تحت التحقق في قائمة القيم المحددة. يمكن استخدام التابع Rule::notIn:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'toppings' => [
        'required',
        Rule::notIn(['sprinkles', 'cherries']),
    ],
]);

not_regex:pattern

يجب ألّا يطابق الحقل تحت التحقّق التعبير النمطي (regular expression) المحدّد.

ملاحظة: عند استخدام الأنماط regex / not_regex، قد يكون تحديد القواعد في مصفوفة بدلًا من استخدام محددات أشرطة عموديّة (pipe delimiters أي "|") ضروريًّا، خاصة إذا كان التعبير النمطي يحتوي على خط عمودي (pipe character).

nullable

يمكن أن يكون الحقل تحت التحقّق ذا قيمة فارغة null. نرى فائدة هذه القاعدة خاصة عند التحقق من صحة بيانات بدائيّة (primitive) مثل السلاسل النصيّة والأعداد الصحيحة الطبيعيّة التي قد تحتوي على قيم null.

numeric

يجب أن يكون الحقل تحت التحقّق عدديّا.

present

يجب أن يوجد الحقل تحت التحقّق في بيانات الإدخال لكن يمكن أن يظل فارغًا.

regex:pattern

يجب أن يطابق الحقل تحت التحقّق التعبير النمطي (regular expression) المحدّد.

ملاحظة: عند استخدام الأنماط regex / not_regex قد يكون تحديد القواعد في مصفوفة بدلاً من استخدام محددات أشرطة عموديّة (pipe delimiters أي "|") ضروريًّا، خاصة إذا كان التعبير العادي يحتوي على خط عمودي  (pipe character).

Required

يجب أن يوجد الحقل تحت التحقق في بيانات الإدخال وألّا يكون فارغًا. يعتبر الحقل "فارغًا" إن تحقّقت أحد الشروط التالية:

  •     القيمة null .
  •     القيمة سلسلة نصيّة فارغة.
  •     القيمة مصفوفة فارغة أو كائن Countable فارغ.
  •     القيمة ملف مُحمّل بدون مسار.

...,Required_if:anotherfield,value

يجب أن يوجد الحقل تحت التحقق وأن لا يكون فارغًا إذا ساوى الحقل anotherfield أيّ قيمة value.

...,required_unless:anotherfield,value

يجب أن يوجد الحقل تحت التحقق وأن لا يكون فارغًا  إلّا إذا لم يوجد الحقل anotherfield أيّ قيمة value.

...,required_with:foo,bar

يجب أن يوجد الحقل تحت التحقق وأن لا يكون فارغًا  فقط إن وُجد أي من الحقول الأخرى المُحدّدة.

...,required_with_all:foo,bar

يجب أن يوجد الحقل تحت التحقق وأن لا يكون فارغًا فقط إن وُجدت كل الحقول الأخرى المُحدّدة.

...,required_without:foo,bar

يجب أن يوجد الحقل تحت التحقق وأن لا يكون فارغًا فقط إن لم يوجد أي من الحقول الأخرى المُحدّدة.

...,required_without_all:foo,bar

يجب أن يوجد الحقل تحت التحقق وأن لا يكون فارغًا فقط إن لم توجد كل الحقول الأخرى المُحدّدة.

same:field

يجب أن يطابق الحقل المُحدّد الحقل تحت التحقّق.

size:value

يجب أن يطابق حجم الحقل تحت التحقق القيمة المحددة. تعني القيمة بالنسبة للبيانات النصيّةعدد الأحرف. القيمة هي القيمة العدديّة المحدّدة بالنسبة للبيانات الرقمية. بالنسبة للمصفوفة، الحجم يُوافق count المصفوفة. بالنسبة للملفات، الحجم هو حجم الملف بالكيلوبايت.

string

يجب أن يكون الحقل تحت التحقق سلسلة نصيّة. إن رغبت في السماح للحقل بأن يكون أيضًا null، عن القاعدة nullable على الحقل.

timezone

يجب أن يكون الحقل ضمن التحقق مُعرّف منطقة زمنيّة صالحا وفقًا للدالّة timezone_identifiers_list PHP.

unique:table,column,except,idColumn

يجب أن يكون الحقل تحت التحقق فريدًا في جدول قاعدة بيانات محدّد. فسيُستخدم اسم الحقل إن لم يُحدّد الخيار column.

تحديد اسم عمود مخصص
'email' => 'unique:users,email_address'
اتصال قاعدة البيانات المخصّص (Custom Database Connection)

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

'email' => 'unique:connection.users,email_address'
إجبار قاعدة فريدة على تجاهل معرّف (ID) معيّن

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

لإعطاء المُتحقّق تعليمات تجاهل معرّف المستخدم (ID)، نستخدم الصنف Rule لتعريف القاعدة بسلاسة. سنحدّد في هذا المثال أيضًا قواعد التحقّق من الصحّة في مصفوفة بدلًا من استخدام الحرف | للفصل بين القواعد:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

تستطيع إن استخدم جدولك اسم عمود مفتاح أوّلي غير id تحديد اسم العمود عند مناداة التابع ignore:

'email' => Rule::unique('users')->ignore($user->id, 'user_id')

إضافة شروط Where أخرى (Adding Additional Where Clauses):

تستطيع أيضًا تحديد قيود استعلام إضافية بتخصيص الاستعلام باستخدام التابع where. فلنضف على سبيل المثال قيدًا يتحقّق من أن account_id يساوي 1:

'email' => Rule::unique('users')->where(function ($query) {
    return $query->where('account_id', 1);
})

url

يجب أن يكون الحقل تحت التحقّق عنوان URL صالح.

إضافة القواعد المشروطة

التحقّق من الصحّة عند الحضور

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

$v = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

في المثال أعلاه ، لن يُقبل الحقل email إلا إن وجد في المصفوفة data$.

ملاحظة: إذا كنت تحاول التحقق من صحّة حقل واجب الوجود لكن مع احتمال كونه فارغًا فراجع هذه الملاحظة في الحقول الاختيارية.

التحقق المشروط المعقّد (Complex Conditional Validation)

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

$v = Validator::make($data, [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

لنفترض أن تطبيقنا الويب مخصّص لهواة جمع الألعاب. إن سجّل جامع ألعاب نفسه بتطبيقنا وامتلك أكثر من 100 لعبة سنرغب بأن يشرح لنا سبب امتلاكه هذا العدد الكبير من الألعاب. ربما مثلًا يديرون متجرًا لبيع الألعاب أو لربما يستمتعون بالتجميع فقط. يمكننا استخدام التابع sometimes لإضافة هذا الشرط بشكل شرطي في النسخة Validator.

$v->sometimes('reason', 'required|max:500', function ($input) {
    return $input->games >= 100;
});

يمثّل المتغيّر الوسيط الأوّل المُمرّر إلى التابع sometimes اسم الحقل الذي نتحقّق منه شرطيًّا. المتغيّر الوسيط الثاني هو القواعد التي نود إضافتها. إذا ردّ Closure المُمرّر كالمتغيّر الثالث القيمة true ستُضاف القواعد. تجعل هذه الطريقة بناء عمليات التحقق الشرطية المعقدة سهلة جدّا. يمكنك حتى إضافة عمليات تحقّق شرطي لعدّة حقول في المرّة:

$v->sometimes(['reason', 'cost'], 'required', function ($input) {
    return $input->games >= 100;
});

ملاحظة: ستكون المعاملة ‎$input المُمرّرة إلى Closure نسخة من Illuminate\Support\Fluent ويمكن استخدامها للوصول إلى إدخالاتك وملفّاتك.

التحقق من المصفوفات

لا يجب أن يكون التحقق من صحّة حقول الإدخال المصفوفة صعبًا. تستطيع استخدام "النقطة" للتحقق من صحة الخاصيّات داخل المصفوفة. تستطيع إن احتوى الطلب HTTP الوارد مثلًا على حقل photos[profile]‎ التحقق من صحته كما يلي:

$validator = Validator::make($request->all(), [
    'photos.profile' => 'required|image',
]);

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

$validator = Validator::make($request->all(), [
    'person.*.email' => 'email|unique:users',
    'person.*.first_name' => 'required_with:person.*.last_name',
]);

تستطيع أيضًا استخدام الحرف * عند تحديد رسائل تحقّقك في ملفات لغتك، ممّا يُسهّل استخدام رسالة تحقّق واحدة للحقول المستندة على مصفوفة:

'custom' => [
    'person.*.email' => [
        'unique' => 'Each person must have a unique e-mail address',
    ]
],

قواعد التحقق المخصص

استخدام كائنات القاعدة

يوفر Laravel مجموعة متنوعة من قواعد التحقق المفيدة؛ قد ترغب مع ذلك في تحديد بعض قواعدك الخاصّة. استخدام كائنات القاعدة هي إحدى طرق تسجيل قواعد التحقق المخصّصة. تستطيع استخدام الأمر make:rule Artisan لتوليد كائن قاعدة جديد. فلنستخدم هذا الأمر لتوليد قاعدة تتحقّق من كون حروف سلسلة نصيّة كبيرة. سيضع Laravel القاعدة الجديدة في المُجلّد app/Rules:

php artisan make:rule Uppercase

نحن مستعدون لتعريف سلوك القاعدة بمجرد إنشائها. يحتوي كائن القاعدة على تابعين: passes و message. يتلقى التابع passes قيمة الخاصيّة واسمها يجب أن يردّ القيمة true أو القيمة false استنادًا على صلاحيّة  قيمة الخاصيّة. يجب أن يرد التابع message رسالة خطأ التحقق التي يجب استخدامها عند فشل التحقق من الصحّة:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
     * تحديد إذا مرّت قاعدة التحقق أم لا.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

تستطيع طبعًا مناداة المساعد trans من تابعك message إذا رغبت في رد رسالة خطأ من ملفات ترجمتك:

/**
 * Get the validation error message.
 *
 * @return string
 */
public function message()
{
    return trans('validation.uppercase');
}

تستطيع إرفاق القاعدة بعد تعريفها بمُتحقّق عبر تمرير نسخة من كائن القاعدة مع قواعد تحقّقك الأخرى:

use App\Rules\Uppercase;

$request->validate([
    'name' => ['required', 'string', new Uppercase],
]);

استخدام Closures

تستطيع إن احتجت لوظيفة (functionality) القاعدة المخصّصة مرة واحدة فقط في التطبيق استخدام Closure بدلًا من كائن القاعدة. يتلقى Closure اسم الخاصيّة وقيمة الخاصيّة وردّ نداء fail$ يجب مناداته في حالة فشل التحقق من الصحّة:

$validator = Validator::make($request->all(), [
    'title' => [
        'required',
        'max:255',
        function($attribute, $value, $fail) {
            if ($value === 'foo') {
                return $fail($attribute.' is invalid.');
            }
        },
    ],
]);

استخدام الإضافات

توجد طريقة أخرى لتسجيل قواعد التحقق المخصّصة وهي استخدام التابع extend على الواجهة الساكنة Validator. فلنستخدم هذا التابع داخل موفّر الخدمات لتسجيل قاعدة تحقّق مخصّصة:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
     * مهّد أي خدمات التطبيق.
     *
     * @return void
     */
    public function boot()
    {
        Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
            return $value == 'foo';
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

تستطيع أيضًا تمرير صنف وتابع للتابع extend بدلًا من Closure:

Validator::extend('foo', 'FooValidator@validate');

تعريف رسالة الخطأ

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

"foo" => "Your input was invalid!",

"accepted" => "The :attribute must be accepted.",

// باقي رسائل أخطاء التحقق من الصحة ...

قد تحتاج أحيانًا عند إنشاء قاعدة تحقّق مخصّصة لتعريف بدائل () مخصّصة لرسائل الخطأ. يمكنك ذلك عبر إنشاء متحقّق مخصّص كما هو موضح أعلاه ثم مناداة التابع replacer على الواجهة الساكنة Validator . تستطيع ذلك بفضل التابع boot موفّر الخدمات:

/**
 * مهّد أي خدمات التطبيق.
 *
 * @return void
 */
public function boot()
{
    Validator::extend(...);

    Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
        return str_replace(...);
    });
}

الإضافات الضمنية (Implicit Extensions)

عند التحقق من خاصيّة غير موجودة أو تحتوي على قيمة فارغة، كما حُدّد في القاعدة required، لا تُشغّل قواعد التحقّق العادية بما في ذلك الملحقات المخصّصة. لن تُشغّل القاعدة unique على قيمة null:

$rules = ['name' => 'unique'];

$input = ['name' => null];

Validator::make($input, $rules)->passes(); // true

كي تشغّل القاعدة حتى عند خلّو إحدى الخاصيّات، على القاعدة أن تشير ضمنيًّا (imply) لكونها مطلوبة. لإنشاء مثل هذا الامتداد "الضمني"، استخدم التابع ()Validator::extendImplicit:

Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
    return $value == 'foo';
});

ملاحظة: كل ما تفعله الملحقة "الضمنية" هو الإشارة لكون الخاصيّة مطلوبة. أنت من يقرر بعدها بطلان الخاصيّة المفقودة أو الفارغة.

مصادر