آموزش مقدماتی لاراول –  ایجاد فرم و ارسال داده به سرور

در آموزش قبلی ما توانستیم یک پایگاه داده sqlite رو به اپلیکیشن لاراولیمون متصل کنیم، یک جدول از طریق migrate کردن ساختیم و با کمک محیط زنده tinker یک رکورد در جدول آهنگهای خودمون ذخیره کردیم. در ادامه و در این مطلب قصد دارم یک فرم بسیار ساده ایجاد کنم تا از طریق اون بتوانیم یک رکورد تازه در دیتابیس ذخیره کنیم.


برای این منظور ابتدا از سایت bootstrap یک فرم ساده با یک تگ input و button در صفحه songs خودمون وارد می‌کنم:

<form class="mb-4">
   <div class="col-sm-5 mb-3">
       <label for="name" class="form-label">نام آهنگ</label>
   <input type="text" class="form-control" id="name" aria-describedby="name">
   </div>
   <button type="submit" class="btn btn-primary">افزودن</button>
</form>

خب فرم بالا ی فرم سادست و بخودی خودش چیزی رو ارسال نمیکنه برای اینکه با زدن دکمه اطلاعات فرم ارسال بشه باید دوتا تگ رو برای فرم تعریف کنیم. یکی نوع ارسال دادست که ما در اینجا از نوع POST میخوایم استفاده کنیم و دیگری آدرس routeی هست که میخوایم از طریق اون به درخواستمون سمت سرور پاسخ بدیم. بنابراین کد بالا بصورت زیر تغییر میدیم:

<form class="mb-4" method="POST" action="songs">
   <div class="col-sm-5 mb-3">
       <label for="name" class="form-label">نام آهنگ</label>
       <input type="text" class="form-control" id="name" name="name" >
   </div>
   <button type="submit" class="btn btn-primary">افزودن</button>
</form>

اگر الان درخواست رو ارسال کنیم خطایی مبنی بر اینکه هیچ route برای پاسخ به این درخواست وجود نداره رو دریافت میکنیم که درست هم هست. بنابراین برمی‌گردیم به روت web.php و در اونجا یک روت جدید از نوع post تعریف می‌کنیم:

Route::post('songs', [\App\Http\Controllers\SongController::class, 'store']);

و حالا نوبت اینه که تابع store رو داخل کنترلر تعریف کنیم ولی سوال اینه که چطور اطلاعاتی که فرم ارسال میکنه رو دریافت کنیم. برای این منظور یک تابع کمکی وجود داره به نام request که از طریق اون میتونیم دیتای ارسال شده رو بگیریم من برای اینکه فرایند داره  درست انجام میشه یا نه از یک تابع کمکی پرکاربرد دیگه به نام dd (مخفف Dump and die) استفاده می‌کنم. 

همانطور که از اسم این تابع کمکی مشخصه این تابع ورودیی که میگیره رو بهمون صورت در مرورگر نمایش میده و برنامه رو در همونجا متوقف میکنه.

public function store()
{
   dd(
       \request('name')
   );
}

اجازه بدید خروجی بالا رو با هم ببینیم:

Image for post
Image for post

چه اتفاقی افتاد؟

دلیل این خطا وجود یک مکانیزم حفاظتی در لاراول به نام CSRF (مخفف cross-site request forgery ) هست که برای جلوگیری از حملات CSRF ایجاد شده. درمورد این مکانیزم‌ها (middleware) بعدا بطور کامل آموزش خواهم داد اما در اینجا تنها همین قدر بدونیم که لاراول برای اینکه جلوگیری بکنه از حملات CSRF روی هر درخواست POST که به سمت سرور ارسال میشه وجود یک token رو بررسی میکنه و درصورتی که مورد تایید باشه اون درخواست رو بررسی میکنه!

برای این منظور کافی داخل فرم خودمون @csrf رو قرار بدیم حال اگه یکبار صفحه رفرش کنید یک تگ از نوع input داخل فرم ما ساخته شده که مخفی هست. این کد در واقع توسط لاراول برای این فرم بصورت اختصاصی تولید شده:

خب حالا اگه یه متن برای تست فرم وارد کنیم و مجددا دکمه افزودن رو بزنیم اینبار درخواست ما از طرف سرور بررسی میشه و متن ما در خروجی نمایش داده خواهد شد.

بیایید تابع store رو تکمیل کنیم.

شیوه کار سادست، همانطور که در آموزش قبلی داخل tinker یک ریکورد ذخیره کردیم اینجا هم به همون شیوه عمل میکنیم و نامی که از طریق فرم ارسال کردیم رو در جدول ذخیره میکنیم.

public function store()
{
   $song = new Song();
   $song->name = \request('name');
   $song->save();
   return back();
}

تبریک میگم شما تونستید یک درخواست ایمن با csrf رو سمت سرور بفرستید و براساس اون یک رکورد داخل دیتابیس ذخیره کنید. حالا باید بتونیم اطلاعاتی که کاربر میفرسته سمت سرور رو پیش از اینکه داخل دیتابیس قرار بدیم ارزیابی کنیم. بطور خاص در رابطه با مثال ما کاربر نتونه نام آهنگ تکراری رو وارد دیتابیس بکنه، این مورد رو در آموزش بعدی حتما بررسی خواهیم کرد!