Laravel迁移不可手写SQL脚本替代,因其绕过migrations表导致状态错乱、执行顺序失控、down逻辑缺失;应坚持用php artisan make:migration生成类,必要时在up()/down()中调用DB::statement执行原生SQL。

直接用 PHP 写数据库迁移脚本是可行的,但绕过 Laravel 的 migrate 命令和 migrations 表管理,极易导致状态错乱、回滚失效、团队协作失败——除非你明确在做轻量 CLI 工具或嵌入式系统,否则不建议脱离 Laravel 迁移机制自行实现。
为什么不能手写 SQL 文件 + foreach 执行
常见错误是把迁移当成“一堆 SQL 脚本”,用 PHP 读取 ./migrations/*.sql 然后逐条 PDO::exec()。这会跳过三个关键控制点:
-
migrations表缺失:Laravel 靠它记录哪些迁移已执行,没有这张表,php artisan migrate:rollback就无法知道该撤哪一条 - 执行顺序不可控:SQL 文件名若不含时间戳,不同环境执行顺序可能不一致,外键引用表还没建就去建子表,报错
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table - down() 逻辑丢失:手写 SQL 很难自动推导“逆操作”,比如
ADD COLUMN email的 rollback 是DROP COLUMN email,但字段改类型、索引重命名等场景需人工维护两份 SQL,极易遗漏
如何复用 Laravel Migration 的核心能力
真正可落地的做法,是继续用 php artisan make:migration 生成标准迁移类,只在必要时绕过 Schema 构建器,改用原生 SQL:
- 在
up()中调用DB::statement('CREATE VIEW ...')或DB::unprepared('CREATE PROCEDURE ...')处理视图、存储过程等 Schema 构建器不支持的操作 - 确保
down()写对应清理语句,例如DB::statement('DROP VIEW IF EXISTS user_summary') - 所有变更仍走
php artisan migrate流程,保证记录进migrations表,不影响rollback和refresh - 避免在迁移中使用模型(如
User::create()),因为模型可能依赖尚未迁移完成的字段或关系
模块化项目中迁移路径不生效
用 nWidart/laravel-modules 时,执行 php artisan module:migrate Admin 却提示 “No migrations to run”,大概率是路径或配置没对上:
立即学习“PHP免费学习笔记(深入)”;
- 确认模块目录下存在
Modules/Admin/Database/Migrations/,且文件名带标准时间戳前缀(如2025_11_26_000000_create_admin_users_table.php) - 检查
Modules/Admin/module.json中"enabled": true,且未被php artisan module:disable Admin关闭 - 运行
php artisan module:migrate Admin --pretend查看实际扫描路径是否匹配预期;若显示路径为base_path('Modules/Admin/Database/Migrations')但无文件,则是目录结构或文件命名不合规 - 不要手动把模块迁移文件复制到
database/migrations/下——这样module:migrate找不到,而migrate又会重复执行,破坏一致性
最易被忽略的一点:迁移文件里写了 Schema::table('users', ...),但该表由另一个模块提供,而那个模块的迁移尚未执行。Laravel 不校验跨模块依赖,只按时间戳顺序跑,出错才报。得靠人眼或文档约定执行顺序,或者把强依赖的迁移合并进同一模块。



















