Hướng dẫn migration database cakephp 4

  • August 27, 2022
  • 1160

Bạn đang tìm cách tạo database khi sử dụng cakephp 4?  Hãy tìm hiểu ngay migration database with cakephp 4. Mặc định cakephp framework đã cài packagist hỗ trợ migration database cakephp/migrations. Packagist này sử dụng thư viện phinx.

Creating Migrations

Các file migrations được tạo trong thư mục config/Migrations. Giờ mình sẽ tạo 3 bảng: admins, users, articles. Để tạo 3 bảng này mình tạo 3 file migration bằng CLI command.


// Create admins table 
bin/cake bake migration CreateAdmins

// Create users table 
bin/cake bake migration CreateUsers

// Create articles table 
bin/cake bake migration CreateArticles

Các file migration tương ứng sẽ được tạo trong thư mục config/Migrations theo định dạng YYYYMMDDHHMMSS_MigrationName.php


20220810093618_CreateAdmins.php

<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateAdmins extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        // Create column id: biginteger, not null, auto increment
        $table = $this->table('admins', [
            'id' => false,
            'primary_key' => ['id'],
        ]);
        $table->addColumn('id', 'biginteger', [
            'autoIncrement' => true,
            'default' => null,
            'limit' => 20,
            'null' => false,
        ]);
        // Create column username: string, max length(255), nullable, index
        $table->addColumn('username', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => true,
        ])->addIndex('username');
        // Create column email: string, max length(125), not null, index, unique
        $table->addColumn('email', 'string', [
            'default' => null,
            'limit' => 125,
            'null' => false,
        ])->addIndex('email', ['unique' => true]);
        $table->addColumn('password', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ]);
        // Create column last_login_datetime: datetime, nullable
        $table->addColumn('last_login_datetime', 'datetime', [
            'default' => null,
            'limit' => null,
            'null' => true,
        ]);
        // Create column status: tinyinteger, index
        $table->addColumn('status', 'tinyinteger', [
            'default' => 1,
            'limit' => 4,
            'null' => false,
        ])->addIndex('status');
        $table->addColumn('created', 'datetime', [
            'comment' => 'Created at',
            'default' => null,
            'limit' => null,
            'null' => false,
        ]);
        $table->addColumn('modified', 'datetime', [
            'comment' => 'Updated at',
            'default' => null,
            'limit' => null,
            'null' => true,
        ]);
        $table->create();
    }
}

20220810093908_CreateUsers.php

<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateUsers extends AbstractMigration
{
    /**
     * Create table users.
     *
     * @return void
     */
    public function up()
    {
        // Create column id: biginteger, not null, auto increment
        $table = $this->table('users', [
            'id' => false,
            'primary_key' => ['id'],
        ]);
        $table->addColumn('id', 'biginteger', [
            'autoIncrement' => true,
            'default' => null,
            'limit' => 20,
            'null' => false,
        ]);
        $table->addColumn('last_name', 'string', [
            'comment' => 'Last name',
            'default' => null,
            'limit' => 255,
            'null' => true,
        ]);
        $table->addColumn('first_name', 'string', [
            'comment' => 'First name',
            'default' => null,
            'limit' => 255,
            'null' => true,
        ]);
        $table->addColumn('email', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ])->addIndex('email', ['unique' => true]);
        $table->addColumn('password', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ]);
        $table->addColumn('last_login_datetime', 'datetime', [
            'default' => null,
            'limit' => null,
            'null' => true,
        ]);
        $table->addColumn('status', 'tinyinteger', [
            'default' => 1,
            'limit' => 4,
            'null' => false,
        ])->addIndex('status');
        $table->addColumn('created', 'datetime', [
            'comment' => 'Created',
            'default' => null,
            'limit' => null,
            'null' => false,
        ]);
        $table->addColumn('modified', 'datetime', [
            'comment' => 'Modified',
            'default' => null,
            'limit' => null,
            'null' => true,
        ]);
        $table->create();
    }

    /**
     * Drop table users.
     *
     * @return void
     */
    public function down()
    {
        $this->table('users')->drop()->save();
    }
}

20220810094102_CreateArticles.php

<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateArticles extends AbstractMigration
{
     /**
     * Create table articles.
     *
     * @return void
     */
    public function up()
    {
        // Create column id: biginteger, not null, auto increment
        $table = $this->table('articles', [
            'id' => false,
            'primary_key' => ['id'],
        ]);
        $table->addColumn('id', 'biginteger', [
            'autoIncrement' => true,
            'default' => null,
            'limit' => 20,
            'null' => false,
        ]);
        // Create column user_id: biginteger, foreignKey with user table
        $table->addColumn('user_id', 'biginteger');
        $table->addForeignKey('user_id', 'users', 'id', [
            'delete' => 'CASCADE',
            'update' => 'CASCADE'
        ]);
        $table->addColumn('title', 'string', [
            'comment' => 'Title',
            'default' => null,
            'limit' => 255,
            'null' => true,
        ]);
        // Create column description: text, nullable, max length 255
        $table->addColumn('description', 'text', [
            'comment' => 'Description',
            'default' => null,
            'limit' => 255,
            'null' => true,
        ]);
        $table->addColumn('slug', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ])->addIndex('slug', ['unique' => true]);
        $table->addColumn('content', 'text', [
            'default' => null,
            'limit' => 255,
            'null' => true,
        ]);
        $table->addColumn('status', 'tinyinteger', [
            'default' => 1,
            'limit' => 4,
            'null' => false,
        ])->addIndex('status');
        
        $table->addColumn('created', 'datetime', [
            'comment' => 'Created',
            'default' => null,
            'limit' => null,
            'null' => false,
        ]);
        $table->addColumn('modified', 'datetime', [
            'comment' => 'Modified',
            'default' => null,
            'limit' => null,
            'null' => true,
        ]);
        $table->create();
    }

    /**
     * Drop table articles.
     *
     * @return void
     */
    public function down()
    {
        $this->table('articles')->drop()->save();
    }
}

Khi viết code migration bạn có thể dùng function change(), or up(), down(). Mình hay dùng tách biệt up(), down() để phân biệt logic khi xử lý khi migrate trong hàm up(), còn rollback trong hàm down()

Create column auto

Bạn cũng có thể tạo các column từ khi tạo file bằng cách truyền các tham số cho command


bin/cake bake migration CreateProducts name:string description:text created modified

<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateProducts extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this->table('products');
        $table->addColumn('name', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ]);
        $table->addColumn('description', 'text', [
            'default' => null,
            'null' => false,
        ]);
        $table->addColumn('created', 'datetime', [
            'default' => null,
            'null' => false,
        ]);
        $table->addColumn('modified', 'datetime', [
            'default' => null,
            'null' => false,
        ]);
        $table->create();
    }
}

Quy tắc đặt tên file

Bạn nên đặt tên file theo quy tắc sau


// Tạo một table mới
(/^(Create)(.*)/) 
bin/cake bake migration CreateAdmins

// Drop table
(/^(Drop)(.*)/)
bin/cake bake migration DropAdmins

// Thêm fields cho table đã tồn tại
(/^(Add).*(?:To)(.*)/)
bin/cake bake migration AddGenderToAdmins

// Removes fields from the exist table
(/^(Remove).*(?:From)(.*)/) 
bin/cake bake migration RemoveGenderToAdmins

// Thay đổi kiểu dữ liệu của 1 trường.
(/^(Alter).*(?:On)(.*)/) 
bin/cake bake migration AlterGenderOnAdmins

Run migration database

Để chạy migration tạo database dùng command sau:


bin/cake migrations migrate

// Migrate success
 == 20220810093618 CreateAdmins: migrating
 == 20220810093618 CreateAdmins: migrated 0.0665s

 == 20220810093908 CreateUsers: migrating
 == 20220810093908 CreateUsers: migrated 0.0356s

 == 20220810094102 CreateArticles: migrating
 == 20220810094102 CreateArticles: migrated 0.0372s

Các file migration đã chạy được lưu vào bảng phinxlog

Rollback migration database

Để rollback lại database dùng lệnh sau:


bin/cake migrations rollback

// Rollback file được tạo mới đây nhất
 == 20220810094102 CreateArticles: reverting
 == 20220810094102 CreateArticles: reverted 0.0348s

Mỗi một lần chạy rollback thì chỉ rollback được 1 file migration

Check status migration database

Bạn cũng có thể kiểm tra trạng thái của các migration sử dụng command:


bin/cake migrations status

// Check status
Status  Migration ID    Migration Name 
-----------------------------------------
     up  20220810093618  CreateAdmins   
     up  20220810093908  CreateUsers    
     up  20220810094102  CreateArticles 

Skipping the schema.lock file generation

Khi chạy lệnh migrate file schema.lock sẽ được tự động tạo ra, muốn không tạo ra file này thì chạy command như sau:


bin/cake migrations migrate --no-lock

bin/cake migrations rollback --no-lock

Như vậy là chúng ta đã tìm hiểu xong migration database với cakephp 4. Chúc các bạn tạo bảng thành công. Nếu bạn gặp khó khăn trong việc viết file migration hãy comment bên dưới nhé. Thanks for reading...