数据库:迁移
简介
迁移就像你的数据库的版本控制,允许你的团队定义和共享应用程序的数据库模式定义。如果你曾经告诉过队友在从源代码控制中拉取更改后手动将列添加到他们的本地数据库模式,那么你已经遇到了数据库迁移解决的问题。
Laravel Schema
外观 为所有 Laravel 支持的数据库系统提供了与数据库无关的创建和操作表格的支持。通常情况下,迁移将使用此外观来创建和修改数据库表格和列。
生成迁移
你可以使用 make:migration
Artisan 命令 来生成数据库迁移。新的迁移将被放置在你的 database/migrations
目录中。每个迁移文件名都包含一个时间戳,允许 Laravel 确定迁移的顺序
php artisan make:migration create_flights_table
Laravel 将使用迁移的名称来尝试猜测表格的名称以及迁移是否将创建一个新表格。如果 Laravel 能够从迁移名称中确定表格名称,Laravel 将使用指定的表格预填充生成的迁移文件。否则,你只需在迁移文件中手动指定表格。
如果你想为生成的迁移指定一个自定义路径,你可以在执行 make:migration
命令时使用 --path
选项。给定的路径应相对于你的应用程序的基路径。
迁移存根可以使用 存根发布 进行自定义。
压缩迁移
随着你的应用程序的构建,你可能会随着时间的推移积累越来越多的迁移。这会导致你的 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 将将一个“模式”文件写入你的应用程序的 database/schema
目录。模式文件的名称将对应于数据库连接。现在,当你尝试迁移数据库并且没有执行其他迁移时,Laravel 将首先执行你使用的数据库连接的模式文件中的 SQL 语句。在执行模式文件的 SQL 语句后,Laravel 将执行任何剩余的不在模式转储中的迁移。
如果你的应用程序的测试使用与你在本地开发期间通常使用的数据库连接不同的数据库连接,你应该确保你已经使用该数据库连接转储了一个模式文件,以便你的测试能够构建你的数据库。你可能希望在转储你通常在本地开发期间使用的数据库连接后执行此操作
php artisan schema:dumpphp artisan schema:dump --database=testing --prune
你应该将你的数据库模式文件提交到源代码控制,以便你的团队中其他新开发人员能够快速创建你的应用程序的初始数据库结构。
迁移压缩仅适用于 MariaDB、MySQL、PostgreSQL 和 SQLite 数据库,并使用数据库的命令行客户端。
迁移结构
一个迁移类包含两个方法:up
和 down
。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
Artisan 命令
php artisan migrate
如果你想查看到目前为止哪些迁移已经运行,你可以使用 migrate:status
Artisan 命令
php artisan migrate:status
如果你想查看迁移将执行的 SQL 语句,而不实际运行它们,你可以在 migrate
命令中提供 --pretend
标志
php artisan migrate --pretend
隔离迁移执行
如果你将你的应用程序部署到多个服务器,并将迁移作为你的部署过程的一部分运行,你可能不希望两台服务器同时尝试迁移数据库。为避免这种情况,你可以在调用 migrate
命令时使用 isolated
选项。
当提供 isolated
选项时,Laravel 将使用你的应用程序的缓存驱动获取原子锁,然后尝试运行你的迁移。在该锁被持有期间,所有其他尝试运行 migrate
命令将不会执行;但是,该命令仍然会以成功的退出状态代码退出
php artisan migrate --isolated
要利用此功能,你的应用程序必须使用 memcached
、redis
、dynamodb
、database
、file
或 array
缓存驱动作为你的应用程序的默认缓存驱动。此外,所有服务器必须与同一个中央缓存服务器进行通信。
强制迁移在生产环境中运行
一些迁移操作具有破坏性,这意味着它们可能会导致你丢失数据。为了保护你免受在生产数据库上运行这些命令的影响,在执行命令之前,系统会提示你确认。要强制命令在没有提示的情况下运行,请使用 --force
标志
php artisan migrate --force
回滚迁移
要回滚最新的迁移操作,你可以使用 rollback
Artisan 命令。此命令会回滚最新的“批次”迁移,其中可能包含多个迁移文件
php artisan migrate:rollback
你可以通过向 rollback
命令提供 step
选项来回滚有限数量的迁移。例如,以下命令将回滚最近的五个迁移
php artisan migrate:rollback --step=5
你可以通过向 rollback
命令提供 batch
选项来回滚特定的“批次”迁移,其中 batch
选项对应于你的应用程序的 migrations
数据库表中的批次值。例如,以下命令将回滚批次三中的所有迁移
php artisan migrate:rollback --batch=3
如果你想查看迁移将执行的 SQL 语句,而不实际运行它们,你可以在 migrate:rollback
命令中提供 --pretend
标志
php artisan migrate:rollback --pretend
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
你可以通过向 refresh
命令提供 step
选项来回滚和重新迁移有限数量的迁移。例如,以下命令将回滚和重新迁移最近的五个迁移
php artisan migrate:refresh --step=5
删除所有表格并迁移
migrate:fresh
命令将删除数据库中的所有表格,然后执行 migrate
命令
php artisan migrate:fresh php artisan migrate:fresh --seed
默认情况下,migrate:fresh
命令只删除默认数据库连接的表。但是,您可以使用 --database
选项指定要迁移的数据库连接。数据库连接名称应与您应用程序的 database
配置文件 中定义的连接相对应。
php artisan migrate:fresh --database=admin
migrate:fresh
命令将删除所有数据库表,无论它们是否有前缀。在与其他应用程序共享的数据库上开发时,应谨慎使用此命令。
表格
创建表格
要创建一个新的数据库表,请使用 Schema
门面的 create
方法。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();});
创建表时,可以使用任何架构构建器的 列方法 来定义表的列。
确定表/列是否存在
您可以使用 hasTable
、hasColumn
和 hasIndex
方法来确定表、列或索引是否存在。
if (Schema::hasTable('users')) { // The "users" table exists...} if (Schema::hasColumn('users', 'email')) { // The "users" table exists and has an "email" column...} if (Schema::hasIndex('users', ['email'], 'unique')) { // The "users" table exists and has a unique index on the "email" column...}
数据库连接和表选项
如果您想对不是应用程序默认连接的数据库连接执行架构操作,请使用 connection
方法。
Schema::connection('sqlite')->create('users', function (Blueprint $table) { $table->id();});
此外,还可以使用一些其他属性和方法来定义表的创建的其他方面。engine
属性可用于在使用 MariaDB 或 MySQL 时指定表的存储引擎。
Schema::create('users', function (Blueprint $table) { $table->engine('InnoDB'); // ...});
charset
和 collation
属性可用于在使用 MariaDB 或 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
方法。表注释目前只受 MariaDB、MySQL 和 PostgreSQL 支持。
Schema::create('calculations', function (Blueprint $table) { $table->comment('Business calculations'); // ...});
更新表格
Schema
门面的 table
方法可用于更新现有表。与 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 分配基于约定的名称。否则,外键约束名称将引用旧的表名。
列
创建列
Schema
门面的 table
方法可用于更新现有表。与 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 bigInteger binary boolean char dateTimeTz dateTime date decimal double enum float foreignId foreignIdFor foreignUlid foreignUuid geography geometry id increments integer ipAddress json jsonb longText macAddress mediumIncrements mediumInteger mediumText morphs nullableMorphs nullableTimestamps nullableUlidMorphs nullableUuidMorphs rememberToken set smallIncrements smallInteger softDeletesTz softDeletes string text timeTz time timestampTz timestamp timestampsTz timestamps tinyIncrements tinyInteger tinyText unsignedBigInteger unsignedInteger unsignedMediumInteger unsignedSmallInteger unsignedTinyInteger ulidMorphs uuidMorphs ulid uuid year
bigIncrements()
bigIncrements
方法创建一个自增的 UNSIGNED BIGINT
(主键)等效列。
$table->bigIncrements('id');
bigInteger()
bigInteger
方法创建一个 BIGINT
等效列。
$table->bigInteger('votes');
binary()
binary
方法创建一个 BLOB
等效列。
$table->binary('photo');
在使用 MySQL、MariaDB 或 SQL Server 时,您可以传递 length
和 fixed
参数来创建 VARBINARY
或 BINARY
等效列。
$table->binary('data', length: 16); // VARBINARY(16) $table->binary('data', length: 16, fixed: true); // BINARY(16)
boolean()
boolean
方法创建一个 BOOLEAN
等效列。
$table->boolean('confirmed');
char()
char
方法创建一个具有给定长度的 CHAR
等效列。
$table->char('name', length: 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', total: 8, places: 2);
double()
double
方法创建一个 DOUBLE
等效列。
$table->double('amount');
enum()
enum
方法创建一个 ENUM
等效列,它具有给定的有效值。
$table->enum('difficulty', ['easy', 'hard']);
float()
float
方法创建一个 FLOAT
等效列,它具有给定的精度。
$table->float('amount', precision: 53);
foreignId()
foreignId
方法创建一个 UNSIGNED BIGINT
等效列。
$table->foreignId('user_id');
foreignIdFor()
foreignIdFor
方法为给定的模型类添加一个 {column}_id
等效列。列类型将是 UNSIGNED BIGINT
、CHAR(36)
或 CHAR(26)
,具体取决于模型键类型。
$table->foreignIdFor(User::class);
foreignUlid()
foreignUlid
方法创建一个 ULID
等效列。
$table->foreignUlid('user_id');
foreignUuid()
foreignUuid
方法创建一个 UUID
等效列。
$table->foreignUuid('user_id');
geography()
geography
方法创建一个 GEOGRAPHY
等效列,它具有给定的空间类型和 SRID(空间参考系统标识符)。
$table->geography('coordinates', subtype: 'point', srid: 4326);
对空间类型的支持取决于您的数据库驱动程序。请参阅您的数据库文档。如果您的应用程序使用的是 PostgreSQL 数据库,则必须安装 PostGIS 扩展才能使用 geography
方法。
geometry()
geometry
方法创建一个 GEOMETRY
等效列,它具有给定的空间类型和 SRID(空间参考系统标识符)。
$table->geometry('positions', subtype: 'point', srid: 0);
对空间类型的支持取决于您的数据库驱动程序。请参阅您的数据库文档。如果您的应用程序使用的是 PostgreSQL 数据库,则必须安装 PostGIS 扩展才能使用 geometry
方法。
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');
在使用 PostgreSQL 时,将创建一个 INET
列。
json()
json
方法创建一个 JSON
等效列。
$table->json('options');
jsonb()
jsonb
方法创建一个 JSONB
等效列。
$table->jsonb('options');
longText()
longText
方法创建一个 LONGTEXT
等效列。
$table->longText('description');
在使用 MySQL 或 MariaDB 时,您可以将 binary
字符集应用于该列,以创建一个 LONGBLOB
等效列。
$table->longText('data')->charset('binary'); // LONGBLOB
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');
在使用 MySQL 或 MariaDB 时,您可以将 binary
字符集应用于该列,以创建一个 MEDIUMBLOB
等效列。
$table->mediumText('data')->charset('binary'); // MEDIUMBLOB
morphs()
morphs
方法是一个便利方法,它添加一个 {column}_id
等效列和一个 {column}_type
VARCHAR
等效列。{column}_id
的列类型将是 UNSIGNED BIGINT
、CHAR(36)
或 CHAR(26)
,具体取决于模型键类型。
此方法旨在用于定义多态 Eloquent 关系 所需的列。在以下示例中,将创建 taggable_id
和 taggable_type
列。
$table->morphs('taggable');
nullableTimestamps()
nullableTimestamps
方法是 timestamps 方法的别名。
$table->nullableTimestamps(precision: 0);
nullableMorphs()
此方法类似于 morphs 方法;但是,创建的列将是“可空”的。
$table->nullableMorphs('taggable');
nullableUlidMorphs()
此方法类似于 ulidMorphs 方法;但是,创建的列将是“可空”的。
$table->nullableUlidMorphs('taggable');
nullableUuidMorphs()
此方法类似于 uuidMorphs 方法;但是,创建的列将是“可空”的。
$table->nullableUuidMorphs('taggable');
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
(带时区)等效列,它带有可选的小数秒精度。此列用于存储 Eloquent 的“软删除”功能所需的 deleted_at
时间戳。
$table->softDeletesTz('deleted_at', precision: 0);
softDeletes()
softDeletes
方法添加一个可空的 deleted_at
TIMESTAMP
等效列,它带有可选的小数秒精度。此列用于存储 Eloquent 的“软删除”功能所需的 deleted_at
时间戳。
$table->softDeletes('deleted_at', precision: 0);
string()
string
方法创建一个指定长度的 VARCHAR
等效列
$table->string('name', length: 100);
text()
text
方法创建一个 TEXT
等效列
$table->text('description');
使用 MySQL 或 MariaDB 时,可以将 binary
字符集应用于该列,以创建 BLOB
等效列
$table->text('data')->charset('binary'); // BLOB
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_at
和 updated_at
TIMESTAMP
(带时区)等效列,并带有可选的小数秒精度
$table->timestampsTz(precision: 0);
timestamps()
timestamps
方法创建 created_at
和 updated_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');
使用 MySQL 或 MariaDB 时,可以将 binary
字符集应用于该列,以创建 TINYBLOB
等效列
$table->tinyText('data')->charset('binary'); // TINYBLOB
unsignedBigInteger()
unsignedBigInteger
方法创建一个 UNSIGNED BIGINT
等效列
$table->unsignedBigInteger('votes');
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
等效列。
此方法旨在用于定义多态 Eloquent 关系 所需的列,这些关系使用 ULID 标识符。在下面的示例中,将创建 taggable_id
和 taggable_type
列
$table->ulidMorphs('taggable');
uuidMorphs()
uuidMorphs
方法是一个方便的方法,它添加了一个 {column}_id
CHAR(36)
等效列和一个 {column}_type
VARCHAR
等效列。
此方法旨在用于定义多态 Eloquent 关系 所需的列,这些关系使用 UUID 标识符。在下面的示例中,将创建 taggable_id
和 taggable_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();});
下表包含所有可用的列修饰符。此列表不包括 索引修饰符
修饰符 | 描述 |
---|---|
->after('column') |
将列放在另一列“之后”(MariaDB / MySQL)。 |
->autoIncrement() |
将 INTEGER 列设置为自增(主键)。 |
->charset('utf8mb4') |
为列指定字符集(MariaDB / MySQL)。 |
->collation('utf8mb4_unicode_ci') |
为列指定排序规则。 |
->comment('my comment') |
向列添加注释(MariaDB / MySQL / PostgreSQL)。 |
->default($value) |
为列指定“默认”值。 |
->first() |
将列放在表中的“第一位”(MariaDB / MySQL)。 |
->from($integer) |
设置自增字段的起始值(MariaDB / MySQL / PostgreSQL)。 |
->invisible() |
使列对 SELECT * 查询“不可见”(MariaDB / MySQL)。 |
->nullable($value = true) |
允许将 NULL 值插入到该列中。 |
->storedAs($expression) |
创建存储的生成列(MariaDB / MySQL / PostgreSQL / SQLite)。 |
->unsigned() |
将 INTEGER 列设置为 UNSIGNED (MariaDB / MySQL)。 |
->useCurrent() |
将 TIMESTAMP 列设置为使用 CURRENT_TIMESTAMP 作为默认值。 |
->useCurrentOnUpdate() |
将 TIMESTAMP 列设置为在记录更新时使用 CURRENT_TIMESTAMP (MariaDB / MySQL)。 |
->virtualAs($expression) |
创建虚拟的生成列(MariaDB / MySQL / SQLite)。 |
->generatedAs($expression) |
使用指定的序列选项创建标识列(PostgreSQL)。 |
->always() |
定义标识列的序列值优先于输入(PostgreSQL)。 |
默认表达式
default
修饰符接受一个值或一个 Illuminate\Database\Query\Expression
实例。使用 Expression
实例将阻止 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(); }); }};
对默认表达式的支持取决于您的数据库驱动程序、数据库版本和字段类型。请参阅您的数据库文档。
列顺序
使用 MariaDB 或 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();});
change
方法不会更改列的索引。因此,您可以使用索引修饰符在修改列时显式添加或删除索引
// Add an index...$table->bigIncrements('id')->primary()->change(); // Drop an index...$table->char('postal_code', 10)->unique(false)->change();
重命名列
要重命名列,可以使用架构构建器提供的 renameColumn
方法
Schema::table('users', function (Blueprint $table) { $table->renameColumn('from', 'to');});
删除列
要删除列,可以使用架构构建器上的 dropColumn
方法
Schema::table('users', function (Blueprint $table) { $table->dropColumn('votes');});
可以通过将列名数组传递给 dropColumn
方法,从表中删除多个列
Schema::table('users', function (Blueprint $table) { $table->dropColumn(['votes', 'avatar', 'location']);});
可用命令别名
Laravel 提供了几种与删除常见列类型相关的便捷方法。下表描述了每种方法
命令 | 描述 |
---|---|
$table->dropMorphs('morphable'); |
删除 morphable_id 和 morphable_type 列。 |
$table->dropRememberToken(); |
删除 remember_token 列。 |
$table->dropSoftDeletes(); |
删除 deleted_at 列。 |
$table->dropSoftDeletesTz(); |
dropSoftDeletes() 方法的别名。 |
$table->dropTimestamps(); |
删除 created_at 和 updated_at 列。 |
$table->dropTimestampsTz(); |
dropTimestamps() 方法的别名。 |
索引
创建索引
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 支持的每种类型索引的方法。每个索引方法都接受一个可选的第二个参数来指定索引的名称。如果省略,名称将从用于索引的表和列的名称以及索引类型派生。下表描述了每种可用的索引方法
命令 | 描述 |
---|---|
$table->primary('id'); |
添加主键。 |
$table->primary(['id', 'parent_id']); |
添加组合键。 |
$table->unique('email'); |
添加唯一索引。 |
$table->index('state'); |
添加索引。 |
$table->fullText('body'); |
添加全文索引(MariaDB / MySQL / PostgreSQL)。 |
$table->fullText('body')->language('english'); |
添加指定语言的全文索引(PostgreSQL)。 |
$table->spatialIndex('location'); |
添加空间索引(除 SQLite 外)。 |
重命名索引
要重命名索引,可以使用架构构建器蓝图提供的 renameIndex
方法。此方法接受当前索引名称作为其第一个参数,并接受所需的名称作为其第二个参数
$table->renameIndex('from', 'to')
删除索引
要删除索引,您必须指定索引的名称。默认情况下,Laravel 会根据表名、索引列的名称和索引类型自动分配索引名称。以下是一些示例
命令 | 描述 |
---|---|
$table->dropPrimary('users_id_primary'); |
从“users”表中删除主键。 |
$table->dropUnique('users_email_unique'); |
从“users”表中删除唯一索引。 |
$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 还支持创建外键约束,这些约束用于在数据库级别强制执行引用完整性。例如,让我们在 posts
表上定义一个 user_id
列,它引用 users
表上的 id
列
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( table: 'users', indexName: 'posts_user_id' );});
您还可以指定约束的“on delete”和“on update”属性的所需操作
$table->foreignId('user_id') ->constrained() ->onUpdate('cascade') ->onDelete('cascade');
还提供了这些操作的另一种表达性语法
方法 | 描述 |
---|---|
$table->cascadeOnUpdate(); |
更新应级联。 |
$table->restrictOnUpdate(); |
更新应受限。 |
$table->nullOnUpdate(); |
更新应将外键值设置为 null。 |
$table->noActionOnUpdate(); |
更新时不执行任何操作。 |
$table->cascadeOnDelete(); |
删除应级联。 |
$table->restrictOnDelete(); |
删除操作应该受到限制。 |
$table->nullOnDelete(); |
删除操作应将外键值设置为 null。 |
$table->noActionOnDelete(); |
如果存在子记录,则阻止删除。 |
任何其他 列修饰符 必须在 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...});
SQLite 默认情况下禁用外键约束。 使用 SQLite 时,请确保在迁移中尝试创建外键之前,在您的数据库配置中启用外键支持。
事件
为了方便起见,每个迁移操作都会分派一个 事件。 以下所有事件都扩展了基本 Illuminate\Database\Events\MigrationEvent
类
类 | 描述 |
---|---|
Illuminate\Database\Events\MigrationsStarted |
即将执行一批迁移。 |
Illuminate\Database\Events\MigrationsEnded |
一批迁移已完成执行。 |
Illuminate\Database\Events\MigrationStarted |
即将执行单个迁移。 |
Illuminate\Database\Events\MigrationEnded |
单个迁移已完成执行。 |
Illuminate\Database\Events\NoPendingMigrations |
迁移命令未找到任何待处理的迁移。 |
Illuminate\Database\Events\SchemaDumped |
数据库模式转储已完成。 |
Illuminate\Database\Events\SchemaLoaded |
已加载现有的数据库模式转储。 |