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.
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
- Encryption: Tự động encrypt/decrypt dữ liệu nhạy cảm (như API Keys) mà không cần logic trong controller.
- Money Patterns: DB lưu integer (cents), Model thao tác với
Money\Moneyobject. - 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ể.
Custom Casts trong Laravel giải quyết vấn đề gì?
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!