数据库迁移 #
一、迁移概述 #
1.1 什么是迁移 #
迁移是数据库的版本控制系统,允许你用代码定义数据库结构,并与团队成员共享。
text
迁移的作用
├── 版本控制
│ ├── 记录数据库变更历史
│ └── 可回滚到任意版本
├── 团队协作
│ ├── 共享数据库结构
│ └── 同步数据库变更
└── 环境一致
├── 开发环境
├── 测试环境
└── 生产环境
1.2 迁移文件位置 #
迁移文件存放在 database/migrations 目录下。
二、创建迁移 #
2.1 创建迁移文件 #
bash
# 创建迁移
php artisan make:migration create_users_table
# 指定表名
php artisan make:migration create_users_table --create=users
# 修改现有表
php artisan make:migration add_votes_to_users_table --table=users
2.2 迁移文件结构 #
php
// database/migrations/2024_01_01_000000_create_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
};
三、表结构构建 #
3.1 创建表 #
php
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
3.2 修改表 #
php
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->after('email');
});
3.3 删除表 #
php
Schema::dropIfExists('users');
3.4 重命名表 #
php
Schema::rename('users', 'members');
四、字段类型 #
4.1 常用字段类型 #
php
Schema::create('example', function (Blueprint $table) {
// 数字类型
$table->bigIncrements('id'); // 自增BIGINT主键
$table->bigInteger('votes'); // BIGINT
$table->integer('votes'); // INTEGER
$table->mediumInteger('votes'); // MEDIUMINT
$table->smallInteger('votes'); // SMALLINT
$table->tinyInteger('votes'); // TINYINT
$table->unsignedInteger('votes'); // UNSIGNED INTEGER
$table->decimal('amount', 8, 2); // DECIMAL
$table->float('amount', 8, 2); // FLOAT
$table->double('amount', 8, 2); // DOUBLE
// 字符串类型
$table->string('name', 100); // VARCHAR
$table->text('description'); // TEXT
$table->mediumText('description'); // MEDIUMTEXT
$table->longText('description'); // LONGTEXT
$table->char('code', 10); // CHAR
// 日期时间类型
$table->date('created_at'); // DATE
$table->time('created_at'); // TIME
$table->dateTime('created_at'); // DATETIME
$table->timestamp('created_at'); // TIMESTAMP
$table->timestamps(); // created_at, updated_at
$table->softDeletes(); // deleted_at
$table->year('birth_year'); // YEAR
// 布尔类型
$table->boolean('active'); // BOOLEAN
// 枚举类型
$table->enum('status', ['pending', 'active', 'inactive']);
// JSON类型
$table->json('options'); // JSON
$table->jsonb('options'); // JSONB
// 二进制类型
$table->binary('data'); // BLOB
// 其他类型
$table->uuid('id'); // UUID
$table->ipAddress('ip'); // IP地址
$table->macAddress('mac'); // MAC地址
$table->geometry('position'); // GEOMETRY
$table->point('position'); // POINT
$table->rememberToken(); // remember_token
});
4.2 字段修饰符 #
php
Schema::table('users', function (Blueprint $table) {
$table->string('email')->nullable(); // 允许NULL
$table->string('name')->default('Guest'); // 默认值
$table->string('email')->unique(); // 唯一索引
$table->string('name')->first(); // 放在表首位
$table->string('phone')->after('email'); // 放在某字段后
$table->string('name')->comment('用户名'); // 注释
$table->string('name')->charset('utf8mb4'); // 字符集
$table->string('name')->collation('utf8mb4_unicode_ci'); // 排序规则
$table->integer('votes')->unsigned(); // 无符号
$table->integer('votes')->autoIncrement(); // 自增
$table->string('name')->storedAs('expression'); // 存储生成列
$table->string('name')->virtualAs('expression'); // 虚拟生成列
});
五、索引 #
5.1 创建索引 #
php
Schema::table('users', function (Blueprint $table) {
// 主键
$table->primary('id');
$table->primary(['id', 'parent_id']);
// 唯一索引
$table->unique('email');
$table->unique(['email', 'name']);
// 普通索引
$table->index('name');
$table->index(['name', 'email']);
// 全文索引
$table->fullText('description');
// 指定索引名称
$table->unique('email', 'unique_email_index');
});
5.2 删除索引 #
php
Schema::table('users', function (Blueprint $table) {
$table->dropPrimary('users_id_primary');
$table->dropUnique('users_email_unique');
$table->dropIndex('users_name_index');
$table->dropFullText('users_description_fulltext');
});
5.3 外键约束 #
php
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
// 或
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
5.4 删除外键 #
php
Schema::table('posts', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->dropForeign('posts_user_id_foreign');
});
六、字段操作 #
6.1 添加字段 #
php
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->after('email');
$table->string('address')->nullable();
});
6.2 修改字段 #
php
Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change();
$table->string('name', 50)->nullable()->change();
});
需要安装 doctrine/dbal:
bash
composer require doctrine/dbal
6.3 重命名字段 #
php
Schema::table('users', function (Blueprint $table) {
$table->renameColumn('from', 'to');
});
6.4 删除字段 #
php
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('votes');
$table->dropColumn(['votes', 'avatar', 'location']);
});
七、运行迁移 #
7.1 执行迁移 #
bash
# 执行所有未执行的迁移
php artisan migrate
# 查看迁移状态
php artisan migrate:status
7.2 回滚迁移 #
bash
# 回滚最后一次迁移
php artisan migrate:rollback
# 回滚最近5次迁移
php artisan migrate:rollback --step=5
# 回滚所有迁移
php artisan migrate:reset
7.3 重置并重新迁移 #
bash
php artisan migrate:fresh
# 同时填充数据
php artisan migrate:fresh --seed
7.4 强制在生产环境运行 #
bash
php artisan migrate --force
八、迁移实战 #
8.1 创建用户表 #
php
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
8.2 创建文章表 #
php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('title');
$table->string('slug')->unique();
$table->text('content');
$table->enum('status', ['draft', 'published'])->default('draft');
$table->timestamp('published_at')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index(['status', 'published_at']);
});
8.3 创建评论表 #
php
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->text('content');
$table->morphs('commentable'); // 多态关联
$table->timestamps();
$table->index(['user_id', 'post_id']);
});
8.4 添加字段 #
php
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->nullable()->after('email');
$table->string('avatar')->nullable()->after('phone');
$table->json('preferences')->nullable()->after('avatar');
});
九、最佳实践 #
9.1 迁移命名规范 #
bash
# 创建表
create_users_table
# 添加字段
add_phone_to_users_table
# 修改字段
change_users_name_length
# 删除字段
remove_phone_from_users_table
# 创建索引
add_index_to_users_email
9.2 迁移顺序 #
text
迁移文件按时间戳排序执行:
2024_01_01_000000_create_users_table.php
2024_01_01_100000_create_posts_table.php
2024_01_02_000000_add_phone_to_users_table.php
9.3 回滚安全 #
php
public function down()
{
// 确保回滚操作安全
Schema::dropIfExists('users');
// 或更精确的回滚
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('phone');
});
}
9.4 生产环境注意事项 #
text
生产环境迁移注意事项:
1. 备份数据库
2. 先在测试环境验证
3. 避免删除重要数据
4. 使用事务包裹
5. 考虑大数据表迁移时间
十、常见问题 #
10.1 迁移卡住 #
bash
# 查看迁移状态
php artisan migrate:status
# 手动解决
php artisan migrate:rollback
10.2 外键约束错误 #
php
// 迁移顺序很重要
// 先创建被引用的表
Schema::create('users', function (Blueprint $table) {
$table->id();
// ...
});
// 再创建引用表
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
// ...
});
10.3 字段修改问题 #
bash
# 安装依赖
composer require doctrine/dbal
十一、总结 #
11.1 核心命令 #
| 命令 | 说明 |
|---|---|
| make:migration | 创建迁移 |
| migrate | 执行迁移 |
| migrate:rollback | 回滚迁移 |
| migrate:fresh | 重置迁移 |
| migrate:status | 查看状态 |
11.2 核心方法 #
| 方法 | 说明 |
|---|---|
| Schema::create() | 创建表 |
| Schema::table() | 修改表 |
| Schema::drop() | 删除表 |
| $table->id() | 自增主键 |
| $table->timestamps() | 时间戳 |
| $table->foreignId() | 外键 |
11.3 下一步 #
掌握了数据库迁移后,让我们继续学习 表单处理,了解Laravel表单操作!
最后更新:2026-03-28