Laravel Media Library v9升级添加generated_conversions列迁移报错排查
报错根因
- 列缺失触发的
SQLSTATE[42S22]错误:spatie/laravel-medialibrary v9版本迭代后,将原本嵌套在custom_propertiesJSON字段内的generated_conversions数据拆分为独立的顶层JSON列,旧版本media表未新增该字段时,执行媒体写入的INSERT操作就会触发列不存在的报错。 - 迁移执行触发的
SQLSTATE[42000] 1064语法错误:迁移代码中使用的->JSON路径简化操作符仅对MySQL 5.7.9+原生支持,MariaDB对该语法的兼容存在版本差异;同时原查询条件中针对JSON字段的空字符串等值判断,会触发隐式类型解析冲突,最终导致SQL语法解析失败。
分步修复方案
1. 迁移文件语法兼容调整
- 替换MariaDB不兼容的JSON取值语法
原代码中使用的custom_properties->"$.generated_conversions"简化写法,替换为全版本兼容的标准JSON函数逻辑,同时增加空值兜底,避免给JSON字段写入非合规格式的值:// 原错误写法 'generated_conversions' => DB::raw('custom_properties->"$.generated_conversions"'), // 兼容MariaDB的正确写法 'generated_conversions' => DB::raw("IFNULL(JSON_UNQUOTE(JSON_EXTRACT(custom_properties, '$.generated_conversions')), JSON_OBJECT())"), - 调整查询过滤条件
原代码中针对JSON字段匹配空字符串的逻辑不符合JSON类型字段的存储规则,是触发语法报错的诱因之一,替换为原生JSON校验逻辑:// 原容易触发语法错误的写法 Media::query() ->whereNull('generated_conversions') ->orWhere('generated_conversions', '') ->orWhereRaw("JSON_TYPE(generated_conversions) = 'NULL'") // 兼容MariaDB的正确写法 Media::query() ->where(function ($query) { $query->whereNull('generated_conversions') ->orWhereRaw("JSON_TYPE(generated_conversions) = 'NULL'") ->orWhereRaw("JSON_LENGTH(generated_conversions) = 0"); }) - 给新增列增加符合扩展包要求的默认值
避免新插入的媒体记录因为字段为null触发扩展包的校验错误,在建列语句中补充默认空对象值:Schema::table('media', function (Blueprint $table) { $table->json('generated_conversions')->default(DB::raw('(JSON_OBJECT())')); }); - 回滚逻辑兼容性说明
迁移down方法中如果启用注释里的字段回写逻辑,因为本身使用的是标准JSON_SET函数,MariaDB可直接兼容,不需要额外调整语法。
2. 迁移执行注意事项
- 不要使用
php artisan migrate:fresh --seed执行升级迁移,该命令会清空全表数据,直接跳过旧数据迁移的实际意义。正确操作流程为:先备份现有media表数据,单独执行这个升级迁移文件完成旧数据转换,再运行扩展包的核心安装迁移逻辑,避免列定义重复冲突。 - 迁移执行前可先在数据库客户端单独运行转换SQL做语法校验:
确认SQL执行无报错后,再运行对应Artisan迁移命令。UPDATE media SET generated_conversions = IFNULL(JSON_UNQUOTE(JSON_EXTRACT(custom_properties, '$.generated_conversions')), JSON_OBJECT()) WHERE generated_conversions IS NULL OR JSON_TYPE(generated_conversions) = 'NULL' OR JSON_LENGTH(generated_conversions) = 0;
内容的提问来源于stack exchange,提问作者AlmoDev
相关产品推荐
相关产品推荐

