数据库迁移

生成迁移

通过 生成一个迁移文件,命令后面跟的是一个文件名参数,通常为这个迁移要打算做的事情。

生成的迁移文件位于根目录下的 migrations 文件夹内,每个迁移文件都包含一个时间戳,以便迁移程序确定迁移的顺序。

--table 选项可以用来指定数据表的名称,指定的表名将会默认生成在迁移文件中。--create 选项也是用来指定数据表的名称,但跟 --table 的差异在于该选项是生成创建表的迁移文件,而 --table 是用于修改表的迁移文件。

  1. php bin/hyperf.php gen:migration create_users_table --table=users
  2. php bin/hyperf.php gen:migration create_users_table --create=users

迁移结构

迁移类默认会包含 2 个方法:updownup 方法用于添加新的数据表,字段或者索引到数据库,而 down 方法就是 up 方法的反操作,和 up 里的操作相反,以便在回退的时候执行。

  1. <?php
  2. use Hyperf\Database\Schema\Schema;
  3. use Hyperf\Database\Migrations\Migration;
  4. class CreateUsersTable extends Migration
  5. {
  6. /**
  7. * Run the migrations.
  8. */
  9. public function up(): void
  10. {
  11. Schema::create('true', function (Blueprint $table) {
  12. $table->bigIncrements('id');
  13. $table->timestamps();
  14. });
  15. }
  16. /**
  17. * Reverse the migrations.
  18. */
  19. public function down(): void
  20. {
  21. Schema::dropIfExists('true');
  22. }
  23. }

运行迁移

通过执行 migrate 命令运行所有尚未完成的迁移文件:

  1. php bin/hyperf.php migrate

一些迁移操作是具有破坏性的,这意味着可能会导致数据丢失,为了防止有人在生产环境中运行这些命令,系统会在这些命令运行之前与你进行确认,但如果您希望忽略这些确认信息强制运行命令,可以使用 --force 标记:

  1. php bin/hyperf.php migrate --force

回滚迁移

若您希望回滚最后一次的迁移,可以通过 migrate:rollback 命令回滚最后一侧的迁移,注意一次迁移可能会包含多个迁移文件:

  1. php bin/hyperf.php migrate:rollback

您还可以在 migrate:rollback 命令后面加上 step 参数来设置回滚迁移的次数,比如以下命令将回滚最近 5 次迁移:

  1. php bin/hyperf.php migrate:rollback --step=5

如果您希望回滚所有的迁移,可以通过 来回滚:

  1. php bin/hyperf.php migrate:reset

回滚并迁移

migrate:refresh 命令不仅会回滚迁移还会接着运行 migrate 命令,这样可以高效地重建某些迁移:

  1. php bin/hyperf.php migrate:refresh
  2. // 重建数据库结构并执行数据填充
  3. php bin/hyperf.php migrate:refresh --seed

通过 --step 参数指定回滚和重建次数,比如以下命令将回滚并重新执行最后 5 次迁移:

  1. php bin/hyperf.php migrate:refresh --step=5

重建数据库

通过 migrate:fresh 命令可以高效地重建整个数据库,这个命令会先删除所有的数据库,然后再执行 migrate 命令:

  1. php bin/hyperf.php migrate:fresh
  2. // 重建数据库结构并执行数据填充
  3. php bin/hyperf.php migrate:fresh --seed

数据表

通过 create 方法来创建新的数据库表。 create 方法接受两个参数:第一个参数为数据表的名称,第二个参数是一个 闭包(Closure),此闭包会接收一个用于定义新数据表的 Hyperf\Database\Schema\Blueprint 对象:

您可以在数据库结构生成器上使用以下命令来定义表的选项:

  1. $table->engine = 'InnoDB';
  2. // 指定数据表的默认字符集
  3. $table->charset = 'utf8';
  4. // 指定数据表默认的排序规则
  5. $table->collation = 'utf8_unicode_ci';
  6. // 创建临时表
  7. $table->temporary();

重命名数据表

若您希望重命名一个数据表,可以通过 rename 方法:

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

在重命名表之前,您应该验证表上的所有外键约束在迁移文件中都有明确的名称,而不是让迁移程序按照约定来设置一个名称,否则,外键的约束名称将引用旧表名。

删除数据表

删除一个已存在的数据表,可以通过 dropdropIfExists 方法:

  1. Schema::drop('users');
  2. Schema::dropIfExists('users');

检查数据表或字段是否存在

可以通过 hasTablehasColumn 方法来检查数据表或字段是否存在:

  1. if (Schema::hasTable('users')) {
  2. //
  3. }
  4. if (Schema::hasColumn('name', 'email')) {
  5. //
  6. }

如果在同时管理多个数据库的情况下,不同的迁移会对应不同的数据库连接,那么此时我们可以在迁移文件中通过重写父类的 $connection 类属性来定义不同的数据库连接:

  1. <?php
  2. use Hyperf\Database\Schema\Schema;
  3. use Hyperf\Database\Schema\Blueprint;
  4. use Hyperf\Database\Migrations\Migration;
  5. class CreateUsersTable extends Migration
  6. {
  7. // 这里对应 config/autoload/databases.php 内的连接 key
  8. protected $connection = 'foo';
  9. public function up(): void
  10. {
  11. Schema::create('users', function (Blueprint $table) {
  12. $table->bigIncrements('id');
  13. $table->timestamps();
  14. });
  15. }
  16. }

字段

创建字段

tablecreate 方法的第二个参数的 闭包(Closure) 内定义该迁移文件要执行的定义或变更,比如下面的代码为定义一个 name 的字符串字段:

<?php

use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{   
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->string('name');
        });
    }
}

可用的字段定义方法

修改字段

先决条件

在修改字段之前,请确保将 doctrine/dbal 依赖添加到 composer.json 文件中。Doctrine DBAL 库用于确定字段的当前状态, 并创建对该字段进行指定调整所需的 SQL 查询:

composer require doctrine/dbal

更新字段属性

change 方法可以将现有的字段类型修改为新的类型或修改其它属性。

<?php

Schema::create('users', function (Blueprint $table) {
    // 将字段的长度修改为 50
    $table->string('name', 50)->change();
});

或修改字段为 可为空

<?php

Schema::table('users', function (Blueprint $table) {
    // 将字段的长度修改为 50 并允许为空
    $table->string('name', 50)->nullable()->change();
});
<?php

Schema::table('users', function (Blueprint $table) {
    // 将字段从 from 重命名为 to
    $table->renameColumn('from', 'to')->change();
});

当前不支持 enum 类型的字段重命名。

删除字段

可以通过 dropColumn 方法来删除字段:

可用的命令别名

创建索引

通过 unique 方法来创建一个唯一索引:

<?php

// 在定义时创建索引
$table->string('name')->unique();
// 在定义完字段之后创建索引
$table->unique('name');

复合索引

<?php

// 创建一个复合索引
$table->index(['account_id', 'created_at'], 'index_account_id_and_created_at');

定义索引名称

迁移程序会自动生成一个合理的索引名称,每个索引方法都接受一个可选的第二个参数来指定索引的名称:

<?php

// 定义唯一索引名称为 unique_name
$table->unique('name', 'unique_name');
// 定义一个复合索引名称为 index_account_id_and_created_at
$table->index(['account_id', 'created_at'], '');
可用的索引类型

重命名索引

您可通过 renameIndex 方法重命名一个索引的名称:

<?php

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

删除索引

您可通过下面的方法来删除索引,默认情况下迁移程序会自动将数据库名称、索引的字段名及索引类型简单地连接在一起作为名称。举例如下:

您也可以通过传递字段数组到 dropIndex 方法,迁移程序会根据表名、字段和键类型生成的索引名称:

<?php

Schema:table('users', function (Blueprint $table) {
    $table->dropIndex(['account_id', 'created_at']);
});

我们还可以通过 foreignreferenceson 方法创建数据库层的外键约束。比如我们让 posts 表定义一个引用 users 表的 id 字段的 user_id 字段:

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

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

还可以为 on deleteon update 属性指定所需的操作:

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

您可以通过 dropForeign 方法来删除外键。外键约束采用的命名方式与索引相同,然后加上 _foreign 后缀:

$table->dropForeign('posts_user_id_foreign');

或者传递一个字段数组,让迁移程序按照约定的规则生成名称:


您可以在迁移文件中使用以下方法来开启或关闭外键约束:

// 开启外键约束
Schema::enableForeignKeyConstraints();
// 禁用外键约束
Schema::disableForeignKeyConstraints();