在 Laravel 项目开发中,数据库结构的管理是一项核心工作。随着项目迭代,如果没有规范的结构管理方式,很容易出现:

  • 开发环境和生产环境结构不一致
  • 团队成员数据库版本混乱
  • 手动修改数据库导致不可追溯
  • 回滚困难

Laravel 提供的 Migrations(数据库迁移) 正是为了解决这些问题。

本文将系统讲解 Laravel Migrations 的使用方式、核心原理以及实战最佳实践。



一、什么是 Migration?

Migration 本质上是:

用代码来管理数据库结构的版本控制系统。

它的作用类似于 Git,只不过 Git 管理代码版本,而 Migration 管理数据库结构版本。



二、创建 Migration

1️⃣ 创建数据表

php artisan make:migration create_users_table

生成文件路径:

database/migrations/2026_02_11_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->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('users');
    }
};


三、Migration 核心方法解析

1️⃣ up()

用于执行结构变更(正向操作)

例如:

  • 创建表
  • 添加字段
  • 添加索引
  • 修改字段


2️⃣ down()

用于回滚操作

必须保证:

up() 做了什么,down() 就要精确反向撤销什么

否则 rollback 会出问题。



四、常用字段类型总结

常见字段类型

$table->id();
$table->string('name', 100);
$table->text('content');
$table->integer('age');
$table->bigInteger('user_id');
$table->boolean('status');
$table->decimal('amount', 10, 2);
$table->timestamp('created_at');
$table->softDeletes();
$table->timestamps();


添加索引

$table->unique('email');
$table->index(['user_id', 'status']);


外键约束

$table->foreignId('user_id')
      ->constrained()
      ->cascadeOnDelete();

等价于:

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');


五、执行 Migration

运行迁移

php artisan migrate


回滚

回滚最近一次:

php artisan migrate:rollback

回滚指定步数:

php artisan migrate:rollback --step=3


重置

php artisan migrate:reset


刷新(重建)

php artisan migrate:refresh

带数据填充:

php artisan migrate:refresh --seed


六、修改已有表结构

添加字段

php artisan make:migration add_phone_to_users_table
Schema::table('users', function (Blueprint $table) {
    $table->string('phone')->nullable();
});


删除字段

$table->dropColumn('phone');

⚠️ 删除字段需要安装:

composer require doctrine/dbal


七、生产环境使用建议

在生产环境执行 migration 时:

php artisan migrate --force

否则 Laravel 会拒绝执行。



八、实战最佳实践总结

✅ 1. 不要直接修改数据库

所有结构变更必须通过 Migration。



✅ 2. 每次结构修改都新建 migration

不要修改旧 migration 文件。

原因:

  • 旧文件可能已经在生产执行
  • 修改会导致版本错乱


✅ 3. 合理命名 migration

好的命名:

add_index_to_users_email
add_status_to_orders_table
modify_amount_precision_in_orders


✅ 4. 使用 Schema::hasTable 判断

在某些特殊场景:

if (!Schema::hasTable('users')) {
    Schema::create(...);
}


✅ 5. 大表修改要谨慎

生产大表添加字段时:

  • 避免高峰期执行
  • 避免锁表操作
  • 尽量添加 nullable 字段


九、Migration 与 Seeder 的关系

Migration 负责:

数据结构

Seeder 负责:

初始化数据

典型流程:

php artisan migrate --seed


十、团队协作中的 Migration 管理策略

推荐流程:

  1. 开发新增 migration
  2. 提交代码
  3. 测试环境执行 migrate
  4. 生产部署时自动执行 migrate


十一、常见问题总结

Q1:迁移文件执行顺序?

按文件名前缀时间戳顺序执行。



Q2:如何查看执行过哪些迁移?

查看数据表:

migrations


Q3:如何只执行某一个 migration?

php artisan migrate --path=database/migrations/xxx.php


十二、总结

Migration 的核心价值:

  • 数据库结构版本化
  • 可回滚
  • 可协作
  • 可自动化部署

一句话总结:

不使用 Migration 的 Laravel 项目,是不完整的项目。