CakePHP3で開発、テスト用に初期データを仕込む方法

#この記事について
CakePHPでは、`bin/cake migrations`というコマンドを実行するだけで、SQLを手動で実行せずにデータを挿入することができる。これにより、開発環境やテスト環境で、データを汚しても、元の状態に戻すことができる。今回はそのやり方として、Seedingと呼ばれる、名の通り「種を植える」手法を紹介する。

#Seedingとは
`cakephpルートディレクトリ/Seeds`の配下にできる`.php`形式のファイルをSeedファイルと言い、それを実行するとInsertが走る。この動作を`Seeding`と呼ぶ。

#参考
以下を参考にしました。
1. [CakePHP3のSeeding（シーディング）で任意の初期データ投入＆fakerでダミーデータ挿入もしてみる]( https://www.ritolab.com/entry/62)
2. [【CakePHP3】seedの使い方](https://insight.hiliberate.biz/?p=2285)

cakephpルートディレクトリへ移動し、以下のコマンドを実行。

#手順
以下の手順で初期データを仕込みます。
1. MySQLでまずデータを作る
2. MySQLのデータを元に、Seedファイルを自動生成する
3. MySQLを空にする
4. Seedingを実行し、 MySQLにデータを挿入する
5. Migrations migrateを実行し、MySQLにデータを挿入する

###1. MySQLでまずデータを作る
Seedファイルを一から書き込むより、コマンドを叩いてMySQLのデータを元にシードファイルを作成した方が手取り早いので、まずはMySQLに適当なデータを作ります。

自分はこんな感じのUsers Tableを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/b6018b18-bc8e-ec09-0492-b559e9c15f35.png)

###2. MySQLのデータを元に、Seedファイルを自動生成する
これを元に以下のコマンドを実行することで、元データのINSERT文が入ったSeedファイルが作成されます。

```shell-session
bin/cake bake seed --data Users
```

※Seedファイルを一から作りたい場合は以下を実行してください。

```shell-session
# seedのテンプレートファイルを生成する
bin/cake bake seed Users
```

```shell-session
# ユーザーテーブルのデータを元にseedファイルを生成する
bin/cake bake seed --data Users
```

これにより、`Seeds`フォルダ配下に、`UsersSeed.php`が作成されたはずなので、確認してください。
`UsersSeed.php`では、AbstractSeedを継承し、かつ`run`メゾットの中で、挿入するデータを`data`というArray型の変数に宣言しています。

例えば、自分の場合、以下のようなコードが書かれています。

```php3

<?php
use Migrations\AbstractSeed;

class UsersSeed extends AbstractSeed
{
    /**
     * Run Method.
     *
     * Write your database seeder using this method.
     *
     * More information on writing seeds is available here:
     * http://docs.phinx.org/en/latest/seeding.html
     *
     * @return void
     */
    public function run()
    {
        $data = [
            [
                'id' => '1',
                'login' => 'admin',
                'password' => 'XXX',
                'role' => 'admin',
                'name' => 'James'
            ],
            [ //以下省略
          
```

###3. MySQLを空にする

テーブルのデータを`TRUNCATE`で空にします。

```sql
TRUNCATE TABLE users;

/*念の為、レコード数が０になっているか確認*/
SELECT count(*) FROM users;
```

次に、いよいよSeedingを実行します。

###4. Seedingを実行し、 MySQLにデータを挿入する

生成したSeedファイルを以下で実行。

```shell-session
# 以下ですべてのSEEDを実行
$ bin/cake migrations seed

# UsersSeed.phpだけを実行する場合、以下を実行
$ bin/cake migrations seed --seed UsersSeed
```

以下、実際の実行結果のスクショです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/d114fe48-7498-d460-f0b7-34852c66a91e.png)

実行後、再度`Users`テーブルをSELECTして見ると、データが戻っていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/0d552701-9d6f-cf9b-b6a9-2ee10c81d355.png)

###5. Migrations migrateを実行し、MySQLにデータを挿入する

次に、`Migrations migrate`のみを実行し、Seedingを行います。
まず、Step3と同様に、`TRUNCATE TABLE users;`でUsersテーブルのレコードを空にします。

`/config/Migrations/`の配下に、新たに以下のようなMigrationファイルを作成します。

ファイル名: 20191210063412_SeedUsers.php

```php3
<?php

use Cake\Datasource\ConnectionManager;
use Migrations\AbstractMigration;
use Migrations\Migrations;

/**
 * SeedUsers Migrations
 */
class SeedUsers extends AbstractMigration
{
    public function up()
    {
        //ここで、SeedUsersという接続オブジェクトを定義
        ConnectionManager::setConfig("SeedUsers", ConnectionManager::getConfig("default"));
        
        //UsersSeedを以下のコードで実行
        $migration = new Migrations();
        $migration->seed(['seed' => 'UsersSeed', 'connection' => 'SeedUsers']);
    }

    public function down()
    {
        //Rollbackした際に、テーブルをTRUNCATEする
        $this->execute('TRUNCATE TABLE users');
    }
}
```

これで、`migrations migrate`を実行するだけで、データが挿入できる準備が整いました。ちなみにファイル名の頭につく`20191210063412`は現在の時間（Timestamp)を表しています。手動で作成する際は気をつけてください。

以下、実行結果のデモです。
![Migrations_Demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/3033afb2-6fff-be76-902e-317fa1a28b1c.gif)

`Phinxlog`に、実行後レコードが追加されているのが、わかります。
Rollbackする際は、`Phinxlog`で`version`コラムを確認し、戻したいVersionまで戻ることができます。
`20191210063412_SeedUsers.php`で、Rollbackの際はテーブルをTRUNCATEするよう`down()`で定義しているので、戻すとTRUNCATEが実行され、レコードが無くなります。Rollbackは以下のコマンドで実行できます。

```bash
$bin/cake migrations rollback -t <version>
```

#最後に
以上、CakePHPで開発、テスト用に初期データを仕込むやり方を説明しました。