7 چیزی که باید بدانید تا نهایت استفاده را از مدل‌های لاراولی ببرید

laravel-models

در این آموزش به 7 نکته مهم می پردازیم که با بکارگیری آن ها می توانید مدل‌ لاراول خود بهبود دهید.

1# ساخت بهینه مدل

زمانی که می خواهید با استفاده از کنسول (command Line) یک مدل‌ لاراول تولید کنید، به طور پیش فرض مدل شما در فولدر app که در دایرکتوری پروژه لاراولی قرار دارد، ایجاد خواهد شد. اما بهتر است برای جداسازی مدل ها، براساس موضوع عملکرد و نوع رفتار مدل، فولدرهای مختلفی را در نظر بگیرید. برای این کار باید نام فولدر موردنظر خود را که می خواهید مدل لاراولی در آن قرار بگیرد، به آخر دستور ساخت مدل اضافه کنید. مانند زیر:

php artisan make:model Models/Product

دستور بالا مدل Product را در فولدر app/Models قرار می دهد که این کار در بهینه سازی زمان شما که بعدها صرف انتقال مدل ها در فولدر مناسب شوند، بسیار مؤثر است.

2# تغییر نوع فیلدهای یک مدل

فریم ورک لاراول با استفاده از متغیر cast$ روشی ارائه کرده است که براساس آن می توانید نوع یک فیلد را در مدل‌ لاراول تغییر دهید. در مثال زیر طریقه بکارگیری این ویژگی را در کلاس مدل می توانید مشاهده کنید:

protected $casts = [
    'is_published' => 'boolean'
];

با استفاده از کد بالا در یک مدل لاراول، می توانید هر زمانی که بخواهید به فیلد 'is_published' با نوع boolean دسترسی داشته باشید، توجه کنید که حتی اگر نوع فیلد 'is_published' که در بالا استفاده شده است، در دیتابیس پروژه شما به صورت ineteger یا هر نوع داده ای دیگری ذخیره شده باشد، با استفاده از کد بالا هنگام دسترسی از طریق مدل لاراولی، به صورت boolean در دسترس خواهد بود.

با این کاربردی که توضیح داده شد، انواع مختلفی از نوع داده (data type) وجود دارند که شما می توانید نوع فیلدهای یک مدل‌ لاراول را به نوع های جدید تبدیل کنید. از معروف ترین فیلدهای یک مدل که نوعشان تغییر می کنند می توان به date یا datetime اشاره کرد.

اما اشتباهی که من بسیاری از مواقع در پروژه های لاراول مشاهده می کنم اینست که در یک مدل، فیلدهایی که از نوع date و یا datetime هستند، به صورت زیر در قالب لاراول فرمت می شود:

{{ $blog->created_at->format('Y-m-d') }}

این اتفاق بیشتر اوقات در قالب های blade پروژه لاراول رخ می دهد. این تغییر فرمت را می توانید با توجه به راهکاری که ارائه شد به صورت مؤثرتری با خاصیت cast$ پیاده کنید. به عنوان مثال برای فیلدهای از نوع date و datetime که در یک مدل قرار دارند، به شکل زیر فرمت خروجی را تعیین می کنیم:

protected $casts = [
    'published_at' => 'datetime:Y-m-d',
];

کد بالا همیشه فیلد published_at را به فرمت 'Y-m-d' در خروجی برمی گرداند، بنابراین دیگر شما نیاز ندارید تا فرمت دهی را به صورت نامرتب و تکراری در قالب Blade انجام دهید.

3# دیده شدن در خروجی مدل

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

برای مثال فیلد password در مدل User (کاربر) را در نظر بگیرید. ما این فیلد را در ساختار مدل داریم زیرا به دسترسی این فیلد برای تغییر مقدار آن نیاز داریم. اما هنگامی که اطلاعات کاربر را در خروجی ارائه می کنیم، نباید فیلد password جزئی از اطلاعات کاربر باشد که نشان داده می شود، زیرا این موضوع از نظر امن بودن پروژه درست نیست. با استفاده از خاصیت hidden$ می توانیم ضمن در عین حال که به فیلد password و تغییر مقدارش دسترسی داشته داریم، هنگام ارائه در خروجی و قرار گرفتن مدل در داده json نشان داده نشود. حالا می توانیم با استفاده از خاصیت hidden$ این امکان را در کلاس مربوط به مدل اعمال کنیم:

protected $hidden = [
    'password'
];

در واقع hidden$ نقشی همچون یک لیست سیاه (blacklist) را برای فیلدهای یک مدل ایفا می کند. این خاصیت، کارکرد مدل های شما را در عین دسترس پذیری بهینه تر می کند. مثلا در مدل بالا با استفاده از مکانیزمی که بکارگرفته شد password در هنگام برگرداندن اطلاعات به کاربر، جزئی از فیلدهای یک مدل نیست. با همین رویه این امکان وجود دارد که از خاصیتی به نام visible$ نیز استفاده کنید تا لیست سفید (whitelist) را پوشش دهد که شامل داده هایی است که حتما باید در خروجی ارائه شوند. در کد زیر طریقه استفاده از خاصیت visible$ آمده است:

protected $visible = [
    'first_name',
    'last_name'
];

توجه کنید زمانی که بخواهید از خاصیت visible$ استفاده کنید، سایر فیلدهای یک مدل به صورت اتوماتیک hidden$ در نظر گرفته می شوند. می توانید این عملکرد را مانند کاربرد خاصیت های fillable$ و guarded$ در یک مدل بدانید.

4# Accessors

زمانی که نیاز دارید تا ترکیب جدیدی از چند فیلد یک مدل را با فرمت خاصی نشان دهید - مثلا هنگامی که نام و نام خانوادگی به صورت جدا تعریف شده باشند اما شما به نام کامل کاربران نیاز دارید - می توانید از این ویژگی (Accessor) استفاده کنید.

فرض کنید که شما مدل User را دارید که شامل فیلدهای first_name و last_name می شوند. در حالت عادی و بدون کمک گرفتن از ویژگی Accessors جهت تولید ترکیب نام کامل افراد باید مانند کد زیر عمل کنید:

$this->first_name . ' ' . $this->last_name

اما کد بالا روش بهینه ای نیست، هر چند که ساده انجام می شود اما در صورت نیاز به استفاده از این ترکیب در سایر قسمت های پروژه، همچنان ترکیب مورد نظر (نام کامل افراد) به صورت کد بالا تکرار می شود.

لاراول برای رفع نیازهایی مانند موضوعی که در بالا به آن اشاره شد، Accessor را پیشنهاد می دهد. Accessor در واقع متدی است که در ساختار یک مدل تعریف می شود. ساختار Accessor بدین صورت است: get[NameOfAttribute]Attribute.

حالا بر اساس کلاس مدل و فیلدهای first_name و last_name و خاصیت Accessor که شرح داده شد، برای دسترسی به نام کامل یک فرد به صورت زیر در کلاس مدل عمل می شود (یک Accessor پیاده می شود):

public function getFullNameAttribute() {
    return "{$this->first_name} {$this->last_name}";
}

حالا اگر بخواهید در مدل User به این accessor دسترسی داشته باشید باید آن را در کد مانند یک فیلد عادی مدل صدا بزنید:

$user->full_name

5# Mutator

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

مثلا فرض کنید می خواهید مطمئن شوید حرف اول مقدار یک فیلد خاص که انگلیسی هم هست همیشه قبل از ذخیره شدن در دیتابیس به حرف بزرگ تبدیل شود. لاراول برای اعمال چنین پردازش هایی Mutator ها را ارائه داده است. Mutator در لغت به معنی جهش دهنده است و این امکان در لاراول ایجاد شده است تا داده ها در مدل ها قبل از ذخیره شدن تغییر کنند و در واقع پردازشی خاص و همیشگی روی داده ها قبل از ذخیره شدن انجام شود. داده های تغییر یافته یا همان پردازش شده با استفاده از آرایه ای تحت عنوان attributes$ در مدل Elequent ذخیره  می شوند، ضمنا Mutator سینتکسی مانند Accessor دارد.

در مثال زیر این کاربرد نشان داده شده است:

public function setLastNameAttribute($value) {
    $this->attributes['last_name'] = ucfirst($value);
}

در مثال بالا یک mutator تعریف شده است(setLastNameAttribute) که فانکشن ucfirst را بر روی نام خانوادگی(last_name) اعمال می کند و نتیجه را در آرایه attributes ذخیره می کند. با این کارکرد قطعه کد زیر را در نظر بگیرید، بعد از مقدار دهی با توجه به استفاده از mutator، حرف اول به حرف بزرگ تبدیل می شود:

$user->last_name = 'jones'; // Will result in `Jones`

6# پیوست کردن

وقتی یک مدل Accessor دارد و شامل relation یا رابطه با مدل های دیگر است، به صورت پیش فرض در json و یا آرایه ای که جهت ارائه خروجی مدل استفاده می شود، موارد مرتبط با relation ها یا Accessor ها دیده نمی شود.

مثلا فرض کنید یک Accessor که کار فرمت خروجی نام کامل فرد با ترکیب فیلدهای نام و نام خانودگی را دارد، به صورت عادی در خروجی مدل نشان داده نمی شود. به همین منظور باید accessor یا relation را به آرایه appends$ که فیلدی در مدل است، اضافه نمود.

حال بیایید کد کاربرد پیوست کردن یا همان استفاده از آرایه appends$ مربوط به getFullNameAttribute که یک Accessor است و در بالا آمده را در ساختار کلاس مدل ببینیم:

$appends = [
    'full_name'
];

با استفاده از کد بالا در مدل‌ لاراول تعریف می شود که این accessor که نام کامل کاربر را فرمت می کند (ترکیبی از نام و نام خانوادگی)، در هنگام برگرداندن مدل به کاربر نشان داده شود.

نکته: Accessor ها زمانی که به فیلد append$ اضافه می شوند، باید به صورت snake case در نظر گرفته شوند حتی اگر accessor ها به صورت camel case تعریف شده باشند.

حالا فرض کنید که مدل User رابطه ای (relation) با مدل Blog دارد.

public function blogs() {
    return $this->hasMany(App\Blog::class);
}

جهت ضمیمه کردن blog ها در مدل User و نشان دادن blog های مرتبط در خروجی یک مدلِ User، شما به راحتی می توانید مانند زیر عمل کنید و فیلد append$ را آپدیت کنید:

$appends = [
    'full_name',
    'blogs:id,title'
];

نکته: اگر از ویژگی appends$ استفاده نشود، Accessor ها در کد همانند آنچه که درباره طریقه صدا زدن یک Accessor گفته شد، در دسترس هستند اما نمی توانید در قالب یک آرایه یا داده json، به همراه سایر فیلدهای یک مدل‌ لاراول، serialize کنید و مثلا به قالب Blade برگردانید.

7# Touches

فرض کنید که مدلی، رابطه BelongsTo یا BelongsToMany با مدل دیگر دارد. مثلا شرایطی را تصور کنید که یک کامنت به یک بلاگ متعلق است. حالا می خواهیم در صورتی که یک کامنت آپدیت شد برچسب زمانی بلاگ نیز براساس آپدیت شدنِ زمانِ کامنت، آپدیت شود. این کاربرد می تواند با اضافه کردن رابطه blog به فیلد touches$ در مدل comment اعمال شود:

class Comment extends Model
{
    protected $touches = ['blog'];

    public function blog()
    {
        return $this->belongsTo(App\Blog::class);
    }
}

در این شرایط وقتی مدل کامنت آپدیت شود، به صورت اتوماتیک فیلد updated_at در مدل Blog نیز آپدیت می شود.

این 7 نکته ای بود که می توانیم با بکارگیری آن ها به بیشترین کاربرد از مدل‌ لاراول برسیم.


منبع: سایت ITNEXT

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.