
php artisan make:migration 生成的文件名和函数名怎么定
生成迁移文件时,Laravel 不关心你写的是 create_users_table 还是 add_status_to_posts,但它会把下划线转成驼峰,自动推导出类名。比如 php artisan make:migration create_posts_table 会生成 CreatePostsTable 类;而 php artisan make:migration add_is_active_to_users 会变成 AddIsActiveToUsers —— 注意:不是 AddIsactiveToUsers,is_active 中的 is 会被识别为前缀,active 首字母大写。
容易踩的坑:
- 别用大写字母命名迁移文件(如
CreateUsersTable.php),Laravel 的命令行工具只接受小写+下划线 - 别在文件名里加年份或时间戳(如
2024_05_10_create_users_table),Laravel 自动加了时间前缀,手动加会导致重复或错乱 - 类名不能和已有迁移类重名,否则
php artisan migrate会报Class not found
up() 和 down() 里该写什么、不该写什么
up() 是执行迁移时运行的逻辑,down() 是回滚时运行的逻辑,二者必须对称。常见错误是只写 up(),或者 down() 里删表却不重建索引、不还原外键约束。
实操建议:
-
up()中建表优先用Schema::create(),改结构用Schema::table();避免在up()里塞大量数据插入(那是 seeder 的事) -
down()必须能安全执行多次:删表前加if (Schema::hasTable('xxx')),删列前确认该列存在(Laravel 9+ 支持dropColumn(),但低版本需手动判断) - 不要在
down()里写DB::table()->truncate()或delete(),清数据不属于迁移职责,且不可逆
运行 migrate 时提示 “SQLSTATE[HY000]: General error: 1005” 或外键失败
这通常是因为引擎不一致或字段类型不匹配。InnoDB 表之间建外键时,关联字段必须完全一致:类型、长度、是否为 unsigned、字符集、排序规则都不能差一点。
典型场景:
- 主表
id是bigIncrements()(即unsignedBigInteger),从表却用integer()做外键 → 报错 - 主表用
utf8mb4_unicode_ci,从表没显式指定,MySQL 默认用utf8mb4_0900_ai_ci→ 外键创建失败 - 没在
Schema::create()里调用$table->engine = 'InnoDB',某些旧配置下默认是 MyISAM → 不支持外键
解决方法:统一用 bigInteger('user_id')->unsigned()->index() + $table->foreign('user_id')->references('id')->on('users'),并在 AppServiceProvider 的 boot() 里加 Schema::defaultStringLength(191)(Laravel 5.8+ 可省略)。
已经 migrate 过的表,怎么安全加字段或改类型
直接改已存在的迁移文件再跑 migrate 是危险操作:Laravel 记录的是迁移文件名哈希,不是内容。改了文件内容,下次 migrate 不会重新执行,但数据库结构可能和代码不一致。
正确做法是新建迁移:
- 加字段:用
php artisan make:migration add_phone_to_users,在up()里写Schema::table('users', function (Blueprint $table) { $table->string('phone')->nullable(); }); - 改字段类型:Laravel 8+ 支持
$table->string('name', 100)->change(),但要先装doctrine/dbal扩展;没装就只能新建迁移 + 手动 SQL(DB::statement('ALTER TABLE ...')),并确保down()可逆 - 别在生产环境直接
migrate:fresh或db:wipe,那会丢数据;有数据的表,改结构务必先备份
最常被忽略的一点:修改字段时,如果该字段上有索引或外键,change() 可能失败,得先 dropForeign() / dropIndex(),改完再重建 —— 这些都得手写进迁移,Laravel 不自动处理。










