跳转到主要内容

什么是迁移

迁移就像是数据库的版本控制。 团队可以共享和管理应用的数据库结构定义。 你或许有过在拉取代码后被要求「请在本地数据库手动加一列」的经历。迁移正好解决了这类问题。 迁移文件存放在 database/migrations 目录,文件名包含时间戳,Laravel 据此决定执行顺序。

创建迁移文件

使用 make:migration Artisan 命令:
php artisan make:migration create_posts_table
Laravel 会根据迁移名推测表名并生成合适的骨架。create_posts_table 就会预置创建 posts 表的代码。

迁移结构

迁移类包含 updown 两个方法:
  • up:向数据库添加表、列、索引。
  • down:撤销 up 的操作,用于回滚。
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->timestamps();
        });
    }

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

常见列定义方法

Blueprint 类内置多种列类型。
方法说明
$table->id()自增主键(bigIncrements('id') 别名)
$table->string('name')VARCHAR(默认 255)
$table->text('body')TEXT
$table->integer('count')INTEGER
$table->boolean('active')用 TINYINT 存储布尔值
$table->timestamp('published_at')TIMESTAMP
$table->timestamps()同时添加 created_atupdated_at
$table->softDeletes()添加软删除字段 deleted_at
$table->foreignId('user_id')外键用 BIGINT UNSIGNED

列修饰符

可以链式添加修饰符:
$table->string('email')->unique();
$table->string('name')->nullable();
$table->integer('votes')->default(0);
$table->string('title')->after('id'); // 在指定列之后

执行迁移

migrate 命令运行未执行的迁移。
php artisan migrate
查看执行情况:
php artisan migrate:status
在生产环境执行迁移会出现确认提示。若需跳过可加 --force,但因为有可能丢失数据请谨慎操作。

回滚

回滚最近一次迁移批次:
php artisan migrate:rollback
按步数回滚:
# 回滚最近 5 次
php artisan migrate:rollback --step=5
回滚全部并重新运行:
php artisan migrate:refresh
migrate:refresh 会重建所有表,既有数据会丢失,适合开发中的数据库重置。

实战示例:创建 posts 表

以博客文章的 posts 表为例。

1. 生成迁移

php artisan make:migration create_posts_table

2. 编辑迁移

打开 database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('title');
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
        });
    }

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

3. 执行迁移

php artisan migrate
数据库中会创建 posts 表。

4. 后期追加列

后期添加列时不要修改已有迁移,而是新建迁移:
php artisan make:migration add_excerpt_to_posts_table
public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->string('excerpt')->nullable()->after('title');
    });
}

public function down(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropColumn('excerpt');
    });
}
尽量不要修改已存在的迁移文件,否则会破坏与其他成员或生产环境的一致性。所有更改都以新迁移的形式添加。

迁移事件

每次迁移操作会派发事件,都继承 Illuminate\Database\Events\MigrationEvent
说明
Illuminate\Database\Events\DatabaseRefreshedmigrate:refresh 完成后
Illuminate\Database\Events\MigrationsStarted迁移批次即将开始
Illuminate\Database\Events\MigrationsEnded迁移批次结束后
Illuminate\Database\Events\MigrationStarted单个迁移即将执行
Illuminate\Database\Events\MigrationEnded单个迁移完成
Illuminate\Database\Events\NoPendingMigrations迁移命令判定无未执行迁移
Illuminate\Database\Events\SchemaDumped数据库结构 dump 完成
Illuminate\Database\Events\SchemaLoaded载入已有 dump
例如可监听 MigrationsEnded 在迁移完成后清理缓存:
use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Event;

Event::listen(MigrationsEnded::class, function () {
    Cache::flush();
});

下一步

数据库填充

了解如何为迁移创建的表填充示例数据。

Eloquent 入门

学习通过 Eloquent ORM 操作迁移创建的表。
最后修改于 2026年7月13日