Laravel nâng cao

Custom Eloquent Casts: Xử lý dữ liệu phức tạp ở cấp độ Model

Tại sao phải xử lý JSON/Encryption trong Controller? Học cách dùng Laravel Custom Casts để encapsulate logic vào nơi nó thuộc về: Model.

newspaper

Phạm Hoàng Long

6 tháng 1, 2026 schedule 2 phút đọc
Custom Eloquent Casts: Xử lý dữ liệu phức tạp ở cấp độ Model
Featured Image

Lập trình viên Laravel thường gặp tình huống này: Database có cột settings lưu JSON: {"theme": "dark", "notifications": true}.

Cách cũ (Mutators/Accessors):

// User.php
public function getSettingsAttribute($value) {
    return json_decode($value);
}
public function setSettingsAttribute($value) {
    $this->attributes['settings'] = json_encode($value);
}

Vấn đề? Code lặp lại ở mọi Model. Và kết quả trả về là stdClass hoặc array, không có behavior.

Laravel 7+ giới thiệu Custom Casts. Đây là cách Domain-Driven Design (DDD) len lỏi vào Laravel.

Ví dụ: Value Object Address

Thay vì lưu address_line1, city, zip rải rác, hoặc lưu JSON và xử lý thủ công. Hãy tạo một Object Address.

// app/Values/Address.php
class Address
{
    public function __construct(
        public string $street,
        public string $city,
        public string $zip
    ) {}
    
    public function getFullAddress(): string {
        return "{$this->street}, {$this->city} {$this->zip}";
    }
}

Tạo Custom Cast:

// app/Casts/AddressCast.php
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class AddressCast implements CastsAttributes
{
    public function get($model, string $key, $value, array $attributes)
    {
        $data = json_decode($value, true);
        return new Address($data['street'], $data['city'], $data['zip']);
    }

    public function set($model, string $key, $value, array $attributes)
    {
        if (!$value instanceof Address) {
            throw new InvalidArgumentException("Must be Address object");
        }
        
        return json_encode([
            'street' => $value->street,
            'city' => $value->city,
            'zip' => $value->zip
        ]);
    }
}

Sử dụng trong Model:

// app/Models/User.php
class User extends Model {
    protected $casts = [
        'address' => AddressCast::class,
    ];
}

Kết quả

Bây giờ code của bạn cực kỳ clean và type-safe:

$user = User::find(1);

// Tự động casting sang Object
echo $user->address->getFullAddress(); 

// Khi lưu, chỉ cần gán object
$user->address = new Address('123 Main St', 'Hanoi', '10000');
$user->save(); // Tự động json_encode vào DB

Use Cases khác

  1. Encryption: Tự động encrypt/decrypt dữ liệu nhạy cảm (như API Keys) mà không cần logic trong controller.
  2. Money Patterns: DB lưu integer (cents), Model thao tác với Money\Money object.
  3. Status Enum: Cast integer (0, 1, 2) sang Enum Objects (Draft, Published).

Custom Casts giúp Model của bạn “thông minh” hơn và code clean hơn đáng kể.

quizQuick Quiz
Câu 1/3

Custom Casts trong Laravel giải quyết vấn đề gì?

history_edu Góc học tập & giải trí

Thử Thách Kiến Thức Lịch Sử?

Khám phá hàng trăm câu hỏi trắc nghiệm lịch sử thú vị tại HistoQuiz. Vừa học vừa chơi, nâng cao kiến thức ngay hôm nay!

Chơi Ngay arrow_forward