停止编写无尽的迁移:掌握 Laravel 中的 PostgreSQL JSONB
Source: Dev.to

“Settings” 表的噩梦
每个 SaaS 应用最终都会碰到同样的架构难题:动态数据。你有一个 users 表,突然产品经理想让用户保存他们的暗色模式偏好。于是你写迁移添加 theme 列。下一周,他们又想添加 notification_time 偏好。再来一次迁移。很快,你的表里出现了 40 列可空字段,而这些字段大多数都是空的。
有些开发者尝试通过完全切换到 MongoDB 之类的 NoSQL 数据库来解决这个问题。但这样会失去关系完整性、ACID 合规性以及外键的强大功能。
最终的解决方案就在 PostgreSQL 中:JSONB 列。
JSONB 的强大之处
PostgreSQL 允许你在列中存储原始 JSON 数据。但不同于普通的文本字段,JSONB(JSON Binary)类型实际上会被解析并以自定义的二进制格式存储。这意味着 PostgreSQL 可以对其建立索引、查询和过滤,速度堪比普通整数列。
在 Laravel 迁移中,设置它非常简单:
Schema::table('users', function (Blueprint $table) {
// One column to rule them all
$table->jsonb('preferences')->default('{}');
});
在 Eloquent 中进行类型转换
Laravel 的 Eloquent ORM 让使用 JSONB 如同魔法般便利。只需在模型中添加数组类型转换,Laravel 会在读取时自动把数据库中的 JSON 转换为原生 PHP 数组,保存时再转换回 JSON。
class User extends Model
{
protected $casts = [
'preferences' => 'array',
];
}
现在,你可以在不再编写迁移的情况下更新动态设置:
$user = User::find(1);
$user->preferences['theme'] = 'dark';
$user->preferences['marketing_emails'] = false;
$user->save();
在 JSON 中查询
因为是 JSONB,你可以使用 Laravel 的箭头语法直接对 JSON 负载中的键进行超快查询。
// Find all users who have the dark theme enabled
$darkUsers = User::where('preferences->theme', 'dark')->get();
结论
处理动态数据并不一定要使用 NoSQL 数据库。通过将 PostgreSQL 的严格关系能力与 JSONB 列的灵活性以及 Laravel 的 Eloquent 类型转换相结合,你可以构建出既在需要之处保持刚性的、又在其他地方无限灵活的数据库架构。