Sử dụng JSON Columns trong Eloquent: Cách tiếp cận lai SQL/NoSQL
Thiết kế cơ sở dữ liệu quan hệ truyền thống (Normalization) nói: "Nếu bạn có danh sách các item, hãy tạo một bảng riêng".
Nhưng đôi khi bạn chỉ muốn lưu trữ "Settings", "Metadata", hoặc các thuộc tính động mà không cần tạo 10 bảng mới.
Đây là lúc kiểu cột JSON xuất hiện.
Migration
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->json('attributes'); // { "color": "red", "size": "XL" }
$table->timestamps();
});
Eloquent Casting
Cho Eloquent biết cần tự động chuyển đổi chuỗi JSON thành Array (hoặc Object).
protected $casts = [
'attributes' => 'array',
];
Bây giờ bạn có thể sử dụng nó như một PHP array bình thường:
$product->attributes['color'] = 'blue';
$product->save();
Truy vấn JSON
Laravel làm điều này cực kỳ dễ dàng sử dụng cú pháp ->.
// Tìm products có color là red
$products = Product::where('attributes->color', 'red')->get();
// Tìm size large
$products = Product::where('attributes->size', 'XL')->get();
// Keys lồng nhau
$products = User::where('meta->settings->notifications->email', true)->get();
Cập nhật JSON một phần
Bạn có thể cập nhật một key đơn lẻ mà không ghi đè toàn bộ JSON blob.
$product->update(['attributes->color' => 'green']);
Cảnh báo về hiệu năng
Truy vấn JSON chậm hơn các cột chuẩn. Nếu bạn truy vấn attributes->color trên mỗi lần tải trang, hãy tách nó ra thành một cột thực.
Tuy nhiên, bạn có thể đánh index cho JSON keys sử dụng "Generated Columns" trong MySQL 5.7+ / MariaDB.
$table->string('color')->virtualAs('attributes->>"$.color"')->index();
Điều này tạo một virtual column color cho phép đánh index hiệu suất cao trong khi vẫn giữ dữ liệu trong cấu trúc JSON.