recent
أخبار ساخنة

تمرير البيانات بين Controller و View في Laravel

تمرير البيانات بين Controller

استقبال البيانات والتحقق منها 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

يمكننا كتابة:

'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

القيمة يجب أن تكون رقمًا.

email

القيمة يجب أن تكون بريدًا إلكترونيًا صالحًا.

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 RequestValidation منظمة وأكثر تعقيدًا
$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

أصبح لدينا الآن نموذج حقيقي يستطيع:

  1. عرض Form.
  2. استقبال البيانات.
  3. حماية الطلب باستخدام CSRF.
  4. التحقق من البيانات.
  5. عرض الأخطاء.
  6. إعادة البيانات القديمة.
  7. إعادة توجيه المستخدم بعد النجاح.

أخطاء شائعة في 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'],

بعد ذلك:

  1. أنشئ Route لعرض Form.
  2. أنشئ Route من نوع POST لاستقبال البيانات.
  3. أنشئ Method باسم create().
  4. أنشئ Method باسم store().
  5. استخدم @csrf.
  6. اعرض أخطاء كل حقل باستخدام @error.
  7. استخدم old() لإعادة البيانات السابقة.
  8. بعد نجاح Validation، أعد توجيه المستخدم إلى صفحة المنتجات.
  9. أرسل رسالة نجاح باستخدام 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 المميزة.

google-playkhamsatmostaqltradentX