Laravel Tutorial

Bài 35: Mutator và Cast trong Laravel Eloquent

Cho phép định dạng các giá trị attribute của Eloquent khi bạn lấy lại hoặc set chúng trên các thể hiện của model. Những tính năng này sẽ rất hữu ích khi bạn muốn thực thi việc gì đó khi lưu trữ dữ liệu vào database. Ví dụ như mã hóa thông tin, convert data type,…

1. Mutator

# Accessor

Để định nghĩa một accessor trong eloquent model, bạn chỉ cần khai báo một phương thức nằm trong model chứa attribute mà bạn cần thay đổi giá trị có tên theo cú pháp:

get{Attribute}Attribute

Trong đó{Attribute} là tên của thuộc tính bạn muốn thay đổi giá trị. Nếu thuộc tính được đặt theo dạng “snake_case” thì tên thuộc tính đó sẽ được convert về dạng “cameCase

Ví dụ: Khai báo accessor cho thuộc tính “first_name

<?php

namespace App\Models;

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 trên có tác dụng in hoa chữ cái đầu tiên của first_name

Lúc này các bạn có thể access đến attribute first_name trong model User để xem kết quả

use App\Models\User;

$user = User::find(1);
$firstName = $user->first_name;

Bạn có thể dùng accessor cho các attribute thực sự không tồn tại trong model

Ví dụ: Thêm accessor lấy ra “full_name” của user

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

Lúc này các bạn có thể truy vấn đến attribute full_name như một thuộc tính của model bình thường

use App\Models\User;

$user = User::find(1);
$firstName = $user->full_name;

# Mutator

Để khai báo một mutator trong eloquent model các bạn chỉ việc thay chữ get bằng set trong tên phương thức, còn lại cú pháp đặt tên thì giống như đối với accessor

Ví dụ: Khai báo một mutator thay đổi giá trị của attribute first_name khi thực thi set giá trị cho nó

<?php

namespace App\Models;

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);
    }
}

Lúc này các bạn có thể set giá trị cho first_name của User để xem kết quả

use App\Models\User;

$user = User::find(1);
$user->first_name = 'Sally';

echo $user->first_name // sally

2. Cast

Cast trong eloquent thực ra cũng là các accesstor, mutator được định nghĩa sẵn trong eloquent ORM core. Cast đúng như tên gọi của nó, nó cho phép chúng ta chuyển đổi giá trị, ép kiểu dữ liệu của một attribute nào đó trong model.

Để khai báo cast trong model các bạn chỉ cần khai báo các attribute các bạn muốn cast và kiểu dữ liệu muốn cast thành vào trong thuộc tính $cast

Ví dụ: Cast attribute blocked_at sang kiểu date

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

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

Mặc định Laravel hỗ trợ sẵn cast các kiểu dữ liệu sau:

  • array
  • boolean
  • collection
  • date
  • datetime
  • decimal:<digits>
  • double
  • encrypted
  • encrypted:array
  • encrypted:collection
  • encrypted:object
  • float
  • integer
  • object
  • real
  • string
  • timestamp

# Custom Cast

Nếu muốn cast data sang một kiểu giá trị khác ngoài các kiểu hỗ trợ ở trên, các bạn có thể khai báo thêm các custom cast trong eloquent

Để khai báo thêm một custom cast trong eloquent các bạn chỉ cần khai báo một class implement CastsAttributes (Illuminate\Contracts\Database\Eloquent\CastsAttributes) có chứa hai phương thức get và set để thực hiện lấy ra và gán giá trị cho attribute

Ví dụ: Khai báo thêm một cast để cast Json

app/Casts/Json.php

<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Json implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return array
     */
    public function get($model, $key, $value, $attributes)
    {
        return json_decode($value, true);
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  array  $value
     * @param  array  $attributes
     * @return string
     */
    public function set($model, $key, $value, $attributes)
    {
        return json_encode($value);
    }
}

Lúc này nếu muốn sử dụng Json cast trong model bạn chỉ việc khai báo như sau:

<?php

namespace App\Models;

use App\Casts\Json;
use Illuminate\Database\Eloquent\Model;

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

Leave a Comment