Laravel 的 $casts 中 'meta' => 'array' 不生效,是因为它仅对数据库原生 JSON 类型(如 MySQL JSON、PostgreSQL jsonb)自动序列化,对 TEXT/VARCHAR 字段无效;若字段非 JSON 类型,需迁移改为 json 类型,或改用 'object' 铸造、自定义 Cast 类处理。
$casts 里写 'meta' => 'array' 有时不生效?因为 Laravel 的 $casts 对 array 类型的处理依赖底层字段是否为 JSON 类型。如果数据库字段是 TEXT 或 VARCHAR,即使写了 'meta' => 'array',Laravel 也不会自动 json_encode/json_decode——它只对原生 JSON 字段(如 MySQL 5.7+ 的 JSON 类型、PostgreSQL 的 jsonb)做隐式转换;对普通字符串字段,array cast 会被忽略,读出来仍是字符串。
DESCRIBE users;确认
meta 列是 JSON(MySQL)或 jsonb(PostgreSQL)Schema::table('users', function (Blueprint $table) {
$table->json('meta')->nullable()->change();
});TEXT 存 JSON 字符串),改用 'meta' => 'object' 或自定义 cast 类cast 写 'object' 和 'array' 有什么实际区别?两者都要求字段内容是合法 JSON 字符串,但反序列化结果不同:array → PHP 关联数组(['name' => 'foo']),object → stdClass 实例(->name 可访问)。注意:Laravel 6+ 中 'array' 会强制转成「索引数组」,哪怕 JSON 是对象结构——这是常见误解点。
$user->meta->name)→ 用 'meta' => 'object'
$user->meta['name'])且 JSON 确实是对象 → 用 'meta' => 'array',但需确保 JSON 字符串开头是 {,不是 [
[{"id":1}](数组结构),'array' 才能正确解析为 PHP 索引数组settings.theme.color)?Laravel 原生不支持点号路径的自动映射,$casts 只作用于整字段。要操作子属性,得手动处理或借助访问器/修改器。
protected $casts = [
'settings' => 'array'
];
protected function getThemeAttribute()
{
return $this->settings['theme'] ?? [];
}
protected function setThemeAttribute($value)
{
$this->settings = array_merge($this->settings, ['theme' => $value]);
}$user->setting
s['theme']['color'] = 'blue' 后漏掉 save() —— 数组赋值不会触发模型脏检测tap() + put() 链式更新tap($user, function ($u) {
data_put($u->settings, 'theme.color', 'blue');
$u->save();
});array 多出什么能力?当需要类型校验、默认值填充、或非标准序列化(比如存为压缩 JSON、加盐加密)时,必须写自定义 cast。原生 array 只做基础 json_decode / json_encode,无容错。
json_decode('', true) 返回 nullclass SafeArrayCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
return json_decode($value ?? '[]', true) ?: [];
}
public function set($model, string $key, $value, array $attributes)
{
return json_encode($value ?? [], JSON_UNESCAPED_UNICODE);
}
}protected $casts = [
'payload' => SafeArrayCast::class
];CastsAttributes 接口,且 get 方法返回值决定属性访问时的类型is_array($model->attribute) 和 isset($model->attribute['key'])。