数据库:迁移

Introduction

迁移就像数据库的版本控制,允许您的团队定义和共享应用程序的数据库架构定义。如果您曾经不得不告诉队友在从源代码控制中提取更改后手动将列添加到他们的本地数据库模式,那么您就遇到了数据库迁移解决的问题。

LaravelSchema facade 为跨所有 Laravel 支持的数据库系统创建和操作表提供数据库不可知的支持。通常,迁移将使用此外观来创建和修改数据库表和列。

生成迁移

您可以使用make:migration 工匠命令 生成数据库迁移。新迁移将放置在您的database/migrations 目录。每个迁移文件名都包含一个时间戳,允许 Laravel 确定迁移的顺序:

php artisan make:migration create_flights_table

Laravel 将使用迁移的名称来尝试猜测表的名称以及迁移是否会创建一个新表。如果 Laravel 能够从迁移名称中确定表名,Laravel 将使用指定的表预填充生成的迁移文件。否则,您可以简单地手动在迁移文件中指定表。

如果您想为生成的迁移指定自定义路径,您可以使用--path 执行时的选项make:migration 命令。给定的路径应该是相对于您的应用程序的基本路径。

Note
可以使用自定义迁移存根存根发布.

压缩迁移

在构建应用程序时,您可能会随着时间的推移积累越来越多的迁移。这可能会导致您database/migrations 目录变得臃肿,可能有数百次迁移。如果愿意,您可以将迁移“压缩”到单个 SQL 文件中。首先,执行schema:dump 命令:

php artisan schema:dump

# Dump the current database schema and prune all existing migrations...
php artisan schema:dump --prune

当你执行这个命令时,Laravel 会写一个“schema”文件到你的应用程序的database/schema 目录。模式文件的名称将对应于数据库连接。现在,当您尝试迁移数据库并且没有执行其他迁移时,Laravel 将首先执行您正在使用的数据库连接的模式文件的 SQL 语句。在执行模式文件的语句后,Laravel 将执行所有不属于模式转储的剩余迁移。

如果您的应用程序的测试使用的数据库连接与您在本地开发期间通常使用的数据库连接不同,您应该确保您已经使用该数据库连接转储了一个架构文件,以便您的测试能够构建您的数据库。您可能希望在转储本地开发期间通常使用的数据库连接后执行此操作:

php artisan schema:dump
php artisan schema:dump --database=testing --prune

您应该将数据库架构文件提交给源代码管理,以便您团队中的其他新开发人员可以快速创建应用程序的初始数据库结构。

Warning
迁移压缩仅适用于 MySQL、PostgreSQL 和 SQLite 数据库,并使用数据库的命令行客户端。模式转储可能无法恢复到内存中的 SQLite 数据库。

迁移结构

迁移类包含两个方法:updown.这up 方法用于向数据库添加新表、列或索引,而down 方法应该反转由执行的操作up 方法。

在这两种方法中,您都可以使用 Laravel 模式构建器来表达地创建和修改表。要了解所有可用的方法Schema建设者,查看它的文档.例如,以下迁移创建了一个flights 桌子:

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::drop('flights');
    }
};

设置迁移连接

如果您的迁移将与应用程序的默认数据库连接以外的数据库连接进行交互,您应该设置$connection 您的迁移属性:

/**
 * The database connection that should be used by the migration.
 *
 * @var string
 */
protected $connection = 'pgsql';

/**
 * Run the migrations.
 */
public function up(): void
{
    // ...
}

运行迁移

要运行所有未完成的迁移,请执行migrate 工匠命令:

php artisan migrate

如果您想查看到目前为止运行了哪些迁移,您可以使用migrate:status 工匠命令:

php artisan migrate:status

如果您想查看将由迁移执行的 SQL 语句而不实际运行它们,您可以提供--pretend 标志到migrate 命令:

php artisan migrate --pretend

隔离迁移执行

如果您跨多个服务器部署应用程序并在部署过程中运行迁移,您可能不希望两台服务器同时尝试迁移数据库。为避免这种情况,您可以使用isolated 调用时的选项migrate 命令。

当。。。的时候isolated 如果提供了选项,Laravel 将在尝试运行迁移之前使用应用程序的缓存驱动程序获取原子锁。所有其他尝试运行migrate 持有该锁的命令将不会执行;但是,该命令仍将以成功退出状态代码退出:

php artisan migrate --isolated

Warning 要使用此功能,您的应用程序必须使用memcached,redis,dynamodb,database,file, 或者array 缓存驱动程序作为应用程序的默认缓存驱动程序。此外,所有服务器都必须与同一个中央缓存服务器通信。

强制迁移在生产环境中运行

某些迁移操作具有破坏性,这意味着它们可能会导致您丢失数据。为了防止您对生产数据库运行这些命令,系统会在执行命令之前提示您进行确认。要强制命令在没有提示的情况下运行,请使用--force 旗帜:

php artisan migrate --force

回滚迁移

要回滚最新的迁移操作,您可以使用rollback 工匠命令。此命令回滚最后“批次”的迁移,其中可能包含多个迁移文件:

php artisan migrate:rollback

您可以通过提供以下命令来回滚有限数量的迁移step 的选项rollback 命令。例如,以下命令将回滚最后五次迁移:

php artisan migrate:rollback --step=5

您可以通过提供batch 的选项rollback 命令,其中batch 选项对应于您的应用程序中的批处理值migrations 数据库表。例如,以下命令将回滚第三批中的所有迁移:

php artisan migrate:rollback --batch=3

migrate:reset 命令将回滚所有应用程序的迁移:

php artisan migrate:reset

使用单个命令回滚和迁移

migrate:refresh 命令将回滚所有迁移,然后执行migrate 命令。此命令有效地重新创建整个数据库:

php artisan migrate:refresh

# Refresh the database and run all database seeds...
php artisan migrate:refresh --seed

您可以回滚并重新迁移有限数量的迁移,方法是提供step 的选项refresh 命令。例如,以下命令将回滚并重新迁移最后五次迁移:

php artisan migrate:refresh --step=5

删除所有表并迁移

migrate:fresh 命令将从数据库中删除所有表,然后执行migrate 命令:

php artisan migrate:fresh

php artisan migrate:fresh --seed

Warning
migrate:fresh 命令将删除所有数据库表,不管它们的前缀如何。在与其他应用程序共享的数据库上进行开发时,应谨慎使用此命令。

Tables

创建表

要创建新的数据库表,请使用create 上的方法Schema 正面。这create 方法接受两个参数:第一个是表的名称,第二个是一个闭包,它接收一个Blueprint 可用于定义新表的对象:

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

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email');
    $table->timestamps();
});

创建表时,您可以使用任何架构构建器的列方法 定义表的列。

检查表/列是否存在

您可以使用hasTablehasColumn 方法:

if (Schema::hasTable('users')) {
    // The "users" table exists...
}

if (Schema::hasColumn('users', 'email')) {
    // The "users" table exists and has an "email" column...
}

数据库连接和表选项

如果要对不是应用程序默认连接的数据库连接执行模式操作,请使用connection 方法:

Schema::connection('sqlite')->create('users', function (Blueprint $table) {
    $table->id();
});

此外,一些其他属性和方法可用于定义表创建的其他方面。这engine使用 MySQL 时,属性可用于指定表的存储引擎:

Schema::create('users', function (Blueprint $table) {
    $table->engine = 'InnoDB';

    // ...
});

charsetcollation properties 可用于指定使用 MySQL 时创建的表的字符集和排序规则:

Schema::create('users', function (Blueprint $table) {
    $table->charset = 'utf8mb4';
    $table->collation = 'utf8mb4_unicode_ci';

    // ...
});

temporary 方法可用于指示该表应该是“临时的”。临时表仅对当前连接的数据库会话可见,并在连接关闭时自动删除:

Schema::create('calculations', function (Blueprint $table) {
    $table->temporary();

    // ...
});

如果您想向数据库表添加“注释”,您可以调用comment 表实例上的方法。目前只有 MySQL 和 Postgres 支持表注释:

Schema::create('calculations', function (Blueprint $table) {
    $table->comment('Business calculations');

    // ...
});

更新表

table 上的方法Schema facade 可用于更新现有表。像create 方法,table 方法接受两个参数:表的名称和接收一个Blueprint 您可以用来向表中添加列或索引的实例:

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

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

重命名/删除表

要重命名现有的数据库表,请使用rename 方法:

use Illuminate\Support\Facades\Schema;

Schema::rename($from, $to);

要删除现有表,您可以使用drop 或者dropIfExists 方法:

Schema::drop('users');

Schema::dropIfExists('users');

使用外键重命名表

在重命名表之前,你应该验证表上的任何外键约束在你的迁移文件中都有一个明确的名称,而不是让 Laravel 分配一个基于约定的名称。否则,外键约束名将引用旧表名。

Columns

创建列

table 上的方法Schema facade 可用于更新现有表。像create 方法,table 方法接受两个参数:表的名称和接收Illuminate\Database\Schema\Blueprint 您可以用来向表中添加列的实例:

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

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes');
});

可用的列类型

架构构建器蓝图提供了多种方法,这些方法对应于您可以添加到数据库表中的不同类型的列。下表列出了每种可用的方法:

bigIncrements()

bigIncrements 方法创建一个自动递增UNSIGNED BIGINT (主键)等效列:

$table->bigIncrements('id');

bigInteger()

bigInteger 方法创建一个BIGINT 等效列:

$table->bigInteger('votes');

binary()

binary 方法创建一个BLOB 等效列:

$table->binary('photo');

boolean()

boolean 方法创建一个BOOLEAN 等效列:

$table->boolean('confirmed');

char()

char 方法创建一个CHAR 具有给定长度的等效列:

$table->char('name', 100);

dateTimeTz()

dateTimeTz 方法创建一个DATETIME (带时区)具有可选精度(总位数)的等效列:

$table->dateTimeTz('created_at', $precision = 0);

dateTime()

dateTime 方法创建一个DATETIME 具有可选精度(总位数)的等效列:

$table->dateTime('created_at', $precision = 0);

date()

date 方法创建一个DATE 等效列:

$table->date('created_at');

decimal()

decimal 方法创建一个DECIMAL 具有给定精度(总位数)和小数位数(小数位数)的等效列:

$table->decimal('amount', $precision = 8, $scale = 2);

double()

double 方法创建一个DOUBLE 具有给定精度(总位数)和小数位数(小数位数)的等效列:

$table->double('amount', 8, 2);

enum()

enum 方法创建一个ENUM 具有给定有效值的等效列:

$table->enum('difficulty', ['easy', 'hard']);

float()

float 方法创建一个FLOAT 具有给定精度(总位数)和小数位数(小数位数)的等效列:

$table->float('amount', 8, 2);

foreignId()

foreignId 方法创建一个UNSIGNED BIGINT 等效列:

$table->foreignId('user_id');

foreignIdFor()

foreignIdFor 方法添加一个{column}_id UNSIGNED BIGINT 给定模型类的等效列:

$table->foreignIdFor(User::class);

foreignUlid()

foreignUlid 方法创建一个ULID 等效列:

$table->foreignUlid('user_id');

foreignUuid()

foreignUuid 方法创建一个UUID 等效列:

$table->foreignUuid('user_id');

geometryCollection()

geometryCollection 方法创建一个GEOMETRYCOLLECTION 等效列:

$table->geometryCollection('positions');

geometry()

geometry 方法创建一个GEOMETRY 等效列:

$table->geometry('positions');

id()

id 方法是的别名bigIncrements 方法。默认情况下,该方法将创建一个id 柱子;但是,如果您想为列分配不同的名称,则可以传递列名:

$table->id();

increments()

increments 方法创建一个自动递增UNSIGNED INTEGER 作为主键的等效列:

$table->increments('id');

integer()

integer 方法创建一个INTEGER 等效列:

$table->integer('votes');

ipAddress()

ipAddress 方法创建一个VARCHAR 等效列:

$table->ipAddress('visitor');

json()

json 方法创建一个JSON 等效列:

$table->json('options');

jsonb()

jsonb 方法创建一个JSONB 等效列:

$table->jsonb('options');

lineString()

lineString 方法创建一个LINESTRING 等效列:

$table->lineString('positions');

longText()

longText 方法创建一个LONGTEXT 等效列:

$table->longText('description');

macAddress()

macAddress 方法创建一个用于保存 MAC 地址的列。某些数据库系统(例如 PostgreSQL)具有专门用于此类数据的列类型。其他数据库系统将使用字符串等效列:

$table->macAddress('device');

mediumIncrements()

mediumIncrements 方法创建一个自动递增UNSIGNED MEDIUMINT 作为主键的等效列:

$table->mediumIncrements('id');

mediumInteger()

mediumInteger 方法创建一个MEDIUMINT 等效列:

$table->mediumInteger('votes');

mediumText()

mediumText 方法创建一个MEDIUMTEXT 等效列:

$table->mediumText('description');

morphs()

morphs 方法是一种方便的方法,它添加了一个{column}_id UNSIGNED BIGINT 等效列和{column}_type VARCHAR 等效列。

此方法旨在用于定义多态所需的列雄辩的关系.在下面的例子中,taggable_idtaggable_type 将创建列:

$table->morphs('taggable');

multiLineString()

multiLineString 方法创建一个MULTILINESTRING 等效列:

$table->multiLineString('positions');

multiPoint()

multiPoint 方法创建一个MULTIPOINT 等效列:

$table->multiPoint('positions');

multiPolygon()

multiPolygon 方法创建一个MULTIPOLYGON 等效列:

$table->multiPolygon('positions');

nullableTimestamps()

nullableTimestamps 方法是的别名timestamps 方法:

$table->nullableTimestamps(0);

nullableMorphs()

该方法类似于morphs 方法;但是,创建的列将是“可空的”:

$table->nullableMorphs('taggable');

nullableUlidMorphs()

该方法类似于ulidMorphs 方法;但是,创建的列将是“可空的”:

$table->nullableUlidMorphs('taggable');

nullableUuidMorphs()

该方法类似于uuidMorphs 方法;但是,创建的列将是“可空的”:

$table->nullableUuidMorphs('taggable');

point()

point 方法创建一个POINT 等效列:

$table->point('position');

polygon()

polygon 方法创建一个POLYGON 等效列:

$table->polygon('position');

rememberToken()

rememberToken 方法创建一个可为空的,VARCHAR(100) 用于存储当前“记住我”的等效列身份验证令牌:

$table->rememberToken();

set()

set 方法创建一个SET 具有给定有效值列表的等效列:

$table->set('flavors', ['strawberry', 'vanilla']);

smallIncrements()

smallIncrements 方法创建一个自动递增UNSIGNED SMALLINT 作为主键的等效列:

$table->smallIncrements('id');

smallInteger()

smallInteger 方法创建一个SMALLINT 等效列:

$table->smallInteger('votes');

softDeletesTz()

softDeletesTz 方法添加一个可为空的deleted_at TIMESTAMP (带时区)具有可选精度(总位数)的等效列。此列用于存储deleted_at Eloquent 的“软删除”功能所需的时间戳:

$table->softDeletesTz($column = 'deleted_at', $precision = 0);

softDeletes()

softDeletes 方法添加一个可为空的deleted_at TIMESTAMP 具有可选精度(总位数)的等效列。此列用于存储deleted_at Eloquent 的“软删除”功能所需的时间戳:

$table->softDeletes($column = 'deleted_at', $precision = 0);

string()

string 方法创建一个VARCHAR 给定长度的等效列:

$table->string('name', 100);

text()

text 方法创建一个TEXT 等效列:

$table->text('description');

timeTz()

timeTz 方法创建一个TIME (带时区)具有可选精度(总位数)的等效列:

$table->timeTz('sunrise', $precision = 0);

time()

time 方法创建一个TIME 具有可选精度(总位数)的等效列:

$table->time('sunrise', $precision = 0);

timestampTz()

timestampTz 方法创建一个TIMESTAMP (带时区)具有可选精度(总位数)的等效列:

$table->timestampTz('added_at', $precision = 0);

timestamp()

timestamp 方法创建一个TIMESTAMP 具有可选精度(总位数)的等效列:

$table->timestamp('added_at', $precision = 0);

timestampsTz()

timestampsTz 方法创建created_atupdated_at TIMESTAMP (带时区)具有可选精度(总位数)的等效列:

$table->timestampsTz($precision = 0);

timestamps()

timestamps 方法创建created_atupdated_at TIMESTAMP 具有可选精度(总位数)的等效列:

$table->timestamps($precision = 0);

tinyIncrements()

tinyIncrements 方法创建一个自动递增UNSIGNED TINYINT 作为主键的等效列:

$table->tinyIncrements('id');

tinyInteger()

tinyInteger 方法创建一个TINYINT 等效列:

$table->tinyInteger('votes');

tinyText()

tinyText 方法创建一个TINYTEXT 等效列:

$table->tinyText('notes');

unsignedBigInteger()

unsignedBigInteger 方法创建一个UNSIGNED BIGINT 等效列:

$table->unsignedBigInteger('votes');

unsignedDecimal()

unsignedDecimal 方法创建一个UNSIGNED DECIMAL 具有可选精度(总位数)和小数位数(小数位数)的等效列:

$table->unsignedDecimal('amount', $precision = 8, $scale = 2);

unsignedInteger()

unsignedInteger 方法创建一个UNSIGNED INTEGER 等效列:

$table->unsignedInteger('votes');

unsignedMediumInteger()

unsignedMediumInteger 方法创建一个UNSIGNED MEDIUMINT 等效列:

$table->unsignedMediumInteger('votes');

unsignedSmallInteger()

unsignedSmallInteger 方法创建一个UNSIGNED SMALLINT 等效列:

$table->unsignedSmallInteger('votes');

unsignedTinyInteger()

unsignedTinyInteger 方法创建一个UNSIGNED TINYINT 等效列:

$table->unsignedTinyInteger('votes');

ulidMorphs()

ulidMorphs 方法是一种方便的方法,它添加了一个{column}_id CHAR(26) 等效列和{column}_type VARCHAR 等效列。

此方法旨在用于定义多态所需的列雄辩的关系 使用 ULID 标识符。在下面的例子中,taggable_idtaggable_type 将创建列:

$table->ulidMorphs('taggable');

uuidMorphs()

uuidMorphs 方法是一种方便的方法,它添加了一个{column}_id CHAR(36) 等效列和{column}_type VARCHAR 等效列。

此方法旨在用于定义多态所需的列雄辩的关系 使用 UUID 标识符。在下面的例子中,taggable_idtaggable_type 将创建列:

$table->uuidMorphs('taggable');

ulid()

ulid 方法创建一个ULID 等效列:

$table->ulid('id');

uuid()

uuid 方法创建一个UUID 等效列:

$table->uuid('id');

year()

year 方法创建一个YEAR 等效列:

$table->year('birth_year');

列修饰符

除了上面列出的列类型之外,还有几种列“修饰符”可以在向数据库表中添加列时使用。例如,要使列“可为空”,您可以使用nullable 方法:

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

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->nullable();
});

下表包含所有可用的列修饰符。此列表不包括索引修饰符:

Modifier Description
->after('column') 将该列放在另一列“之后”(MySQL)。
->autoIncrement() 将 INTEGER 列设置为自动递增(主键)。
->charset('utf8mb4') 为列指定字符集 (MySQL)。
->collation('utf8mb4_unicode_ci') 为列指定排序规则 (MySQL/PostgreSQL/SQL Server)。
->comment('my comment') 向列添加注释 (MySQL/PostgreSQL)。
->default($value) 为该列指定一个“默认”值。
->first() 将列“first”放在表 (MySQL) 中。
->from($integer) 设置自动递增字段的起始值 (MySQL / PostgreSQL)。
->invisible() 使列“不可见”SELECT * 查询(MySQL)。
->nullable($value = true) 允许将 NULL 值插入到列中。
->storedAs($expression) 创建存储的生成列 (MySQL / PostgreSQL)。
->unsigned() 将 INTEGER 列设置为 UNSIGNED (MySQL)。
->useCurrent() 将 TIMESTAMP 列设置为使用 CURRENT_TIMESTAMP 作为默认值。
->useCurrentOnUpdate() 将 TIMESTAMP 列设置为在更新记录时使用 CURRENT_TIMESTAMP。
->virtualAs($expression) 创建虚拟生成列 (MySQL)。
->generatedAs($expression) 创建具有指定序列选项的标识列 (PostgreSQL)。
->always() 为标识列 (PostgreSQL) 定义序列值相对于输入的优先级。
->isGeometry() 将空间列类型设置为geometry - 默认类型是geography (PostgreSQL)。

默认表达式

default 修饰符接受一个值或一个Illuminate\Database\Query\Expression 实例。使用一个Expression instance 将阻止 Laravel 将值包装在引号中,并允许您使用数据库特定的功能。这特别有用的一种情况是当您需要为 JSON 列分配默认值时:

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->json('movies')->default(new Expression('(JSON_ARRAY())'));
            $table->timestamps();
        });
    }
};

Warning
对默认表达式的支持取决于您的数据库驱动程序、数据库版本和字段类型。请参阅您的数据库的文档。

列顺序

使用MySQL数据库时,after 方法可用于在模式中的现有列之后添加列:

$table->after('password', function (Blueprint $table) {
    $table->string('address_line1');
    $table->string('address_line2');
    $table->string('city');
});

修改列

change 方法允许您修改现有列的类型和属性。例如,您可能希望增加一个string 柱子。看到change 方法在行动,让我们增加的大小name 列从 25 到 50。为此,我们只需定义列的新状态,然后调用change 方法:

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 50)->change();
});

修改列时,您必须在列定义中显式包含所有要保留的修饰符 - 任何缺失的属性都将被删除。例如,保留unsigned,default, 和comment 属性,您必须在更改列时显式调用每个修饰符:

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')->unsigned()->default(1)->comment('my comment')->change();
});

在 SQLite 上修改列

如果您的应用程序正在使用 SQLite 数据库,则必须安装doctrine/dbal 在修改列之前使用 Composer 包管理器进行打包。 Doctrine DBAL 库用于确定列的当前状态并创建对列进行请求更改所需的 SQL 查询:

composer require doctrine/dbal

如果您打算修改使用timestamp 方法,您还必须将以下配置添加到您的应用程序的config/database.php 配置文件:

use Illuminate\Database\DBAL\TimestampType;

'dbal' => [
    'types' => [
        'timestamp' => TimestampType::class,
    ],
],

Warning
当使用doctrine/dbal package,可以修改以下列类型:bigInteger,binary,boolean,char,date,dateTime,dateTimeTz,decimal,double,integer,json,longText,mediumText,smallInteger,string,text,time,tinyText,unsignedBigInteger,unsignedInteger,unsignedSmallInteger,ulid, 和uuid.

重命名列

要重命名列,您可以使用renameColumn 模式构建器提供的方法:

Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('from', 'to');
});

重命名遗留数据库中的列

如果您正在运行早于以下版本之一的数据库安装,您应该确保您已经安装了doctrine/dbal 在重命名列之前通过 Composer 包管理器获取库:

  • MySQL <8.0.3
  • 数据库 <10.5.2
  • SQLite <3.25.0

删除列

要删除列,您可以使用dropColumn 架构构建器上的方法:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('votes');
});

您可以通过将列名数组传递给dropColumn 方法:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn(['votes', 'avatar', 'location']);
});

删除遗留数据库中的列

如果您运行的是之前的 SQLite 版本3.35.0,您必须安装doctrine/dbal 之前通过 Composer 包管理器打包dropColumn 可以使用方法。不支持在使​​用此包时删除或修改单个迁移中的多个列。

可用的命令别名

Laravel 提供了几种与删除常见类型的列相关的便捷方法。下表描述了其中的每一种方法:

Command Description
$table->dropMorphs('morphable'); 放下morphable_idmorphable_type 列。
$table->dropRememberToken(); 放下remember_token 柱子。
$table->dropSoftDeletes(); 放下deleted_at 柱子。
$table->dropSoftDeletesTz(); 的别名dropSoftDeletes() 方法。
$table->dropTimestamps(); 放下created_atupdated_at 列。
$table->dropTimestampsTz(); 的别名dropTimestamps() 方法。

Indexes

创建索引

Laravel 模式构建器支持多种类型的索引。下面的例子创建了一个新的email列并指定其值应该是唯一的。要创建索引,我们可以链接unique 列定义上的方法:

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

Schema::table('users', function (Blueprint $table) {
    $table->string('email')->unique();
});

或者,您可以在定义列之后创建索引。为此,您应该调用unique 模式构建器蓝图上的方法。此方法接受应接收唯一索引的列的名称:

$table->unique('email');

您甚至可以将列数组传递给索引方法以创建复合(或复合)索引:

$table->index(['account_id', 'created_at']);

创建索引时,Laravel 会根据表名、列名和索引类型自动生成索引名,但你可以向该方法传递第二个参数来自己指定索引名:

$table->unique('email', 'unique_email');

可用索引类型

Laravel 的模式构建器蓝图类提供了创建 Laravel 支持的每种索引类型的方法。每个索引方法都接受一个可选的第二个参数来指定索引的名称。如果省略,名称将派生自用于索引的表和列的名称以及索引类型。下表描述了每种可用的索引方法:

Command Description
$table->primary('id'); 添加主键。
$table->primary(['id', 'parent_id']); 添加复合键。
$table->unique('email'); 添加唯一索引。
$table->index('state'); 添加索引。
$table->fullText('body'); 添加全文索引 (MySQL/PostgreSQL)。
$table->fullText('body')->language('english'); 添加指定语言 (PostgreSQL) 的全文索引。
$table->spatialIndex('location'); 添加空间索引(SQLite 除外)。

索引长度和 MySQL / MariaDB

默认情况下,Laravel 使用utf8mb4 字符集。如果您运行的 MySQL 版本早于 5.7.7 版本或 MariaDB 版本早于 10.2.2 版本,您可能需要手动配置迁移生成的默认字符串长度,以便 MySQL 为它们创建索引。您可以通过调用Schema::defaultStringLength 内的方法boot 你的方法App\Providers\AppServiceProvider 班级:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Schema::defaultStringLength(191);
}

或者,您可以启用innodb_large_prefix 数据库的选项。有关如何正确启用此选项的说明,请参阅数据库的文档。

重命名索引

要重命名索引,您可以使用renameIndex 模式构建器蓝图提供的方法。此方法接受当前索引名称作为其第一个参数,并接受所需名称作为其第二个参数:

$table->renameIndex('from', 'to')

Warning
如果您的应用程序正在使用 SQLite 数据库,则必须安装doctrine/dbal 之前通过 Composer 包管理器打包renameIndex 可以使用方法。

删除索引

要删除索引,您必须指定索引的名称。默认情况下,Laravel 会根据表名、索引列的名称和索引类型自动分配一个索引名称。这里有些例子:

Command Description
$table->dropPrimary('users_id_primary'); 从“用户”表中删除一个主键。
$table->dropUnique('users_email_unique'); 从“用户”表中删除一个唯一索引。
$table->dropIndex('geo_state_index'); 从“geo”表中删除一个基本索引。
$table->dropFullText('posts_body_fulltext'); 从“posts”表中删除全文索引。
$table->dropSpatialIndex('geo_location_spatialindex'); 从“geo”表中删除空间索引(SQLite 除外)。

如果将列数组传递给删除索引的方法,则将根据表名、列和索引类型生成常规索引名称:

Schema::table('geo', function (Blueprint $table) {
    $table->dropIndex(['state']); // Drops index 'geo_state_index'
});

外键约束

Laravel 还支持创建外键约束,用于在数据库级别强制引用完整性。例如,让我们定义一个user_id 专栏上的posts 引用的表id 专栏users 桌子:

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

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

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

由于这种语法相当冗长,Laravel 提供了额外的、更简洁的方法,这些方法使用约定来提供更好的开发人员体验。当使用foreignId 创建列的方法,上面的示例可以这样重写:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
});

foreignId 方法创建一个UNSIGNED BIGINT 等效列,而constrained 方法将使用约定来确定被引用的表名和列名。如果你的表名不符合 Laravel 的约定,你可以通过将表名作为参数传递给constrained 方法:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained('users');
});

您还可以为约束的“删除时”和“更新时”属性指定所需的操作:

$table->foreignId('user_id')
      ->constrained()
      ->onUpdate('cascade')
      ->onDelete('cascade');

还为这些操作提供了另一种表达语法:

Method Description
$table->cascadeOnUpdate(); 更新应该级联。
$table->restrictOnUpdate(); 应该限制​​更新。
$table->cascadeOnDelete(); 删除应该级联。
$table->restrictOnDelete(); 应该限制​​删除。
$table->nullOnDelete(); 删除应将外键值设置为空。

任何额外的列修饰符 必须在constrained 方法:

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

删除外键

要删除外键,您可以使用dropForeign 方法,将要删除的外键约束的名称作为参数传递。外键约束使用与索引相同的命名约定。换句话说,外键约束名称是基于表的名称和约束中的列,后跟一个“_foreign”后缀:

$table->dropForeign('posts_user_id_foreign');

或者,您可以传递一个数组,其中包含保存外键的列名dropForeign 方法。该数组将使用 Laravel 的约束命名约定转换为外键约束名称:

$table->dropForeign(['user_id']);

切换外键约束

您可以使用以下方法在迁移中启用或禁用外键约束:

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();

Schema::withoutForeignKeyConstraints(function () {
    // Constraints disabled within this closure...
});

Warning
SQLite 默认禁用外键约束。使用 SQLite 时,请确保启用外键支持 在您的数据库配置中尝试在迁移中创建它们之前。此外,SQLite 仅在创建表时支持外键,不是当表格被改变时.

Events

为了方便起见,每个迁移操作都会派发一个event.以下所有事件都扩展了基础Illuminate\Database\Events\MigrationEvent 班级:

Class Description
Illuminate\Database\Events\MigrationsStarted 即将执行一批迁移。
Illuminate\Database\Events\MigrationsEnded 一批迁移已执行完毕。
Illuminate\Database\Events\MigrationStarted 即将执行单个迁移。
Illuminate\Database\Events\MigrationEnded 单个迁移已完成执行。
Illuminate\Database\Events\SchemaDumped 数据库架构转储已完成。
Illuminate\Database\Events\SchemaLoaded 已加载现有数据库架构转储。
豫ICP备18041297号-2