yii migrate/create 带 --fields 参数不自动生成字段,因默认只生成空骨架;需 Yii ≥2.0.41 且启用增强版 migrate 控制器,字段语法须严格如 name:string(100):notNull。

yii migrate/create 带参数生成迁移文件时,为什么 up() 里没自动加字段?
因为 yii migrate/create 默认只生成空骨架,不解析参数含义。它把所有额外参数(比如 --fields="name:string(100) email:email")原样塞进文件名或注释,但不会自动生成 $this->createTable() 或字段定义。
真正能触发字段代码生成的是 yii migrate/create create_post_table --fields="title:string(255):notNull,body:text" 这类命令 —— 但前提是你的 Yii 版本 ≥ 2.0.41 且用了官方增强版 migrate/create(非基础命令)。老版本或自定义命令模板基本忽略 --fields。
- 检查是否启用了
yii\console\controllers\MigrateController的增强字段支持:在console/config/main.php中确认没有覆盖migrate命令类 - 若用的是自定义模板,需手动在模板里解析
$params['fields']并拼 SQL;否则字段定义得手写 - 字段语法必须严格:
name:integer:notNull:defaultValue(0),中间不能有空格,括号不支持嵌套
yii migrate/up --interactive=1 执行时卡住,光标不动
这不是卡死,是 Yii 在等你输入「y」或「n」确认每条迁移。但终端可能没显示提示文字,尤其当输出被重定向、或用了某些 SSH 客户端(如 MobaXterm 默认关掉交互回显)。
典型现象:*** applying m230101_120000_create_user_table 后停住,stdin 没响应。本质是 PHP 的 fgets(STDIN) 调用阻塞了。
- 先试
echo "y" | yii migrate/up --interactive=1看是否跳过 —— 如果成功,说明确实是交互等待问题 - 避免在 CI/CD 或 crontab 里用
--interactive=1,改用--include-all=1+ 显式指定版本号 - 某些 Docker 容器启动时没分配 TTY(比如
docker run -d),会导致STDIN不可用,必须加-t参数
带参数运行迁移时,yii migrate/up --migrationPath=@app/migrations/admin 报错 “Unknown option: migrationPath”
因为 --migrationPath 是 migrate 命令的配置项,不是 up 子命令的选项。Yii 的命令行参数解析规则是:全局选项(如 --color)放前面,子命令专属选项(如 up 的 --time)只能跟在子命令后。
正确写法只有两种:yii migrate --migrationPath=@app/migrations/admin up,或更推荐的方式 —— 在配置里预设路径:
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => '@app/migrations/admin',
],
],- 直接在命令中混用
--xxx和子命令顺序错位,90% 会报 “Unknown option” -
@app别名必须已注册,否则路径解析失败,错误信息可能是 “Directory does not exist” 而非路径参数错误 - 多个迁移路径要用数组:
'migrationPaths' => ['@app/migrations', '@vendor/yiisoft/yii2-auth/migrations'](注意是paths复数)
迁移中调用 $this->db->createCommand() 手动建表,为什么事务没生效?
Yii 迁移默认开启事务,但 createCommand() 执行 DDL(如 CREATE TABLE、ALTER TABLE)在 MySQL/PostgreSQL 中会隐式提交当前事务 —— 这是数据库行为,不是 Yii 的 bug。
结果就是:DDL 之后的语句(比如插入测试数据)如果出错,前面的建表操作无法回滚。
- MySQL 8.0+ 对部分 DDL 支持原子性,但 Yii 不做适配,仍建议拆成两个迁移:一个纯 DDL,一个纯 DML
- 想强制事务控制,得用
$this->db->getSchema()->createTable()等 ActiveRecord 封装方法,它们内部做了兼容处理 - PostgreSQL 中
CREATE INDEX CONCURRENTLY不能在事务块里执行,必须单独迁移,否则直接报错
实际用起来最麻烦的从来不是语法,而是不同 Yii 小版本对命令参数的兼容策略不一致,还有 DDL 事务这种数据库底层行为和框架抽象之间的缝隙 —— 得盯着日志里那句 “executing SQL” 后有没有 “commit transaction” 才敢放心。


















