MySQL低于5.7.8时不支持JSON类型,迁移需先检测版本并降级为TEXT字段,配合PHP层序列化处理,同时避免使用JSON函数。

Yii2 迁移中新增 JSON 字段,若目标 MySQL 版本低于 5.7.8,会直接建表失败——因为低版本根本不识别 JSON 类型,CREATE TABLE 语句一出现该关键字就报 ERROR 1064 (42000)。不能硬上,必须做兼容性降级。
迁移前先判断目标库是否支持 JSON
在执行迁移前,应主动探测数据库能力,而不是依赖运行时报错:
- 在迁移类的
up()方法开头加检查:if (!$this->db->getSchema()->getTableSchema('your_table', true)) { /* 表不存在,可建 */ }
更关键的是查 JSON 支持:$jsonTest = $this->db->createCommand("SELECT JSON_TYPE('{\"a\":1}')")->queryScalar();<br>if ($jsonTest === false || $jsonTest === null) { throw new Exception('MySQL version < 5.7.8: JSON type not supported'); } - 或者更轻量:用
SELECT VERSION()获取版本号,解析主版本+次版本(如5.6、5.7.12),低于5.7.8则拒绝执行 JSON 相关 DDL
低版本替代方案:用 TEXT + 注释明确用途
当确认目标库不支持 JSON 时,字段类型必须退化为 TEXT,并在迁移文件和数据库注释中清晰标注其语义:
- 建字段写法:
$this->addColumn('article', 'meta', $this->text()->comment('JSON field for i18n fallback, not for search')); - 避免用
json做字段名(易误导),建议用meta_data或config_text等中性名称 - 在 Yii2 模型中,通过
afterFind和beforeSave自动处理序列化/反序列化,保持业务层调用一致:
例如$model->meta_data读取时自动json_decode,保存前自动json_encode
迁移文件需显式声明兼容边界
一个健壮的迁移文件不应假设所有环境都支持新特性:
- 文件名和类名仍按标准时间戳命名(如
m260928_103000_add_meta_to_article.php),但类中要加说明注释:// ⚠️ Requires MySQL ≥ 5.7.8 for JSON type. For older versions, TEXT is used with manual JSON handling. - 如果项目需长期兼容 5.6,建议拆成两个迁移:
—m260928_102000_add_meta_text_version.php(通用版)
—m260928_103000_add_meta_json_version.php(高版本专用,通过$depends声明前置依赖) - 避免在
down()中盲目删字段;应先判断字段是否存在:if ($this->db->getTableSchema('article')?->getColumn('meta_data')) { $this->dropColumn('article', 'meta_data'); }
应用层必须放弃 JSON 函数依赖
一旦用了 TEXT 替代 JSON,所有原生 JSON 查询逻辑必须重构:
- 不能用
JSON_EXTRACT(meta, '$.title'),只能走 PHP 层解析后匹配 - 搜索场景(如“查所有含 tag=‘api’ 的记录”)需改为全表扫描 +
strpos(json_encode($row['meta_data']), '"api"'),或提前在额外字段冗余关键值 - Yii2 AR 查询中禁用
JSON_CONTAINS等表达式,否则在低版本环境运行时直接 SQL 报错


















