فصل چهارم: لایه مدل

ورود فله‌ای اطلاعات

در درس پیش، آموختیم که چطور مدل‌های خالی الیکوئنت که با دستورات آرتیزان ساخته می‌شوند، به کار می‌آیند. ما متدهای موجود در همین الیکوئنت‌های صفرکیلومتر را برای سه عملکرد اصلی «ساخت رکورد جدید»، «به‌روزرسانی» و «حذف» به کار گرفتیم و نیم‌نگاهی هم به کوئری‌های ساده‌ای همچون شمارش کردن (()count) و یافتن (()find) انداختیم.

در این درس، ساز و کارهای ورود فله‌ای اطلاعات در دیتابیس را خواهیم آموخت و برای این کار ،دیگر الیکوئنت‌های خالی به کارمان نمی‌آیند و باید تغییراتی در آن‌ها داده شود.

یک رکورد جدید

به جای این که مثل درس قبل، ستون‌ها را یکی یکی مقداردهی کنیم و سپس ذخیره نماییم، می‌توانیم از متد ()create استفاده کنیم و همه چیز را یکباره به لاراول سفارش دهیم.

برای اجرای یک مثال، سراغ همان فایل کنترلر آزمایشی خودمان می‌رویم که در درس قبل ساختیم. متد ()index‍ فقط متد اصلی را صدا می‌کند تا لازم نباشد متدهای آزمایشی‌ای که ساخته‌ایم و می‌سازیم را هر بار دور بریزیم.
class EloquentTestController extends Controller
{
    public function index()
    {
        return $this->massCreate();
    }

    private function massCreate()
    {
        $saved_record = Mission::create([
            "code" => "1234",
            "title" => "Mass Mission Test",
            "operator" => "Mass Operator Test",
        ]);

        return $saved_record->id;
    }

متد استاتیک ()create، آرایه‌ای شامل ستون‌ها و مقدارهای هر یک را می‌گیرد و در دیتابیس ذخیره می‌کند و همان شیء ساخته‌شده از نوع الیکوئنت را به عنوان خروجی بازمی‌گرداند.

فلسفهٔ وجودی این متد آن است که مقدار دریافتی از فرمی که کاربر پر کرده را از یک دست تحویل بگیرد و با دست دیگر در دیتابیس ذخیره کند.

این کار کمی خطرناک به نظر می‌رسد.

  • اولین خطر آن است که انگار داده‌ها بدون اعتبارسنجی سمت سرور روانهٔ دیتابیس شده‌اند. این نگرانی در عمل بیهوده است. لایهٔ اعتبارسنجی ریکوئست در لاراول، میانهٔ راه را می‌گیرد و مطمئن می‌شود که داده‌هایی که به کنترلر می‌رسند از سلامت کامل برخوردارند.
  • دومین خطر آن است که اگر کاربری جرزنی کند و داده‌ای را که انتظار نداریم همراه با فرم روانهٔ سرور کند، کاری از دست ما ساخته نیست.

لاراول، به صورت پیش‌فرض راه را بر خطر دوم نیز بسته است. در واقع چنین کدی اصلاً اجرا نمی‌شود. برای آزمایش، با ریفرش مرورگر خود، قطعه کد بالا را آزمایش کنید و نتیجه را ببینید.

Model Mass-alignment Error

از این خبرها نیست و لاراول نیز چنین اجازه‌ای نمی‌دهد. برای این که بتوانیم داده‌ای را به صورت فله‌ای در دیتابیس ذخیره کنیم، باید از قبل تدارک دیده باشیم و به الیکوئنت گفته باشیم که چه ستون‌هایی می‌توانند به این ترتیب پر شوند.

این همان تغییری است که در مقدمه از آن یاد کردم.

برای این کار، سراغ فایل مدلی که ساخته‌ایم می‌رویم و ستون‌های مجاز را در متغیری به نام fillable$‍‍ معرفی می‌کنیم.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Mission extends Model
{
    protected $fillable = ['code', 'title', 'operator'];
}

حالا که چنین کردیم، می‌توانیم مرورگر را ریفرش کنیم و این بار ببینیم که خبری از پیام خطا نیست و اگر سری هم به برنامه‌هایی مثل phpMyAdmin بزنیم، می‌توانیم به رکورد تازه‌ای که به صورت فله‌ای ذخیره کردیم، سلام کنیم.

Model Mass-alignment Succcess

ملاحظه می‌فرمایید که این بار نیز ستون‌های created_at‍ و updated_at بدون دخالت ما تکمیل شدند.

لیست سفید / لیست سیاه

در حالی که متغیر fillable$‍ لیست سفیدی از ستون‌هایی که می‌توانند به صورت فله‌ای ذخیره شوند را در خود نگاه می‌دارند، ممکن است این موضوع را در عمل دردسرساز ببینیم و دوست داشته باشیم به جای این کار، لیست سیاهی داشته باشیم از ستون‌هایی که اجازه ندارند به صورت فله‌ای پر شوند.

متغیر guarded$ برای همین روزهاست. این متغیر نیز حاوی آرایه‌ای از ستون‌هاست، با این تفاوت که نام ستون‌هایی را نگهداری می‌کند که قرار نیست و اجازه ندارند سفارش‌های فله‌ای بپذیرند.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Mission extends Model
{
    protected $guarded = ['is_ratified'];
}

مدل الیکوئنتی که در قطعه کد بالا تصویر شده، هر ستونی را به صورت فله‌ای می‌پذیرد، به جز ستونی که نشان تصویب شدن مأموریت فضایی را در خود حمل می‌کند.

دانشمندان برنامهٔ فضایی ما نمی‌توانند با دستکاری سادهٔ فرمی که داده‌های یک مأموریت را پر می‌کنند، آن را «تصویب‌شده» جا بزنند و کارشان را جلو بیاندازند.

طبیعتاً منطقی است که بدانیم لازم است انتخاب کنیم. یا لیست سفید را می‌توانیم داشته باشیم و یا لیست سیاه را.

یا متغیر fillable$ را پر می‌کنیم و یا guarded$ را:

یکی از آن‌ها، نه هر دو.

به‌روزرسانی فله‌ای

حالا که می‌توانیم رکوردی را با ارسال فله‌ای داده‌ها ایجاد کنیم، منطقی است که بتوانیم رکوردی موجود را نیز به همین ترتیب آپدیت نماییم.

class EloquentTestController extends Controller
{
    public function index()
    {
        return $this->massUpdate();
    }

    private function massUpdate()
    {
        $saved_record = Mission::find(112)->update([
            "code" => "1234" ,
        ]);

        return strval($saved_record);
    }

این بار هم فقط ستون‌هایی می‌توانند مقدارهای فله‌ای بپذیرند که اگر لیست سفیدی تعریف شده، نامشان در آن وجود داشته باشد و اگر لیست سیاهی تعریف شده، نامشان در آن نباشد.

متد ()update بر خلاف متد ()create که رکورد ساخته‌شده را بازمی گرداند، مقداری منطقی (true/false) را بازمی‌گرداند که حاکی از موفقیت‌آمیز بودن یا نبودن عمل به‌روزرسانی است.

این ویرایش فله‌ای ممکن است مسخره به نظر برسد، اما به درد زمانی می‌خورد که بخواهیم محتوای یک فرم ویرایش اطلاعات را مستقیماً روانهٔ دیتابیس کنیم. در این صورت احتمالاً id مورد نظر ما نیز همراه با فرم آمده و صد البته که با سطحی از رمزنگاری همراه است، چون قرار نیست اجازه بدهیم یک کاربر کنجکاو با تغییر یک ورودی مخفی، مثل آب خوردن رکوردی که مربوط به او نیست را ویرایش کند.

ویرایش فله‌ای چند رکورد

وقتی صحبت از ویرایش اطلاعات در میان باشد، ممکن است لازم باشد که چند رکورد را هم‌زمان تغییر دهیم. آپدیت فله‌ای لاراول، این امکان را مهیا می‌کند.

Mission::where('code' , '1234')->update([
    "code" => "5678",
]);

جان کلام

در این درس کوتاه، با ورود فله‌ای داده‌ها آشنا شدیم و دانستیم که تنها دو متد الیکوئنت، یکی برای ایجاد و یکی برای به‌روزرسانی، تمام کار ما را راه می‌اندازند. همچنین، دریافتیم که لاراول تنها ستون‌هایی را در فرآیند ورود فله‌ای اطلاعات بازی می‌دهد که یا در لیست سفید معرفی شده باشند و یا در لیست سیاه نباشند.

آخرین قطعه کد این درس، حاوی متدی بود که بی‌توضیح رها شد. این متد و خواهرانش، که «کوئری بیلدر» خوانده می‌شوند، موضوع درس بعدی هستند.

تا آماده شدن درس بعدی که امیدوارم این قدر طول نکشید، با ستاره زدن روی پروژهٔ این کتاب در گیتهاب، به من انگیزه بدهید، یا با روش‌هایی که در صفحهٔ بازخورد گفته‌ام، ایرادهای نوشته‌ام را نشانم دهید، یا سری به صفحهٔ حمایت از کتاب بزنید و ببینید که حمایت، همه‌اش پول نیست.

ناگفته پیداست که اگر سؤالی چیزی داشتید هم می‌توانید از طریق راه‌های گفته‌شده در صفحهٔ بازخورد با من در میان بگذارید.