آشنایی با eloquent mutators

اصول آموزش Laravel

تاریخ : جمعه 29 دی 1396

Accessor ها و Mutator ها به شما این امکان را می دهند تا attribute های Eloquent را به هنگام بازیابی از مدل یا مقدار دهی آن، فرمت دهی کنید. به عنوان مثال می توان به سناریویی اشاره کرد که در آن می خواهیم با استفاده از encrypter لارول مقداری را در حالی که در پایگاه داده ذخیره شده، رمزنگاری کنیم و سپس آن را در زمان دسترسی (به آن) در مدل Eloquent، بار دیگر رمزگشایی نماییم.

علاوه بر ارائه ی accessor ها و mutator های اختصاصی، Eloquent قادر است فیلدهای حاوی تاریخ و نوع داده ای date را به نمونه هایی از نوعCarbon کانورت کرده و حتی فیلدهای متنی را به فرمت JSON تبدیل کند.


نحوه ی تعریف Accessor

برای تعریف Accessor، یک متد getFooAttribute در مدل خود ایجاد نمایید. واژه ی Foo در نام این متد در واقع نسخه ی CamelCase (بر اساس سیستم نوشتاری camelcase) اسم همان ستونی است که می خواهید به آن دسترسی داشته باشید. در این مثال، یک accessor برای اتریبیوت first_name تعریف می کنیم. به هنگام بازیابی و دسترسی به مقدار attribute نام برده، Eloquent به صورت خودکار accessor تعریف شده را صدا می زند:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Get the user's first name.
     *
     * @param  string  $value
     * @return string
     */
    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }
}

همان طور که می بینید، مقدار اولیه ی ستون به accessor ارسال می شود و به شما این امکان را می دهد تا به آسانی آن را ویرایش و بازیابی کنید. حال برای دسترسی به مقدار mutator، کافی است به اتریبیوت first_name دسترسی پیدا کنید:

$user = App\User::find(1);

$firstName = $user->first_name;

همچنین می توانید با استفاده از accessors جهت ایجاد مقادیر جدید استفاده نمایید :

/**
 * Get the user's full name.
 *
 * @return string
 */
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}


نحوه ی تعریف یک Mutator

به منظور تعریف mutator، یک متد به نام setFooAttribute در مدل ایجاد کنید. واژه ی Foo در اسم این متد در واقع نسخه ی camelcase نام همان ستونی است که می خواهید به مقدارش دسترسی داشته باشید. بنابراین ابتدا یک mutator برای اتریبیوت first_name تعریف می کنیم. به هنگام مقداردهی attribute ذکر شده در مدل مورد نظر، این mutator به صورت خودکار فراخوانده می شود:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Set the user's first name.
     *
     * @param  string  $value
     * @return void
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }
}

mutator مقداری که در attribute قرار داده (set) می شود را دریافت کرده و به شما اجازه می دهد تا مقدار آن را ویرایش کنید، سپس مقدار ویرایش شده را در متغیر (property) درون ساخته ی مدل Eloquent به نام $attributes ذخیره نمایید/قرار دهید. بنابراین، اگر بخواهیم مقدارfirst_name را با Sally تنظیم نماییم، می بایست به صورت زیر اقدام کنیم:

$user = App\User::find(1);

$user->first_name = 'Sally';

$user->save();

در این مثال، تابع setFirstNameAttribute با مقدار Sally فراخوانده می شود. mutator سپس تابع strtolower را بر روی اسم اجرا کرده و مقدارش را در آرایه ی درون ساخته ی attributes$ قرار می دهد.


تاریخ در Mutator

به صورت پیش فرض، Eloquent ستون های created_at و updated_at را به نمونه های (اشیای) از نوع Carbon تبدیل می کند که تعداد زیادی متد مفید در اختیار ما قرار داده و کلاس درون ساخته ی DateTime زبان PHP را ارث بری می کند.

می توانید مشخص کنید کدام فیلدها بایستی به صورت خودکار تبدیل (mutate) شوند یا این تبدیل را کاملا غیر فعال نمایید. برای این منظور کافی است property ای که dates$ نام دارد را در مدل خود بازنویسی کنید:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at'
    ];
}

ستونی که از نوع date شناخته می شود را می توان با تایم استمپ های UNIX، تاریخ با فرمت رشته (Y-m-d)، تاریخ-زمان با فرمت رشته و البته یک نمونه از DateTime / Carbon مقداردهی نمود. مقدار date متعاقبا به صورت خودکار با فرمت مناسب در پایگاه داده ذخیره می شود:

$user = App\User::find(1);

$user->deleted_at = now();

$user->save();

همان طور که در بالا ذکر شد، زمانی که attribute های لیست شده در متغیر(property) $dates را واکشی می کنید، این attribute ها به صورت خودکار به نمونه هایی از نوع Carbon تبدیل می شوند. این امر به شما اجازه می دهد تا متدهای Carbon را بر روی attribute های مورد نظر فراخوانی کنید:

$user = App\User::find(1);

return $user->deleted_at->getTimestamp();

به صورت پیش فرض، timestamp ها بدین صورت فرمت دهی می شوند: 'Y-m-d H:i:s'. در صورت تمایل می توانید این فرمت را اختصاصی تنظیم کنید. برای این منظور کافی است dateFormat property$ را در مدل خود مقداردهی نمایید. این property تعیین می کند attribute های حاوی مقدار تاریخ چگونه در پایگاه داده ذخیره شوند و همچنین فرمت آن ها را در زمان serialize (کد) شدن مدل به آرایه یا JSON مشخص می کند:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}


تبدیل Attribute

متغیر casts$ (در مدل) روشی آسان برای تبدیل attribute ها به نوع داده های معمول فراهم می کند. property مزبور باید یک متغیر از نوع آرایه باشد که در آن کلید در واقع اسم attribute ای است که باید تبدیل شود و مقدار آن نوع داده ای است که می خواهید ستون (فیلد) به آن cast شود. نوع هایی که برای تبدیل پشتیبانی می شوند عبارتند از: integer، real، float، double، string، boolean، object، array،collection، date، datetime و timestamp.

در مثال زیر اتریبیوت is_admin که به صورت یک عدد صحیح 0 یا 1 در پایگاه داده ذخیره شده را به نوع داده ای Boolean تبدیل می کنیم:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'is_admin' => 'boolean',
    ];
}

اکنون دیگر مقدار attribute نام برده همیشه به هنگام دسترسی به آن، به یک مقدار از نوع بولی تبدیل می شود، هرچند مقدار اصلی به صورت یک عدد صحیح در پایگاه داده ذخیره شده:

$user = App\User::find(1);

if ($user->is_admin) {
    //
}


تبدیل به نوع Array & JSON

تبدیل نوع آرایه به خصوص برای کار با ستون هایی که به صورت JSON سریاله شده، ذخیره شده اند مفید واقع می شود. به عنوان مثال، اگر پایگاه داده ی شما دارای فیلدی از نوع TEXT باشد که با JSON سریاله شده مقداردهی شده است، در آن صورت افزودن نوع array به آن attributeباعث می شود، در زمان دسترسی به آن ATTRIBUTE در مدل Eloquent، نوع attribute خودکار به یک آرایه ی معمولی PHP تبدیل شود:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => 'array',
    ];
}

پس از تعریف عملیات تبدیل، می توانید به options attribute دسترسی پیدا کنید. خواهید دید که نوعش به صورت خودکار از JSON سریاله شده به یک آرایه ی متعارف PHP تبدیل می شود. زمانی که attribute نام برده را مقداردهی می کنید، آرایه ی ارائه شده مجددا برای ذخیره سازی به صورت خودکار به فرمت JSON (serialized) برگردانده می شود:


$user = App\User::find(1);

$options = $user->options;

$options['key'] = 'value';

$user->options = $options;

$user->save();

منابع مورد مطالعه جهت جمع آوری این مطلب:
https://laravel.com/docs/5.5/eloquent-mutators
www.tahlildadeh.com/ArticleDetails/آموزش-Mutator-ها-و-Accessor-ها-در-Eloquent


نظرات