php artisan migrate --pretend 不输出 SQL,仅模拟执行并返回成功/失败;真正预览 SQL 需用 schema:dump --ansi(Laravel 9+)或 DB::listen() 捕获,测试应使用内存 SQLite 或独立测试库确保环境隔离。

php artisan migrate --pretend 为什么没输出 SQL
它确实不会打印 SQL,只模拟执行并报告是否通过。很多人误以为 --pretend 是“查看将要执行什么”,其实它只是跳过写库、保留校验逻辑(比如字段是否存在、索引名是否重复)。真正想看 SQL,得换方式。
-
php artisan migrate --pretend只返回成功/失败,不输出语句;失败时会抛出具体错误,比如SQLSTATE[42S01]: Base table or view already exists - 想预览 SQL,用
php artisan schema:dump --ansi(Laravel 9+)配合--dry-run不够直观,更可靠的是临时改写迁移文件,在up()里加DB::listen()捕获查询(仅开发环境) - 注意:某些数据库驱动(如 SQLite)在
--pretend下可能跳过部分约束检查,MySQL 则较严格——别依赖它发现所有兼容性问题
测试迁移是否报错,但不想改数据库
核心是隔离环境 + 控制副作用。本地用内存 SQLite 最稳,不是因为快,而是它天然不污染真实库,且支持大部分语法。
- 在
phpunit.xml中配一个专用测试数据库连接:DB_CONNECTION=sqlite和DB_DATABASE=:memory: - 跑迁移前确保
artisan migrate:refresh --database=testing能清空重来;否则残留表会导致后续迁移误判 - 别用
--pretend替代真实执行——比如外键顺序、视图依赖、存储过程等,只有真跑一遍才会暴露 - 如果必须用 MySQL 测试,务必指定独立库名(如
test_migrations),并在 CI 中自动创建/销毁,避免和开发库混用
php artisan migrate:fresh --seed 报错但 --pretend 不报,怎么回事
--pretend 不执行 down(),也不触发 Seeder,更不检查外键级联行为。很多“静默失败”其实藏在回滚或填充阶段。
- 常见坑:迁移中用了
foreignIdFor(User::class),但users表在当前批次还没建,--pretend不报,migrate:fresh直接崩 - Seeder 里调了未初始化的配置(如
config('app.name')),--pretend完全不走这一步 - 解决方法:把迁移拆成小步,用
php artisan migrate --step=1逐个验证;或者给 Seeder 加if (app()->environment('testing'))防止干扰 - 注意:Laravel 10+ 的
migrate:fresh默认禁用外键检查,但某些云数据库(如 AWS RDS)仍可能拦截,需手动加DB::statement('SET FOREIGN_KEY_CHECKS=0');
CI 中自动化测试迁移,怎么避免漏掉隐式依赖
最常漏的是迁移文件命名顺序和 PHP 类名不一致,或者用了 Schema::create('xxx', function () {}) 却忘了 use Illuminate\Support\Facades\Schema;。
- 在 CI 脚本里加校验步骤:
php artisan migrate:status | grep "Ran"确保无 pending;再跑一次php artisan migrate:rollback --step=1 && php artisan migrate确认可逆 - 用
composer test触发一个最小迁移测试用例,该用例只包含一个新建表 + 一个添加字段,强制覆盖基础路径 - 禁止在迁移中调用 Eloquent 模型——模型可能依赖尚未迁移的表,导致
--pretend成功但真实运行失败 - 留意 Laravel 版本升级后的变更:比如 9.x 开始
bigIncrements默认变unsignedBigInteger,老迁移若显式写了unsigned()会冲突
迁移不是写完就扔,关键在验证路径是否闭环。哪怕加一行 DB::table('migrations')->where('migration', 'like', '%create_posts_table%')->count() 做断言,也比只信 --pretend 强。


















