استقبال البيانات والتحقق منها Requests وValidation في Laravel
بعد أن تعلمنا في الدرس السادس كيفية استخدام Blade Templates و Views لبناء واجهات ديناميكية، أصبح بإمكاننا الآن إنشاء صفحات تحتوي على نصوص وقوائم وأزرار ونماذج Forms.
لكن بناء النموذج وحده لا يكفي.
تخيل أن لدينا نموذجًا لإنشاء مقال يحتوي على:
- عنوان المقال.
- محتوى المقال.
- البريد الإلكتروني للكاتب.
- تاريخ النشر.
عندما يضغط المستخدم على زر حفظ، يجب أن يستقبل Laravel هذه البيانات، ثم يتأكد من أنها صحيحة قبل أن يستخدمها أو يحفظها في قاعدة البيانات.
هنا يأتي دور HTTP Request وValidation.
Laravel توفر نظامًا قويًا للتعامل مع البيانات القادمة من المستخدم والتحقق منها باستخدام مجموعة كبيرة من قواعد Validation، كما توفر طريقة أكثر تنظيمًا باستخدام Form Requests عندما تصبح عمليات التحقق أكثر تعقيدًا.
في هذا الدرس سنتعلم :
- ما هو Request؟
- كيف نستقبل البيانات القادمة من Form؟
- الفرق بين GET وPOST.
- استخدام
Request. - قراءة بيانات المستخدم.
- إنشاء Form باستخدام Blade.
- استخدام
@csrf. - التحقق من البيانات باستخدام
validate(). - أهم قواعد Validation.
- عرض رسائل الخطأ.
- إعادة تعبئة النموذج بالبيانات القديمة.
- استخدام
old(). - إنشاء Form Request.
- استخدام
validated(). - التعامل مع الحقول الاختيارية.
- بناء نموذج عملي كامل لإنشاء مقال.
ما هو HTTP Request؟
عندما يفتح المستخدم صفحة في موقعك أو يرسل نموذجًا أو يضغط على زر يؤدي إلى رابط معين، يقوم المتصفح بإرسال HTTP Request إلى الخادم.
مثلًا عندما يفتح المستخدم:
/articles
قد يكون الطلب:
GET /articles
وعندما يرسل نموذج إنشاء مقال:
POST /articles
يحتوي الطلب على معلومات مختلفة يمكن أن يحتاج إليها التطبيق، مثل:
- البيانات المرسلة من Form.
- عنوان الصفحة المطلوبة.
- HTTP Method.
- Headers.
- Cookies.
- معلومات أخرى مرتبطة بالطلب.
في Laravel يمكننا الوصول إلى هذه المعلومات من خلال كائن:
Illuminate\Http\Request
وغالبًا نقوم بتمريره إلى Controller Method.
الفرق بين GET و POST في Laravel
قبل أن نبدأ، من المهم فهم الفرق بين أشهر طريقتين سنستخدمهما في Forms.
GET
يستخدم GET عادةً لطلب أو عرض البيانات.
مثل:
/articles
أو:
/articles/10
مثال:
Route::get('/articles', [ArticleController::class, 'index']);
عندما يزور المستخدم الرابط، يتم إرسال GET Request.
POST
يستخدم POST عادةً لإرسال بيانات إلى التطبيق لإنشاء أو معالجة شيء جديد.
مثل:
Route::post('/articles', [ArticleController::class, 'store']);
عندما يرسل المستخدم Form إنشاء مقال، يمكن أن تصل البيانات إلى store().
بالتالي يمكن أن تكون الدورة:
GET /articles/create
↓
عرض Form
↓
المستخدم يملأ البيانات
↓
POST /articles
↓
Controller
↓
Validation
↓
حفظ البيانات
Laravel تستخدم هذا النمط بكثرة في تطبيقات CRUD. وتوضح وثائق Validation الرسمية مثالًا مشابهًا يعتمد على Route لعرض النموذج ثم POST Route لمعالجة البيانات والتحقق منها.
إنشاء Form في Blade
لنبدأ بإنشاء صفحة تحتوي على نموذج لإضافة مقال.
أنشئ:
resources/views/articles/create.blade.php
واكتب:
@extends('layouts.app')
@section('title', 'إضافة مقال')
@section('content')
<h1>إضافة مقال جديد</h1>
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<div>
<label for="title">عنوان المقال</label>
<input
type="text"
name="title"
id="title"
>
</div>
<div>
<label for="body">محتوى المقال</label>
<textarea
name="body"
id="body"
></textarea>
</div>
<button type="submit">
حفظ المقال
</button>
</form>
@endsection
لدينا هنا Form يرسل:
title body
إلى Route اسمه:
articles.store
باستخدام:
POST
ما أهمية @csrf؟
لاحظ أننا كتبنا داخل Form:
@csrf
هذه خطوة مهمة جدًا في Forms التي ترسل طلبات إلى Laravel.
تقوم Laravel باستخدام CSRF Token لحماية التطبيق من نوع من الهجمات يسمى Cross-Site Request Forgery.
لذلك عندما تنشئ Form يرسل POST أو PUT أو PATCH أو DELETE إلى تطبيق Laravel، ستحتاج عادةً إلى إضافة:
@csrf
مثل:
<form method="POST" action="/articles">
@csrf
...
</form>
لا تعتبر @csrf مجرد سطر إضافي؛ اجعله عادة أساسية عند إنشاء Forms في Laravel.
إنشاء Routes للنموذج
في:
routes/web.php
يمكننا كتابة:
use App\Http\Controllers\ArticleController;
Route::get('/articles/create', [ArticleController::class, 'create'])
->name('articles.create');
Route::post('/articles', [ArticleController::class, 'store'])
->name('articles.store');
الـ Route الأول:
GET /articles/create
مسؤول عن عرض Form.
والـ Route الثاني:
POST /articles
مسؤول عن استقبال البيانات.
يمكننا التفكير في الأمر هكذا:
/articles/create
↓
create()
↓
Form
ثم:
Form ↓ POST /articles ↓ store() ↓ Validation ↓ حفظ البيانات
استقبال البيانات داخل Controller
افتح:
app/Http/Controllers/ArticleController.php
ثم أضف:
use Illuminate\Http\Request;
وبعدها:
public function store(Request $request)
{
//
}
الآن Laravel ستمرر Request إلى Method تلقائيًا.
يمكننا قراءة البيانات باستخدام:
$request->input('title')
مثل:
public function store(Request $request)
{
$title = $request->input('title');
return $title;
}
إذا أرسل المستخدم:
تعلم Laravel
ستكون قيمة:
$title
هي:
تعلم Laravel
قراءة أكثر من قيمة
يمكننا قراءة:
$request->input('title');
>و:
$request->input('body');
مثل:
public function store(Request $request)
{
$title = $request->input('title');
$body = $request->input('body');
return $title;
}
لكن هناك مشكلة مهمة:
هل يمكننا الوثوق بأن البيانات التي أرسلها المستخدم صحيحة؟
بالطبع لا.
قد يرسل المستخدم عنوانًا فارغًا.
أو نصًا طويلًا جدًا.
أو قيمة ليست من النوع المطلوب.
أو يترك بعض الحقول فارغة.
وهنا نحتاج إلى Validation.
ما هو Validation؟
Validation يعني التحقق من صحة البيانات القادمة إلى التطبيق.
مثلًا يمكننا تحديد قواعد مثل:
العنوان مطلوب. العنوان يجب أن يكون نصًا. العنوان لا يتجاوز 255 حرفًا. المحتوى مطلوب. البريد الإلكتروني يجب أن يكون صالحًا. السعر يجب أن يكون رقمًا.
بدون Validation قد تدخل بيانات غير صحيحة إلى التطبيق وقاعدة البيانات.
Laravel توفر عددًا كبيرًا من Validation Rules الجاهزة.
أول Validation باستخدام validate()
أبسط طريقة هي استخدام:
$request->validate()
مثال:
public function store(Request $request)
{
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
]);
//
}
هنا حددنا:
title
بأنه:
- مطلوب.
- نص.
- أقصى طول 255.
أما:
body
فهو:
- مطلوب.
- نص.
إذا نجحت Validation، يستمر تنفيذ Controller بشكل طبيعي.
أما إذا فشلت، تقوم Laravel بالتعامل مع نتيجة Validation وإعادة المستخدم إلى الصفحة السابقة في الطلبات التقليدية، مع توفير رسائل الأخطاء لعرضها في View.
فهم قاعدة required في Laravel
أبسط قاعدة:
'required'
تعني أن الحقل يجب أن يكون موجودًا وغير فارغ.
مثل:
'title' => ['required']
إذا لم يرسل المستخدم title بشكل صحيح، تفشل Validation.
قاعدة string في Laravel
يمكنك التأكد من أن القيمة نص باستخدام:
'string'
مثل:
'title' => ['required', 'string']
وهذا مفيد عندما تتوقع قيمة نصية.
قاعدة max في Laravel
يمكنك تحديد الحد الأقصى:
'max:255'
مثل:
'title' => ['required', 'string', 'max:255']
وبذلك لا تسمح بعنوان يتجاوز الحد المحدد.
قاعدة min في Laravel
يمكنك أيضًا تحديد الحد الأدنى:
'min:3'
مثل:
'title' => ['required', 'string', 'min:3', 'max:255']
وهذا يعني أن العنوان يجب أن يحتوي على عدد مناسب من الأحرف ضمن الحدود المحددة.
التحقق من البريد الإلكتروني
إذا كان لدينا:
يمكننا كتابة:
'email' => ['required', 'email']
مثل:
$request->validate([
'name' => ['required', 'string'],
'email' => ['required', 'email'],
]);
Laravel توفر قواعد متخصصة للبريد الإلكتروني، ويمكن أيضًا استخدام خيارات أكثر تقدمًا عندما تحتاج إلى مستوى تحقق إضافي.
التحقق من الأرقام
إذا كان لدينا سعر:
price
يمكننا استخدام:
'price' => ['required', 'numeric']
مثل:
$request->validate([
'name' => ['required', 'string'],
'price' => ['required', 'numeric'],
]);
وهذا مناسب في حالات مثل:
- أسعار المنتجات.
- الكميات.
- التقييمات.
- أرقام معينة.
قاعدة integer في Laravel
إذا كنت تتوقع رقمًا صحيحًا:
'quantity' => ['required', 'integer']
مثل:
'quantity' => ['required', 'integer', 'min:1']
وهذا مناسب عندما تكون القيمة:
1 2 3 4
وليس:
1.5
الحقول الاختيارية باستخدام nullable
ليس كل حقل يجب أن يكون مطلوبًا.
لنفترض أن لدينا:
publish_at
ويمكن للمستخدم تركه فارغًا.
يمكننا كتابة:
'publish_at' => ['nullable', 'date']
أي:
إذا كانت القيمة موجودة، يجب أن تكون تاريخًا صحيحًا. أما إذا كانت null فهي مسموحة.
وتشير وثائق Laravel 13 إلى أهمية nullable عند التعامل مع الحقول الاختيارية التي قد تتحول قيمها الفارغة إلى null بسبب Middleware الخاص بالتطبيق.
عرض رسائل Validation في Blade
بعد أن وضعنا Validation، نحتاج إلى إظهار الأخطاء للمستخدم.
يمكننا استخدام:
@error('title')
<p>{{ $message }}</p>
@enderror
مثال:
<label for="title">عنوان المقال</label>
<input
type="text"
name="title"
id="title"
>
@error('title')
<p>{{ $message }}</p>
@enderror
إذا كان العنوان غير صالح، يمكن عرض رسالة الخطأ المناسبة.
Laravel توفر أيضًا متغير:
$errors
داخل Views للتعامل مع رسائل Validation.
عرض جميع الأخطاء Laravel
يمكنك أيضًا عرض جميع الأخطاء في مكان واحد:
@if ($errors->any())
<div>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
وهذا مفيد خصوصًا في بداية المشروع أو عندما تريد عرض قائمة عامة بالأخطاء أعلى النموذج.
إعادة البيانات القديمة باستخدام old()
تخيل أن المستخدم ملأ Form كاملًا ثم نسي عنوان المقال.
ضغط:
حفظ
ففشلت Validation.
من غير الجيد أن تعيد الصفحة فارغة وتجبره على كتابة كل شيء من جديد.
هنا يمكننا استخدام:
old()
مثل:
<input
type="text"
name="title"
value="{{ old('title') }}"
>
إذا كان المستخدم كتب:
تعلم Laravel
ثم فشلت Validation بسبب حقل آخر، يمكن إعادة عرض:
تعلم Laravel
داخل الحقل.
وبالنسبة إلى textarea:
<textarea name="body">{{ old('body') }}</textarea>
وهذا يجعل تجربة المستخدم أفضل بكثير.
وضع قيمة افتراضية مع old()
يمكنك أيضًا توفير قيمة افتراضية:
{{ old('title', 'عنوان افتراضي') }}
إذا لم توجد قيمة قديمة، سيتم استخدام:
عنوان افتراضي
مثال كامل على Form مع Validation
لنقم الآن ببناء Form أكثر واقعية.
Controller
use Illuminate\Http\Request;
public function store(Request $request)
{
$validated = $request->validate([
'title' => ['required', 'string', 'min:3', 'max:255'],
'body' => ['required', 'string', 'min:10'],
'email' => ['required', 'email'],
]);
return redirect()
->route('articles.index')
->with('success', 'تم إرسال المقال بنجاح.');
}
لدينا هنا ثلاثة حقول:
title body email
وكل واحد لديه قواعد مختلفة.
إذا نجحت Validation، نحصل على البيانات التي اجتازت التحقق داخل:
$validated
وهذه نقطة مهمة جدًا.
بدلًا من الاعتماد على كل البيانات الموجودة في Request، أصبح لدينا مجموعة بيانات تم التحقق منها.
لماذا نستخدم $validated؟
لنفترض أن Request يحتوي على:
title body email admin unexpected_field
بينما قواعد Validation تسمح فقط بـ:
title body email
بعد Validation، من الأفضل أن تعتمد على:
$validated
بدل التعامل مع كل البيانات الواردة بشكل عشوائي.
مثلًا:
$validated = $request->validate([
'title' => ['required', 'string'],
'body' => ['required', 'string'],
]);
ثم:
$title = $validated['title']; $body = $validated['body'];
هذا يجعل الكود أكثر وضوحًا.
إعادة التوجيه بعد نجاح العملية
بعد نجاح Form، غالبًا لا نريد ترك المستخدم في نفس الطلب.
يمكننا استخدام:
return redirect()
->route('articles.index');
أو:
return redirect('/articles');
وفي تطبيقات CRUD، غالبًا يكون السيناريو:
POST ↓ Validation ↓ حفظ البيانات ↓ Redirect ↓ صفحة القائمة
وهذا يمنع بعض المشاكل التي قد تحدث عند إعادة إرسال Form بعد تحديث الصفحة.
إرسال رسالة نجاح
يمكننا أيضًا إرسال رسالة إلى الصفحة:
return redirect()
->route('articles.index')
->with('success', 'تم إنشاء المقال بنجاح.');
ثم في Blade:
@if (session('success'))
<div>
{{ session('success') }}
</div>
@endif
وهكذا تظهر للمستخدم رسالة مثل:
تم إنشاء المقال بنجاح.
سنستخدم هذا الأسلوب كثيرًا في تطبيقات CRUD.
Form Request
عندما يكون Controller صغيرًا، يمكن استخدام:
$request->validate()
مباشرة.
لكن ماذا يحدث عندما يصبح لدينا Form كبير وقواعد Validation كثيرة؟
يمكننا استخدام Form Request.
Form Request هو Class مخصص يجمع:
Validation Rules.
Authorization Logic.
منطق متعلق بالطلب.
ويمكن إنشاء Form Request باستخدام:
php artisan make:request StoreArticleRequest
وتقوم Laravel بوضعه داخل:
app/Http/Requests
وفقًا لوثائق Laravel الرسمية.
إنشاء StoreArticleRequest
نفذ:
php artisan make:request StoreArticleRequest
سيتم إنشاء:
app/Http/Requests/StoreArticleRequest.php
وستجد داخله Methods مثل:
authorize()
و:
rules()
كتابة Validation Rules داخل Form Request
يمكنك كتابة:
public function rules(): array
{
return [
'title' => ['required', 'string', 'min:3', 'max:255'],
'body' => ['required', 'string', 'min:10'],
'email' => ['required', 'email'],
];
}
وبذلك أصبح Validation منفصلًا عن Controller.
authorize()
Form Request يحتوي أيضًا على:
public function authorize(): bool
{
return true;
}
هذه Method تحدد ما إذا كان المستخدم مسموحًا له بتنفيذ العملية.
في البداية يمكن أن تكون:
return true;
لكن لاحقًا عندما نتعلم Authentication وAuthorization وPolicies، يمكن استخدام هذه Method للتحكم في الصلاحيات.
استخدام Form Request داخل Controller
بدلًا من:
public function store(Request $request)
نستخدم:
use App\Http\Requests\StoreArticleRequest;
public function store(StoreArticleRequest $request)
{
//
}
الميزة هنا أن Laravel تقوم بتنفيذ Validation قبل الوصول إلى Controller Method.
إذا نجحت Validation، يصل الطلب إلى:
store()
أما إذا فشلت، يتم التعامل مع الأخطاء وإعادة المستخدم بالطريقة المناسبة.
استخدام validated()
بعد نجاح Form Request، يمكنك الحصول على البيانات التي اجتازت Validation باستخدام:
$validated = $request->validated();
مثل:
public function store(StoreArticleRequest $request)
{
$validated = $request->validated();
// حفظ البيانات
return redirect()
->route('articles.index');
}
وهذا يجعل Controller نظيفًا جدًا.
متى أستخدم Request ومتى أستخدم Form Request؟
في المشاريع الصغيرة، يمكنك البدء بـ:
$request->validate([
...
]);
وهذا بسيط وسهل للمبتدئين.
لكن عندما تصبح عملية Validation كبيرة أو يتم استخدامها في أكثر من مكان، يكون Form Request أكثر تنظيمًا.
يمكنك التفكير بهذه الطريقة:
Validation بسيطة
↓
$request->validate()
أما:
Validation كبيرة ومعقدة
↓
Form Request
مثال كامل باستخدام Form Request
إنشاء Request
php artisan make:request StoreArticleRequest
القواعد
public function rules(): array
{
return [
'title' => ['required', 'string', 'min:3', 'max:255'],
'body' => ['required', 'string', 'min:10'],
];
}
Controller
use App\Http\Requests\StoreArticleRequest;
public function store(StoreArticleRequest $request)
{
$validated = $request->validated();
return redirect()
->route('articles.index')
->with('success', 'تم إنشاء المقال بنجاح.');
}
Form
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<input
type="text"
name="title"
value="{{ old('title') }}"
>
@error('title')
<p>{{ $message }}</p>
@enderror
<textarea name="body">{{ old('body') }}</textarea>
@error('body')
<p>{{ $message }}</p>
@enderror
<button type="submit">
حفظ
</button>
</form>
الآن أصبحت لدينا دورة كاملة:
Blade Form ↓ POST Request ↓ StoreArticleRequest ↓ Validation ↓ Controller ↓ Validated Data ↓ Database
سنضيف قاعدة البيانات في الدروس القادمة.
بعض قواعد Validation المهمة
هناك عدد كبير جدًا من قواعد Validation في Laravel، لكن كمبتدئ من المفيد أن تتعرف على أشهرها:
required
القيمة مطلوبة.
nullable
القيمة يمكن أن تكون null.
string
القيمة يجب أن تكون نصًا.
integer
القيمة يجب أن تكون عددًا صحيحًا.
numeric
القيمة يجب أن تكون رقمًا.
القيمة يجب أن تكون بريدًا إلكترونيًا صالحًا.
url
القيمة يجب أن تكون رابطًا صالحًا.
min
تحديد الحد الأدنى.
max
تحديد الحد الأقصى.
date
التحقق من التاريخ.
boolean
التحقق من قيمة منطقية.
confirmed
مفيد في حقول التأكيد مثل كلمة المرور.
Laravel توفر مجموعة واسعة من القواعد الإضافية، ويمكن الرجوع إلى وثائق Validation الرسمية لمعرفة التفاصيل والصيغ المتاحة.
Validation للحقول المتداخلة
Laravel تسمح أيضًا بالتحقق من بيانات متداخلة باستخدام صيغة النقطة.
مثل:
$request->validate([
'author.name' => ['required', 'string'],
'author.email' => ['required', 'email'],
]);
إذا كانت البيانات بهذا الشكل:
author
name
email
يمكنك الوصول إليها باستخدام هذه الصيغة.
هذه الميزة تصبح مفيدة جدًا عندما تتعامل مع Forms تحتوي على بيانات منظمة أو Arrays متداخلة.
التحقق من الحقول الفريدة
عند إنشاء حساب مستخدم مثلًا، قد نريد أن يكون البريد الإلكتروني غير مستخدم من قبل.
يمكن استخدام:
'email' => ['required', 'email', 'unique:users,email']
الفكرة هنا أن Laravel تتحقق من عدم وجود قيمة مكررة وفق قاعدة البيانات.
سنعود إلى هذه القاعدة بشكل أعمق عندما نصل إلى Database وEloquent.
التحقق من وجود قيمة في قاعدة البيانات
يمكن أيضًا استخدام:
exists
مثل:
'category_id' => ['required', 'exists:categories,id']
وهذا يعني أن category_id يجب أن تكون موجودة في جدول:
categories
داخل العمود:
id
هذه القواعد ستكون مهمة جدًا عندما نبدأ في التعامل مع العلاقات بين الجداول.
ماذا يحدث عند فشل Validation؟
من المهم أن تفهم دورة Validation.
لنفترض أن المستخدم أرسل:
title = "" body = "مقال"
ولدينا:
'title' => ['required'],
ستفشل Validation.
في الطلب التقليدي، Laravel تعيد المستخدم إلى الصفحة السابقة وتوفر رسائل الأخطاء والبيانات القديمة التي يمكن استخدامها في View.
ثم يمكننا عرض:
@error('title')
<p>{{ $message }}</p>
@enderror
واستخدام:
value="{{ old('title') }}"
وهكذا يحصل المستخدم على تجربة واضحة بدل ظهور خطأ غير مفهوم.
الفرق بين Validation في Controller وForm Request
يمكن تلخيص الفرق هكذا:
| الطريقة | الاستخدام |
|---|---|
$request->validate() | Validation بسيطة وسريعة |
| Form Request | Validation منظمة وأكثر تعقيدًا |
$request->validated() | الحصول على البيانات التي تم التحقق منها |
$errors | الوصول إلى أخطاء Validation داخل View |
@error | عرض خطأ حقل محدد |
old() | إعادة البيانات القديمة إلى Form |
هذه الأدوات سترافقك في معظم تطبيقات Laravel التي تحتوي على Forms.
مثال عملي شامل
لنقم ببناء Form بسيط لإنشاء مقال.
الخطوة الأولى: Route
Route::get('/articles/create', [ArticleController::class, 'create'])
->name('articles.create');
Route::post('/articles', [ArticleController::class, 'store'])
->name('articles.store');
الخطوة الثانية: Controller
public function create()
{
return view('articles.create');
}
ثم:
public function store(Request $request)
{
$validated = $request->validate([
'title' => ['required', 'string', 'min:3', 'max:255'],
'body' => ['required', 'string', 'min:10'],
]);
return redirect()
->route('articles.index')
->with('success', 'تم إنشاء المقال بنجاح.');
}
الخطوة الثالثة: View
@extends('layouts.app')
@section('title', 'إضافة مقال')
@section('content')
<h1>إضافة مقال</h1>
@if ($errors->any())
<div>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<div>
<label for="title">العنوان</label>
<input
type="text"
name="title"
id="title"
value="{{ old('title') }}"
>
@error('title')
<p>{{ $message }}</p>
@enderror
</div>
<div>
<label for="body">المحتوى</label>
<textarea
name="body"
id="body"
>{{ old('body') }}</textarea>
@error('body')
<p>{{ $message }}</p>
@enderror
</div>
<button type="submit">
حفظ المقال
</button>
</form>
@endsection
أصبح لدينا الآن نموذج حقيقي يستطيع:
- عرض Form.
- استقبال البيانات.
- حماية الطلب باستخدام CSRF.
- التحقق من البيانات.
- عرض الأخطاء.
- إعادة البيانات القديمة.
- إعادة توجيه المستخدم بعد النجاح.
أخطاء شائعة في Requests وValidation
1 - نسيان @csrf
من أكثر الأخطاء شيوعًا عند إنشاء POST Form:
<form method="POST">
بدون:
@csrf
اجعل إضافة @csrf عادة ثابتة في Forms التي تحتاجها.
2 - عدم تحديد name
إذا كتبت:
<input type="text" id="title">
بدون:
name="title"
فلن تحصل على الحقل باسم title ضمن بيانات Form كما تتوقع.
الصحيح:
<input
type="text"
name="title"
id="title"
>
3 - اختلاف اسم الحقل عن اسم Validation
إذا كان Form يحتوي على:
<input name="article_title">
ثم كتبت:
'title' => ['required']
فهناك عدم تطابق.
يجب أن تتفق أسماء الحقول مع Validation Rules.
4 - نسيان old()
ليس خطأ تقنيًا قاتلًا، لكنه يجعل تجربة المستخدم أسوأ، خصوصًا في Forms الكبيرة.
استخدم:
value="{{ old('title') }}"
عند الحاجة.
5 - قبول بيانات غير متحقق منها
لا تعتمد على:
$request->all()
كبديل عن Validation عندما تكون البيانات ستستخدم في عمليات حساسة.
الأفضل أن تتحقق من البيانات ثم تتعامل مع البيانات التي اجتازت Validation.
تحقق من البيانات عند دخولها إلى التطبيق
لا تنتظر حتى تصل البيانات إلى قاعدة البيانات ثم تكتشف أن هناك مشكلة.
استخدم Validation قبل المعالجة أو الحفظ.
استخدم قواعد واضحة
بدل:
'title' => ['required']
إذا كان لديك متطلبات إضافية، استخدم قواعد مناسبة:
'title' => [
'required',
'string',
'min:3',
'max:255'
]
استخدم Form Requests عند زيادة التعقيد
عندما يبدأ Controller بالامتلاء بقواعد Validation، انقلها إلى Form Request.
اعرض الأخطاء بوضوح
استخدم:
@error('field')
قرب الحقل الذي توجد فيه المشكلة.
لا تثق ببيانات المستخدم
حتى لو كان Form يحتوي على:
<input type="number">
هذا لا يعني أن البيانات القادمة إلى الخادم آمنة أو صحيحة.
التحقق الحقيقي يجب أن يحدث على الخادم باستخدام Laravel Validation.
تمرين عملي
قم الآن بإنشاء Form لإضافة منتج.
يجب أن يحتوي على:
name price description email
ثم أنشئ Validation:
'name' => ['required', 'string', 'min:3', 'max:255'], 'price' => ['required', 'numeric', 'min:0'], 'description' => ['required', 'string', 'min:10'], 'email' => ['required', 'email'],
بعد ذلك:
- أنشئ Route لعرض Form.
- أنشئ Route من نوع POST لاستقبال البيانات.
- أنشئ Method باسم
create(). - أنشئ Method باسم
store(). - استخدم
@csrf. - اعرض أخطاء كل حقل باستخدام
@error. - استخدم
old()لإعادة البيانات السابقة. - بعد نجاح Validation، أعد توجيه المستخدم إلى صفحة المنتجات.
- أرسل رسالة نجاح باستخدام
with().
بعد تنفيذ التمرين، حاول تحويل Validation من Controller إلى:
php artisan make:request StoreProductRequest
ثم ضع القواعد داخل:
rules()
واستخدم:
$request->validated();
داخل Controller.
في هذا الدرس انتقلنا من مجرد عرض البيانات إلى استقبال البيانات القادمة من المستخدم والتعامل معها بطريقة صحيحة.
تعلمنا أن HTTP Request يحتوي على البيانات والمعلومات المرتبطة بالطلب، ويمكننا الوصول إليه في Controller باستخدام:
use Illuminate\Http\Request;
ثم:
public function store(Request $request)
وتعلمنا قراءة البيانات باستخدام:
$request->input('title');
ثم تعرفنا على Validation باستخدام:
$request->validate([
...
]);
وتعلمنا قواعد مهمة مثل:
required string integer numeric email min max nullable date unique exists
كما تعلمنا كيفية عرض الأخطاء في Blade باستخدام:
@error('title')
{{ $message }}
@enderror
وتعلمنا استخدام:
old('title')
لإعادة البيانات التي أدخلها المستخدم إلى النموذج بعد فشل Validation.
ثم انتقلنا إلى Form Requests باستخدام:
php artisan make:request StoreArticleRequest
وتعلمنا وضع Validation Rules داخل:
rules()
ثم استخدام:
$request->validated();
للحصول على البيانات التي اجتازت التحقق.
وأصبح لدينا الآن تصور أوضح لدورة Form كاملة:
Blade Form
↓
HTTP Request
↓
Route
↓
Controller / Form Request
↓
Validation
↓
Validated Data
↓
Database
↓
Redirect
↓
Blade View
وهنا نصل إلى نقطة مهمة جدًا في الكورس.
لقد تعلمنا حتى الآن:
Routes Controllers Views Blade Requests Validation
والخطوة الطبيعية التالية هي أن نتعلم أين ستذهب البيانات بعد نجاح Validation.
وهنا سنبدأ بالدخول إلى عالم Database وMigrations، ونتعلم كيفية إنشاء قاعدة البيانات والجداول باستخدام Laravel، وكيف يمكن للتطبيق إنشاء وتعديل بنية الجداول بطريقة منظمة بدل التعامل معها يدويًا.
في الدرس القادم سنبدأ مع Database وMigrations في Laravel، ثم ننتقل بعد ذلك إلى Models وEloquent للتعامل مع البيانات بطريقة Laravel المميزة.
