hyperf/docs/en/db/migration.md
2022-10-31 00:47:12 +07:00

20 KiB

Database migration

Database migration can be understood as version management of the database structure, which can effectively solve the management of the database structure across members of the team.

Generate migrations

Generate a migration file via gen:migration, the command is followed by a filename parameter, usually for what the migration is intended to do.

php bin/hyperf.php gen:migration create_users_table

The generated migration files are located in the migrations folder in the root directory, and each migration file includes a timestamp so that the migration program can determine the order of migrations.

The --table option can be used to specify the name of the data table. The specified table name will be generated in the migration file by default. The --create option is also used to specify the name of the data table, but the difference from --table is that this option generates a migration file for creating a table, while --table is a migration file for modifying the table.

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

Migration structure

The migration class will contain 2 methods by default: up and down. The up method is used to add a new data table, field or index to the database, and the down method is the inverse of the up method, which is the opposite of the operation in up, so that it is executed during rollback.

<?php

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

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('true', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

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

Run migration

Run all pending migration files by executing the migrate command:

php bin/hyperf.php migrate

Force the migration

Some migration operations are destructive, which means that data loss may result. To prevent someone from running these commands in a production environment, the system will confirm with you before these commands are run, but if you wish to ignore these confirmations, force To run a command, you can use the --force flag:

php bin/hyperf.php migrate --force

Rollback migration

If you want to roll back the last migration, you can use the migrate:rollback command to roll back the last migration. Note that a migration may contain multiple migration files:

php bin/hyperf.php migrate:rollback

You can also set the number of rollback migrations by appending the step parameter to the migrate:rollback command. For example, the following command will roll back the last 5 migrations:

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

If you wish to roll back all migrations, you can do so with migrate:reset:

php bin/hyperf.php migrate:reset

Rollback & Migrate

migrate:refresh The command not only rolls back the migration but also runs migrate command, which rebuilds some migrations efficiently:

php bin/hyperf.php migrate:refresh

// Rebuild database structure and perform data population
php bin/hyperf.php migrate:refresh --seed

Specify the number of rollbacks and rebuilds with the --step parameter. For example, the following command will rollback and re-execute the last 5 migrations:

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

Rebuild database

The entire database can be efficiently rebuilt with the migrate:fresh command, which deletes all databases before executing the migrate command:

php bin/hyperf.php migrate:fresh

// Rebuild database structure and perform data population
php bin/hyperf.php migrate:fresh --seed

Schema

In the migration file, the Hyperf\Database\Schema\Schema class is mainly used to define the data table and manage the migration process.

Create table

Create a new database table with the create method. The create method accepts two parameters: the first parameter is the name of the data table, and the second parameter is a Closure, which will receive a Hyperf\Database' to define the new data table \Schema\Blueprint object:

<?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->bigIncrements('id');
            $table->timestamps();
        });
    }
}

You can use the following commands on the database structure generator to define options for a table:

// Specify the table storage engine
$table->engine = 'InnoDB';
// Specifies the default character set for data tables
$table->charset = 'utf8';
// Specifies the default collation of the data table
$table->collation = 'utf8_unicode_ci';
// Create a temporary table
$table->temporary();

Rename table

If you wish to rename a data table, you can use the rename method:

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

Rename table with foreign key

Before renaming a table, you should verify that all foreign key constraints on the table have an explicit name in the migration file, rather than letting the migration program set a name by convention, otherwise, the foreign key's constraint name will refer to the old table name .

Drop table

To drop an existing table, use the drop or dropIfExists methods:

Schema::drop('users');

Schema::dropIfExists('users');

Check if the data table or field exists

The hasTable and hasColumn methods can be used to check whether a data table or field exists:

if (Schema::hasTable('users')) {
    //
}

if (Schema::hasColumn('name', 'email')) {
    //
}

Database connection options

If multiple databases are managed at the same time, different migrations will correspond to different database connections, then we can define different database connections in the migration file by overriding the $connection class attribute of the parent class:

<?php

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

class CreateUsersTable extends Migration
{
    // This corresponds to the connection key in config/autoload/databases.php
    protected $connection = 'foo';
    
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }
}

Fields

Create fields

Define the definition or change to be performed by the migration file within the Closure of the second parameter of the table or create method. For example, the following code defines a string field of 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');
        });
    }
}

Available field definition methods

Command Description
$table->bigIncrements('id'); Increment ID (primary key), equivalent to "UNSIGNED BIG INTEGER"
$table->bigInteger('votes'); equivalent to BIGINT
$table->binary('data'); equivalent to BLOB
$table->boolean('confirmed'); equivalent to BOOLEAN
$table->char('name', 100); equivalent to with length CHAR
$table->date('created_at'); equivalent to DATE
$table->dateTime('created_at'); equivalent to DATETIME
$table->dateTimeTz('created_at'); equivalent to with time zone DATETIME
$table->decimal('amount', 8, 2); equivalent to with precision and base DECIMAL
$table->double('amount', 8, 2); equivalent to with precision and base DOUBLE
$table->enum('level', ['easy', 'hard']); equivalent to ENUM
$table->float('amount', 8, 2); equivalent to with precision and base FLOAT
$table->geometry('positions'); equivalent to GEOMETRY
$table->geometryCollection('positions'); equivalent to GEOMETRYCOLLECTION
$table->increments('id'); Incrementing ID (primary key), equivalent to "UNSIGNED INTEGER"
$table->integer('votes'); equivalent to INTEGER
$table->ipAddress('visitor'); equivalent to IP address
$table->json('options'); equivalent to JSON
$table->jsonb('options'); equivalent to JSONB
$table->lineString('positions'); equivalent to LINESTRING
$table->longText('description'); equivalent to LONGTEXT
$table->macAddress('device'); equivalent to MAC address
$table->mediumIncrements('id'); Increment ID (primary key), equivalent to "UNSIGNED MEDIUM INTEGER"
$table->mediumInteger('votes'); equivalent to MEDIUMINT
$table->mediumText('description'); equivalent to MEDIUMTEXT
$table->morphs('taggable'); equivalent to adding incremental taggable_id and string taggable_type
$table->multiLineString('positions'); equivalent to MULTILINESTRING
$table->multiPoint('positions'); equivalent to MULTIPOINT
$table->multiPolygon('positions'); equivalent to MULTIPOLYGON
$table->nullableMorphs('taggable'); equivalent to nullable version morphs() field
$table->nullableTimestamps(); equivalent to nullable version timestamps() field
$table->point('position'); equivalent to POINT
$table->polygon('positions'); equivalent to POLYGON
$table->rememberToken(); equivalent to nullable version VARCHAR (100) of remember_token field
$table->smallIncrements('id'); Increment ID (primary key), equivalent to "UNSIGNED SMALL INTEGER"
$table->smallInteger('votes'); equivalent to SMALLINT
$table->softDeletes(); equivalent to add a nullable for soft delete deleted_at field
$table->softDeletesTz(); equivalent to add a nullable for soft delete deleted_at field with time zone
$table->string('name', 100); equivalent to with length VARCHAR
$table->text('description'); equivalent to TEXT
$table->time('sunrise'); equivalent to TIME
$table->timeTz('sunrise'); equivalent to with time zone of TIME
$table->timestamp('added_on'); equivalent to TIMESTAMP
$table->timestampTz('added_on'); equivalent to with time zone TIMESTAMP
$table->timestamps(); equivalent to nullable created_at and updated_at TIMESTAMP
$table->timestampsTz(); equivalent to nullable with timezone created_at and updated_at TIMESTAMP
$table->tinyIncrements('id'); equivalent to auto increment UNSIGNED TINYINT
$table->tinyInteger('votes'); equivalent to TINYINT
$table->unsignedBigInteger('votes'); equivalent to UNSIGNED BIGINT
$table->unsignedDecimal('amount', 8, 2); equivalent to with precision and base UNSIGNED DECIMAL
$table->unsignedInteger('votes'); equivalent to UNSIGNED INT
$table->unsignedMediumInteger('votes'); equivalent to UNSIGNED MEDIUMINT
$table->unsignedSmallInteger('votes'); equivalent to UNSIGNED SMALLINT
$table->unsignedTinyInteger('votes'); equivalent to UNSIGNED TINYINT
$table->uuid('id'); equivalent to UUID
$table->year('birth_year'); equivalent to YEAR

Modify fields

Prerequisites

Make sure to add the doctrine/dbal dependency to the composer.json file before modifying the fields. The Doctrine DBAL library is used to determine the current state of a field and create the SQL query required to make the specified adjustments to that field:

composer require doctrine/dbal

Update field properties

change Methods can modify existing field types to new types or modify other properties.

<?php

Schema::create('users', function (Blueprint $table) {
    // Modify the length of the field to 50
    $table->string('name', 50)->change();
});

Or modify the field to be nullable:

<?php

Schema::table('users', function (Blueprint $table) {
    // Modify the length of the field to 50 and allow null
    $table->string('name', 50)->nullable()->change();
});

Only the following field types can be "modified": bigInteger, binary, boolean, date, dateTime, dateTimeTz, decimal, integer, json, longText, mediumText, smallInteger, string, text, time, unsignedBigInteger, unsignedInteger and unsignedSmallInteger.

Rename field

Fields can be renamed via the renameColumn method:

<?php

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

Field renaming of type enum is not currently supported.

Delete field

Fields can be dropped via the dropColumn method:

<?php

Schema::table('users', function (Blueprint $table) {
    // Remove the name field
    $table->dropColumn('name');
    // Delete multiple fields
    $table->dropColumn(['name', 'age']);
});

Available command aliases

Command Description
$table->dropRememberToken(); Remove the remember_token field.
$table->dropSoftDeletes(); Delete the deleted_at field.
$table->dropSoftDeletesTz(); Alias for the dropSoftDeletes() method.
$table->dropTimestamps(); Delete the created_at and updated_at fields.
$table->dropTimestampsTz(); Alias for the dropTimestamps() method.

Index

Create index

Unique index

Use the unique method to create a unique index:

<?php

// Create index at definition time
$table->string('name')->unique();
// Create indexes after fields are defined
$table->unique('name');

Compound index

<?php

// Create a compound index
$table->index(['account_id', 'created_at'], 'index_account_id_and_created_at');

Define index name

The migrator automatically generates a reasonable index name, and each index method accepts an optional second argument to specify the name of the index:

<?php

// Define a unique index name as unique_name
$table->unique('name', 'unique_name');
// Define a composite index named index_account_id_and_created_at
$table->index(['account_id', 'created_at'], '');
Available index types
Command Description
$table->primary('id'); Add primary key
$table->primary(['id', 'parent_id']); Add composite key
$table->unique('email'); Add unique index
$table->index('state'); Add normal index
$table->spatialIndex('location'); Add spatial index

Rename index

You can rename an index with the renameIndex method:

<?php

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

delete index

You can drop an index in the following way. By default, the migration program will automatically concatenate the database name, the field name of the index, and the index type as the name. Examples are as follows:

Command Description
$table->dropPrimary('users_id_primary'); Drop the primary key from the users table
$table->dropUnique('users_email_unique'); Drop unique index from users table
$table->dropIndex('geo_state_index'); Drop base index from geo table
$table->dropSpatialIndex('geo_location_spatialindex'); Drop the spatial index from the geo table

You can also pass an array of fields to the dropIndex method and the migrator will generate an index name based on the table name, field and key type:

<?php

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

foreign key constraints

We can also create foreign key constraints at the database layer through the foreign, references, on methods. For example, let's let the posts table define a user_id field that references the id field of the users table:

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

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

You can also specify the desired action for the on delete and on update properties:

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

You can drop foreign keys with the dropForeign method. Foreign key constraints are named in the same way as indexes, followed by a _foreign suffix:

$table->dropForeign('posts_user_id_foreign');

Or pass an array of fields and have the migrator generate the names according to the agreed-upon rules:

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

You can turn foreign key constraints on or off using the following methods in the migration file:

// Enable foreign key constraints
Schema::enableForeignKeyConstraints();
// Disable foreign key constraints
Schema::disableForeignKeyConstraints();