正确写法是php artisan make:migration create_users_table,类名合法且符合Laravel迁移命名规范;错误写法如add email to users因含空格导致文件名非法,后续migrate会跳过该文件。

php artisan make:migration 命令怎么写才不报错
创建迁移文件最常踩的坑是表名和动作描述混在一起,导致生成的类名非法(比如含冒号、空格或中文)。Laravel 要求迁移文件名必须是「时间戳_小写字母+下划线」格式,而 make:migration 命令只负责生成骨架,不校验语义。
- 正确写法:
php artisan make:migration create_users_table(生成CreateUsersTable类) - 错误写法:
php artisan make:migration add email to users(空格和关键词导致类名AddEmailToUsers但文件名非法,后续artisan migrate会跳过该文件) - 如果要加字段,推荐用
add_{field}_to_{table}_table模式,如add_phone_to_users_table - 别在命令里写数据库类型(如
create_users_table_with_uuid),迁移逻辑写在up()方法里更清晰
迁移文件里 Schema::create 和 Schema::table 的区别
新手常把建表和改表逻辑全塞进一个迁移,结果上线后执行失败——因为 Schema::create() 要求表不存在,Schema::table() 要求表必须存在。两者不能互换,且 Laravel 不做运行时检查。
-
Schema::create('users', function (Blueprint $table) { ... }):仅用于新建表,若表已存在,执行时抛出SQLSTATE[42S01]: Base table or view already exists -
Schema::table('users', function (Blueprint $table) { ... }):仅用于修改已有表,若表不存在,抛出SQLSTATE[42S02]: Base table or view not found - 新增字段、索引、外键一律用
Schema::table();删字段需注意 MySQL 8.0+ 才支持$table->dropColumn(),低版本得手写DB::statement() - 一个迁移文件里可以多次调用
Schema::table(),但不要混用create和table
php artisan migrate 执行失败常见原因
执行迁移卡住或报错,90% 不是语法问题,而是环境状态不一致:本地有表、生产库没表;或者 migration 表记录错乱。
- 先确认
migrations表是否存在且可读写(Laravel 自动建,但某些共享主机禁用自动建表) - 执行
php artisan migrate:status查看哪些迁移标记为Ran,哪些是Pending;如果状态和磁盘文件不一致,别直接migrate,先用migrate:reset或手动清理migrations表 - MySQL 报
Specified key was too long?那是默认 utf8mb4 字符集下索引长度超限,要在config/database.php的mysql配置里加'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',并确保App\Providers\AppServiceProvider中调用了Schema::defaultStringLength(191) - 执行中中断(Ctrl+C 或超时),可能导致
migrations表写入一半,此时要先查migrations表最后一条记录,再决定是migrate:rollback还是手动删记录
本地开发和线上部署迁移操作差异
本地 php artisan migrate 可以反复跑,线上却必须严格按顺序、只进不退。Laravel 不锁迁移过程,多实例并发执行同一迁移可能引发冲突。
- 线上部署务必加
--force参数(否则交互式确认会卡住),例如:php artisan migrate --force --no-interaction - 禁止在生产环境用
migrate:refresh或migrate:reset,它们会删数据;要用migrate:fresh --seed仅限新环境初始化 - 团队协作时,迁移文件一旦提交 Git,就不能再改
up()或down()逻辑;修复只能靠新增迁移文件(比如字段类型改错了,就写个change_email_type_in_users_table) - 有些云数据库(如 AWS RDS Proxy、阿里云 PolarDB)对 DDL 语句有连接池限制,长迁移(如给千万级表加索引)建议拆成两步:先
ALTER TABLE ... ALGORITHM=INPLACE(如果支持),再用 Laravel 迁移包装
迁移不是写完就能跑通的代码,它是数据库 schema 的“版本快照”,一旦生效,回滚成本远高于 PHP 代码。每次改 up() 前,先想清楚 down() 怎么写,哪怕暂时用不上。











