Laravel 编码技巧 - 迁移文件
迁移顺序
如果你想改变数据库迁移的顺序,只需要将文件按时间戳记命名, 就像 2018_08_04_070443_create_posts_table.php
改为 2018_07_04_070443_create_posts_table.php
(从 2018_08_04
改成了 2018_07_04
)。
迁移是以字母顺序执行。
带时区的迁移字段
你知道吗?在迁移中不止有 timestamps()
还有带时区的 timestampsTz()
。
Schema::create('employees', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email');
$table->timestampsTz();
});
同样,还有这么些列 dateTimeTz()
, timeTz()
, timestampTz()
, softDeletesTz()
。
数据库迁移字段类型
迁移中有一些有趣的字段类型,下面是一些示例。
$table->geometry('positions');
$table->ipAddress('visitor');
$table->macAddress('device');
$table->point('position');
$table->uuid('id');
在 官方文档 中你可以找到全部的字段类型列表.
默认时间戳
当创建迁移文件时,你可以使用带 useCurrent()
和 useCurrentOnUpdate()
可选项的 timestamp()
类型,这将会设置使相应字段以 CURRENT_TIMESTAMP
作为默认值。
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrentOnUpdate();
迁移状态
如果你想检查哪些迁移已经执行或者还没有执行,不需要查看数据库的 migrations
表,你可以启动 php artisan migrate:status
命令。
结果示例:
Migration name .......................................................................... Batch / Status
2014_10_12_000000_create_users_table ........................................................... [1] Ran
2014_10_12_100000_create_password_resets_table ................................................. [1] Ran
2019_08_19_000000_create_failed_jobs_table ..................................................... [1] Ran
创建带空格的迁移
当输入 make:migration
命令时,你不必像 create_transactions_table
这样在部分之间使用下划线符号。你可以将名称放在引号中,然后使用空格而不是下划线。
// 这种方式可以工作
php artisan make:migration create_transactions_table
// 但是这种方式也可以工作
php artisan make:migration "create transactions table"
在另一列之后创建列
如果你正在向现有的表中添加新列,它不一定必须在列表中的最后。你可以指定在其之后创建:
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->after('email');
});
如果你正在向现有的表中添加新列,它不一定必须在列表中的最后。你可以指定在其之前创建:
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->before('created_at');
});
如果你想让你的列成为你的表中的第一个,那么使用第一个方法。
Schema::table('users', function (Blueprint $table) {
$table->string('uuid')->first();
});
此外,现在可以使用after()方法来添加多个字段。
Schema::table('users', function (Blueprint $table) {
$table->after('remember_token', function ($table){
$table->string('card_brand')->nullable();
$table->string('card_last_four', 4)->nullable();
});
});
为已存在的表生成迁移文件
如果你为现有的表创建迁移,并希望 Laravel 为你生成 Schema::table()
,那么在如果你为现有的表创建迁移,并希望 Laravel 为你生成Schema::table(),那么在末尾添加"_in_xxxxx_table"或"_to_xxxxx_table",或者指定"--table"参数。例如,运行php artisan change_fields_products_table
会生成一个空的类:
如果你对已有的表进行了迁移,并且你希望 Laravel 为你生成 Schema::table()
,那么在末尾添加 _in_xxxxx_table
或 _to_xxxxx_table
,或者指定 --table
参数。php artisan change_fields_products_table
生成空类
class ChangeFieldsProductsTable extends Migration
{
public function up()
{
//
}
}
但是,如果添加in_xxxxx_table
,运行php artisan make:migration change_fields_in_products_table
会生成一个带有预填充的Schema::table()的类:
class ChangeFieldsProductsTable extends Migration
{
public function up()
{
Schema::table('products', function (Blueprint $table) {
//
})
};
}
此外,你还可以使用--table
参数指定表名,运行php artisan make:migration whatever_you_want --table=products
:
class WhateverYouWant extends Migration
{
public function up()
{
Schema::table('products', function (Blueprint $table) {
//
})
};
}
在运行迁移之前输出SQL
当输入 migrate --pretend
命令,你可以得到将在终端中执行的 SQL 查询。如果有需要的话调试 SQL 的方法,这是个很有趣的方法。
// Artisan command
php artisan migrate --pretend
匿名迁移
Laravel
团队发布了Laravel 8.37
版本 支持匿名迁移,它解决了GitHub上的迁移类名冲突问题。问题的核心是,如果多个迁移具有相同的类名,则在尝试从头开始重新创建数据库时会导致问题。下面是一个pull request 测试的例子:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(
{
Schema::table('people', function (Blueprint $table) {
$table->string('first_name')->nullable();
});
}
public function down()
{
Schema::table('people', function (Blueprint $table) {
$table->dropColumn('first_name');
});
}
};
你可以在迁移中添加有关列的“注释”
你可以在迁移文件中为某一列添加 "comment",并提供有用的信息。
如果数据库由其他人管理而非开发人员,他们可以在执行任何操作之前查看表结构中的注释。
$table->unsignedInteger('interval')
->index()
->comment('此列用于索引。');
检查表/列是否存在
你可以使用 hasTable
和 hasColumn
方法来检查数据库中是否存在某个表或列:
if (Schema::hasTable('users')) {
// "users"表存在...
}
if (Schema::hasColumn('users', 'email')) {
// "users"表存在并且有一个"email"列...
}
对 After 方法中的列进行分组
对 After 方法中的列进行分组
Schema::table('users', function (Blueprint $table) {
$table->after('password', function ($table) {
$table->string('address_line1');
$table->string('address_line2');
$table->string('city');
});
});
仅当列不存在时才将其添加到数据库表中,如果存在,则可以删除它
现在您可以在数据库表中添加列,只有当它不存在时才能添加,如果它存在,则可以删除它。为此,引入了以下方法:
👉 whenTableDoesntHaveColumn
👉 whenTableHasColumn
从 Laravel 9.6.0 可用
return new class extends Migration {
public function up()
{
Schema::whenTableDoesntHaveColumn('users', 'name', function (Blueprint $table) {
$table->string('name', 30);
});
}
public function down()
{
Schema::whenTableHasColumn('users', 'name', function (Blueprint $table) {
$table->dropColumn('name');
});
}
}
设置当前时间戳默认值的方法
您可以对自定义时间戳列使用 useCurrent()
方法,将当前时间戳存储为默认值。
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->timestamp('added_at')->useCurrent();
$table->timestamps();
});