本文目录导读:

在 Laravel 项目中,数据库迁移(Migrations)是管理数据库结构版本控制的强大工具,以下是全面的 Laravel 数据库迁移管理指南:
基础命令
创建迁移文件
# 创建迁移(自动根据表名生成) php artisan make:migration create_users_table # 指定表名和操作 php artisan make:migration add_phone_to_users_table --table=users php artisan make:migration create_products_table --create=products # 创建带有模型的迁移 php artisan make:model Product -m
执行迁移
# 运行所有未执行的迁移 php artisan migrate # 指定路径 php artisan migrate --path=/database/migrations/custom # 指定数据库连接 php artisan migrate --database=mysql_backup
回滚迁移
# 回滚最后一次迁移 php artisan migrate:rollback # 回滚多步 php artisan migrate:rollback --step=3 # 回滚所有迁移 php artisan migrate:reset # 回滚并重新迁移 php artisan migrate:refresh # 刷新并执行数据填充 php artisan migrate:refresh --seed
迁移文件结构
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* 运行迁移
*
* @return void
*/
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();
});
}
/**
* 回滚迁移
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
常见字段类型
Schema::create('products', function (Blueprint $table) {
// 主键和索引
$table->id();
$table->bigIncrements('id')->unsigned();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
// 字符串类型
$table->string('name', 100);
$table->char('code', 10);
$table->text('description');
$table->mediumText('medium_text');
$table->longText('long_text');
// 数字类型
$table->integer('quantity');
$table->unsignedInteger('stock')->default(0);
$table->decimal('price', 10, 2);
$table->float('weight', 8, 2);
$table->double('length', 8, 2);
$table->boolean('is_active')->default(true);
// 日期时间
$table->date('published_date');
$table->time('opens_at');
$table->datetime('started_at');
$table->timestamp('expired_at')->nullable();
$table->dateTime('created_at')->useCurrent();
$table->softDeletes(); // deleted_at
// 其他
$table->json('metadata');
$table->binary('file_data');
$table->uuid('uuid');
$table->geometry('location');
$table->enum('status', ['active', 'inactive', 'pending']);
$table->ipAddress('visitor_ip');
$table->macAddress('client_mac');
// 时间戳
$table->timestamps(); // created_at + updated_at
});
常用修饰符
Schema::create('examples', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('用户名称');
$table->integer('age')->unsigned()->default(18);
$table->string('email')->unique();
$table->string('slug')->index();
$table->boolean('is_admin')->default(false);
$table->string('nullable_column')->nullable();
$table->string('first_name')->after('id'); // 位置
$table->string('last_name')->after('first_name');
$table->string('full_name')->storedAs("concat(first_name, ' ', last_name)");
// 复合索引
$table->index(['name', 'email']);
});
表操作
// 重命名表
Schema::rename('old_table', 'new_table');
// 删除表
Schema::drop('posts');
// 检查表是否存在
if (Schema::hasTable('users')) {
// 表存在
}
// 检查列是否存在
if (Schema::hasColumn('users', 'email')) {
// 列存在
}
// 获取所有表
$tables = DB::select('SHOW TABLES');
修改现有表
public function up()
{
Schema::table('users', function (Blueprint $table) {
// 添加字段(需要安装 doctrine/dbal)
$table->string('phone')->nullable()->after('email');
// 修改字段
$table->string('name', 200)->change();
// 重命名字段
$table->renameColumn('from', 'to');
// 删除字段
$table->dropColumn(['column1', 'column2']);
// 删除索引/约束
$table->dropIndex('index_name');
$table->dropUnique('unique_name');
$table->dropForeign('foreign_key_name');
$table->dropPrimary();
// 添加索引
$table->index('column');
$table->unique('column');
});
}
迁移高级特性
条件迁移
public function up()
{
if (!Schema::hasTable('table_name')) {
Schema::create('table_name', function (Blueprint $table) {
// ...
});
}
}
可回滚的迁移
public function up()
{
// 创建视图或存储过程
DB::statement("CREATE VIEW v_users AS SELECT * FROM users");
}
public function down()
{
DB::statement("DROP VIEW IF EXISTS v_users");
}
一次性迁移
Schema::create('temp_table', function (Blueprint $table) {
// 不记录在迁移表
});
迁移注意事项
生产环境部署建议
# 使用 --force 在生产环境执行 php artisan migrate --force # 预先生成迁移 SQL 文件 php artisan schema:dump
迁移顺序管理
创建时间要确保依赖顺序:
// 2024_01_01_000000_create_categories_table.php
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
});
}
// 2024_01_02_000000_create_products_table.php
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')
->constrained() // 自动创建外键和索引
->onDelete('cascade');
});
}
模型与迁移配合
// Product.php
class Product extends Model
{
use SoftDeletes;
protected $fillable = [
'name', 'description', 'price'
];
protected $casts = [
'price' => 'decimal:2',
'is_active' => 'boolean'
];
protected $dates = ['published_at'];
}
最佳实践
迁移文件命名规范
2024_01_01_000000_create_users_table.php
2024_01_02_000000_add_email_to_users_table.php
2024_01_03_000000_drop_unnecessary_columns.php
开发流程建议
# 1. 创建 Model 和迁移 php artisan make:model Product -m -c # 2. 使用资源控制器 php artisan make:controller ProductController --resource # 3. 运行迁移 php artisan migrate --seed # 4. 测试回滚 php artisan migrate:rollback --step=1 # 5. 生产部署 php artisan migrate --force
常用指令组合
# 完全重建数据库(开发环境) php artisan migrate:fresh --seed # 查看迁移状态 php artisan migrate:status # 生成模型关系图(需要额外工具) composer require beyondcode/laravel-er-diagram
十一、注意事项
- 字段类型选择:选择合理的数据类型以节省存储空间和提高查询效率
- 索引优化:在查询频繁的字段上添加索引
- 外键约束:合理使用外键保证数据完整性
- Avoid using Schema::dropIfExists:在生产环境要谨慎
- 迁移原子性:每个迁移应该独立且可逆
十二、第三方扩展
# 安装扩展包
composer require doctrine/dbal # 支持修改字段
composer require laravel/horizon # 队列监控
# 使用扩展
Schema::table('users', function (Blueprint $table) {
$table->string('name')->change();
});
通过遵循这些最佳实践,你可以有效地管理 Laravel 项目的数据库结构,确保项目在不同环境间的可移植性和可维护性。