数据库迁移是 Laravel 中用于管理数据库结构的版本控制系统,它允许你使用 PHP 代码定义和修改数据库表,并轻松在团队中同步。 本章将系统讲解如何编写迁移文件,包括创建表、修改表、添加字段、索引和外键约束。
迁移就像数据库的版本控制,让你能够轻松地创建和修改数据库表。每一条迁移文件都记录了数据库的一次变更(如创建表、添加字段等),并且可以按需回滚。 使用迁移的好处包括:
使用 Artisan 命令 make:migration 创建迁移文件:
php artisan make:migration create_users_table
php artisan make:migration add_email_verified_at_to_users_table
命令选项:
--create=表名:指定要创建的表,Laravel 会自动生成表创建模板。--table=表名:指定要修改的表,Laravel 会生成修改表结构模板。例如:
php artisan make:migration create_posts_table --create=posts
php artisan make:migration add_category_id_to_posts_table --table=posts
生成的迁移文件位于 database/migrations 目录,文件名包含时间戳以避免冲突。
一个典型的迁移文件包含 up 和 down 两个方法:
<?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('content');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
up():执行迁移时运行的方法,用于创建/修改数据库结构。down():回滚迁移时运行的方法,用于撤销 up() 所做的更改。--class 选项生成传统的命名类。
在迁移中可以使用丰富的字段类型,以下是常用的几种:
$table->id(); — 自增主键,等价于 bigIncrements('id')。$table->string('name', 100); — VARCHAR 字段,可指定长度。$table->text('description'); — TEXT 字段。$table->integer('age'); — INT 字段。$table->bigInteger('user_id'); — BIGINT 字段。$table->boolean('is_active'); — BOOLEAN/TINYINT 字段。$table->date('birthday'); — DATE 字段。$table->datetime('published_at'); — DATETIME 字段。$table->timestamp('created_at')->nullable(); — TIMESTAMP 字段。$table->json('metadata'); — JSON 字段。$table->enum('status', ['active', 'inactive']); — ENUM 字段(但注意 MySQL 的 ENUM 有一些限制)。$table->timestamps(); — 创建 created_at 和 updated_at 字段。$table->softDeletes(); — 添加 deleted_at 字段(软删除)。还有许多其他类型,如 float、double、char、binary 等,可根据需要查阅文档。
字段定义后可以链式调用修饰符:
$table->string('email')->unique(); // 唯一索引
$table->string('name')->nullable(); // 允许 NULL
$table->integer('age')->default(18); // 默认值
$table->text('content')->comment('文章内容'); // 添加注释
$table->timestamp('published_at')->useCurrent(); // 使用 CURRENT_TIMESTAMP
$table->index('email'); // 普通索引
$table->unique('email'); // 唯一索引
$table->fullText('content'); // 全文索引(MySQL)
$table->primary('id'); // 主键(通常用 id() 自动创建)
也可以创建复合索引:
$table->index(['user_id', 'created_at']);
$table->foreignId('user_id')
->constrained()
->onDelete('cascade');
上面的方法会为 user_id 字段创建外键,引用 users 表的 id 字段。constrained() 可以指定表名和字段名,例如 constrained('users', 'id')。
如果你使用的是 unsignedBigInteger,可以手动创建外键:
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
--foreign 选项或确保迁移顺序正确。
使用 Schema::table 可以修改已有表:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('avatar')->nullable()->after('email');
$table->renameColumn('name', 'full_name');
$table->dropColumn('age');
});
}
常用的修改方法:
addColumn / 直接调用字段方法添加字段。renameColumn — 重命名字段。dropColumn — 删除字段。change — 修改字段类型(需要安装 doctrine/dbal 扩展)。composer require doctrine/dbal
然后:
$table->string('name', 50)->change();
php artisan migrate
该命令会运行所有未执行过的迁移。
php artisan migrate:rollback # 回滚最近一次迁移
php artisan migrate:rollback --step=3 # 回滚最近3个迁移
php artisan migrate:reset # 回滚所有迁移
php artisan migrate:refresh # 回滚所有并重新执行
php artisan migrate:refresh --seed # 回滚、重新执行并运行种子
php artisan migrate:status
创建 users 表迁移:
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();
});
}
创建 posts 表迁移:
public function up()
{
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->boolean('is_published')->default(false);
$table->timestamp('published_at')->nullable();
$table->timestamps();
$table->softDeletes();
// 复合索引
$table->index(['user_id', 'created_at']);
});
}
创建 comments 表迁移:
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->text('content');
$table->timestamps();
});
}
down 方法中删除表或撤销修改,确保回滚可以完整还原。使用 foreignId 和 constrained 简化外键定义,注意表之间的顺序。
bigInteger 或 unsignedBigInteger)。
Schema::table 添加字段和外键。注意如果表中已有数据,需要确保外键字段的值在引用表中存在,否则会失败。
create_users_table、add_avatar_to_users_table、change_status_column_in_orders_table。这样能清晰表达迁移的作用。
迁移是 Laravel 管理数据库结构的利器,通过编写清晰、可回滚的迁移文件,可以轻松实现团队协作和版本控制。 掌握常用字段类型、索引、外键以及修改表的方法,将使你的数据库操作更加规范。 下一章我们将学习数据填充与工厂,为数据库添加测试数据。