Tech Blog

Phinxを利用してデータベースのマイグレーションをおこなう

概要

PhinxとはPHPアプリケーションのデータベースのマイグレーションを簡単に行うことが出来るフレームワークに依存しないパッケージです。
Phinxを利用してデータベースのマイグレーションをおこないます。

1.インストール

まず任意のプロジェクトディレクトリに移動しComposerを使用してインストールします。

$ composer require robmorgan/phinx
Using version ^0.12.9 for robmorgan/phinx
./composer.json has been created
Running composer update robmorgan/phinx
Loading composer repositories with package information
Updating dependencies
Lock file operations: 21 installs, 0 updates, 0 removals
  - Locking cakephp/core (4.3.0)
  - Locking cakephp/database (4.3.0)
  - Locking cakephp/datasource (4.3.0)
  - Locking cakephp/utility (4.3.0)
  - Locking psr/container (2.0.1)
  - Locking psr/log (1.1.4)
  - Locking psr/simple-cache (1.0.1)
  - Locking robmorgan/phinx (0.12.9)
  - Locking symfony/config (v5.3.10)
  - Locking symfony/console (v5.3.10)
  - Locking symfony/deprecation-contracts (v2.4.0)
  - Locking symfony/filesystem (v5.3.4)
  - Locking symfony/polyfill-ctype (v1.23.0)
  - Locking symfony/polyfill-intl-grapheme (v1.23.1)
  - Locking symfony/polyfill-intl-normalizer (v1.23.0)
  - Locking symfony/polyfill-mbstring (v1.23.1)
  - Locking symfony/polyfill-php73 (v1.23.0)
  - Locking symfony/polyfill-php80 (v1.23.1)
  - Locking symfony/polyfill-php81 (v1.23.0)
  - Locking symfony/service-contracts (v1.1.2)
  - Locking symfony/string (v5.3.10)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 21 installs, 0 updates, 0 removals
  - Downloading symfony/string (v5.3.10)
  - Downloading symfony/console (v5.3.10)
  - Downloading symfony/config (v5.3.10)
  - Installing psr/simple-cache (1.0.1): Extracting archive
  - Installing psr/log (1.1.4): Extracting archive
  - Installing cakephp/core (4.3.0): Extracting archive
  - Installing cakephp/utility (4.3.0): Extracting archive
  - Installing cakephp/datasource (4.3.0): Extracting archive
  - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
  - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
  - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
  - Installing symfony/string (v5.3.10): Extracting archive
  - Installing symfony/service-contracts (v1.1.2): Extracting archive    
  - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive      
  - Installing symfony/deprecation-contracts (v2.4.0): Extracting archive
  - Installing symfony/console (v5.3.10): Extracting archive
  - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
  - Installing symfony/filesystem (v5.3.4): Extracting archive
  - Installing symfony/config (v5.3.10): Extracting archive
  - Installing psr/container (2.0.1): Extracting archive
  - Installing cakephp/database (4.3.0): Extracting archive
  - Installing robmorgan/phinx (0.12.9): Extracting archive
16 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
12 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

2.Phinxの初期化

$ vendor/bin/phinx init
Phinx by CakePHP - https://phinx.org.

created <ディレクトリ名>\phinx.php

初期化することでプロジェクトのディレクトリにphinx.phpファイルが作成されます。
作成されたphinx.phpファイルにデータベースのデフォルトの設定が記述されているのでプロジェクト用に適宜必要な箇所を追記修正します。
今回はtesting環境のみで試すのでtesting_dbというデータベースを作成しておき、パスワードの箇所がカラになっているのでパスワードを記述します。
また、マイグレーションファイルを配置するディレクトリを作成する必要があるのでデフォルトの設定にしたがい「db/migrations」ディレクトリを作成します。

<?php

return
[
    'paths' => [
        'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations',
        'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'
    ],
    'environments' => [
        'default_migration_table' => 'phinxlog',
        'default_environment' => 'development',
        'production' => [
            'adapter' => 'mysql',
            'host' => 'localhost',
            'name' => 'production_db',
            'user' => 'root',
            'pass' => '',
            'port' => '3306',
            'charset' => 'utf8',
        ],
        'development' => [
            'adapter' => 'mysql',
            'host' => 'localhost',
            'name' => 'development_db',
            'user' => 'root',
            'pass' => '',
            'port' => '3306',
            'charset' => 'utf8',
        ],
        'testing' => [
            'adapter' => 'mysql',
            'host' => 'localhost',
            'name' => 'testing_db',
            'user' => 'root',
            'pass' => '<ここにパスワード>',
            'port' => '3306',
            'charset' => 'utf8',
        ]
    ],
    'version_order' => 'creation'
];

3.マイグレーションファイルの作成

「AddUserLoginTable」という名前でPhinxマイグレーションを作成します。

$ vendor/bin/phinx create AddUserLoginTable
Phinx by CakePHP - https://phinx.org.

using config file phinx.php
using config parser php
using migration paths
 - <ディレクトリ名>\db\migrations
using seed paths
using migration base class Phinx\Migration\AbstractMigration
using default template
created db\migrations\20211031044819_add_user_login_table.php

「20211031044819_add_user_login_table.php」ファイルが「db/migrations」ディレクトリに作成されます。
ファイル名はタイムスタンプと指定したマイグレーション名に基づいています。

4.マイグレーションファイルの編集

作成されたファイルにはAbstractMigrationクラスを継承したAddUserLoginTableクラスが記述されています。

<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class AddUserLoginTable extends AbstractMigration
{
    /**
     * Change Method.
     *
     * Write your reversible migrations using this method.
     *
     * More information on writing migrations is available here:
     * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
     *
     * Remember to call "create()" or "update()" and NOT "save()" when working
     * with the Table class.
     */
    public function change(): void
    {

    }
}

ここではchangeメソッドを削除し、upメソッドとdownメソッドを新しく定義します。
(changeメソッドはupメソッドとdownメソッドを兼ねるものですが今回は敢えてupメソッドとdownメソッドで書いています)

upメソッドではuser_loginsテーブルを作成しuser_id, createdのカラムを作成しています。逆にdownメソッドではuser_loginsテーブルを削除します。

<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class AddUserLoginTable extends AbstractMigration
{
    /**
     * Change Method.
     *
     * Write your reversible migrations using this method.
     *
     * More information on writing migrations is available here:
     * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
     *
     * Remember to call "create()" or "update()" and NOT "save()" when working
     * with the Table class.
     */
    public function up()
    {
        $table = $this->table('user_logins');
        $table->addColumn('user_id', 'integer')
              ->addColumn('created', 'datetime')
              ->create();
    }
    public function down()
    {
        $table = $this->table('user_logins');
        $table->drop()
              ->save();
    }
}

5.マイグレーションの実行

マイグレーションを実行するとupメソッドが実行されテーブルが作成されます。
またこのときphinxlogというテーブルも自動で作成されます。

$ vendor/bin/phinx migrate -e testing
Phinx by CakePHP - https://phinx.org.

using config file phinx.php
using config parser php
using migration paths
 - <ディレクトリ名>\db\migrations
using seed paths
using environment testing
using adapter mysql
using database testing_db
ordering by creation time

 == 20211031044819 AddUserLoginTable: migrating
 == 20211031044819 AddUserLoginTable: migrated 0.0082s

All Done. Took 0.0460s

データベースを確認すると「user_logins」テーブルが定義されているのを確認できます。

MariaDB [testing_db]> show columns from user_logins;
+---------+----------+------+-----+---------+----------------+
| Field   | Type     | Null | Key | Default | Extra          |
+---------+----------+------+-----+---------+----------------+
| id      | int(11)  | NO   | PRI | NULL    | auto_increment |
| user_id | int(11)  | NO   |     | NULL    |                |
| created | datetime | NO   |     | NULL    |                |
+---------+----------+------+-----+---------+----------------+

6.ロールバックの実行

次に先ほど実行したマイグレーションをもとに戻してみます。

$ vendor/bin/phinx rollback -e testing
Phinx by CakePHP - https://phinx.org.

using config file phinx.php
using config parser php
using migration paths
 - <ディレクトリ名>\db\migrations
using seed paths
using environment testing
using adapter mysql
using database testing_db
ordering by creation time

 == 20211031044819 AddUserLoginTable: reverting
 == 20211031044819 AddUserLoginTable: reverted 0.0147s

All Done. Took 0.0356s

データベースを確認すると「user_logins」テーブルがなくなっているのが確認できます。

MariaDB [testing_db]> show tables;
+----------------------+
| Tables_in_testing_db |
+----------------------+
| phinxlog             |
+----------------------+
1 row in set (0.001 sec)