التحقق (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';
});
ملاحظة: كل ما تفعله الملحقة "الضمنية" هو الإشارة لكون الخاصيّة مطلوبة. أنت من يقرر بعدها بطلان الخاصيّة المفقودة أو الفارغة.