Laravel 编码技巧 - 迁移文件

作者: 温新

图书: 【Laravel 编码技巧】

阅读: 173

时间: 2024-02-24 16:37:49

迁移顺序

如果你想改变数据库迁移的顺序,只需要将文件按时间戳记命名, 就像 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('此列用于索引。');

检查表/列是否存在

你可以使用 hasTablehasColumn 方法来检查数据库中是否存在某个表或列:

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();
});
请登录后再评论