ぺい

大阪の専門学生の落書き。主にエンジニア寄りの話。

PHPのLaravel5.4でアプリケーションを作る(Migration編)

f:id:tikasan0804:20170528230547p:plain

マイグレーション

そもそもマイグレーションとは何だ?という人向けに公式のドキュメントが分かりやすく説明してくれてます。

マイグレーションとはデータベースのバージョンコントロールのようなもので、チームでアプリケーションデータベースのスキーマを簡単に更新し共有できるようにしてくれます。通常、マイグレーションはアプリケーションのデータベーススキーマを簡単に構築できるようにする、Laravelのスキーマビルダーと一緒に使用します。

データベースのバージョン管理ということです。

LaravelのSchemaファサードはテーブルの作成や操作をどのデータベースエンジンを使うかに関わらずサポートします。Laravelがサポートしているデータベースシステム全部で同じ記述法と書きやすいAPIを共用できます。

つまり、Laravelのマイグレーションの機能を使えば、様々なデータベースエンジンに対応するマイグレーションが出来上がるということのようです。 では、さっそくマイグレーションのコードを書いていきます。

f:id:tikasan0804:20170512153207p:plain

準備

github.com

Migrationするということは、何でもいいのでデータベースを用意する必要があります。今回はこちらが用意したDockerでMySQLを使うことにします。

make docker/build
make docker/start
項目
HOST 127.0.0.1
PORT 3306
DATABASE celler
USERNAME celler
PASSWORD celler

config/database.phpに以下のような感じでデータベースとの接続設定をしてください。(個々の環境に合わせてください)

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'celler'),
        'username' => env('DB_USERNAME', 'celler'),
        'password' => env('DB_PASSWORD', 'celler'),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
],

上記に加えて、.envという設定ファイルにもデータベース情報を追記してください。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=celler
DB_USERNAME=celler
DB_PASSWORD=celler

.envを設定しないと、homesteadユーザーを使ってデータベースにアクセスしようとします。

[Illuminate\Database\QueryException]                       
  SQLSTATE[HY000] [1045] Access denied for user 'homestead'  
  @'localhost' (using password: YES) (SQL: select * from in  
  formation_schema.tables where table_schema = homestead an  
  d table_name = migrations)  

config/database.phpはModel用の定義で、.envはartisanのための設定ファイルのようです。

実装

$ php artisan make:migration create_accounts_table

以下の形式でファイルが作成されます。
database/migrations/yyyy_mm_dd_timestamp_create_accounts_table.php
↑具体例
2017_05_28_143736_create_accounts_table.php

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAccountsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('accounts', function (Blueprint $table) {
            $table->bigIncrements('id')->comment('ID');
            $table->string('name')->comment('名前');
            $table->string('email')->comment('メールアドレス');
            $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('accounts');
    }
}
php artisan migrate
Migrating: 2017_05_28_143736_create_accounts_table
Migrated:  2017_05_28_143736_create_accounts_table

上記のようなメッセージが出たら正しくテーブルが作成されます。

他テーブルも対応

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBottlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bottles', function (Blueprint $table) {
            $table->bigIncrements('id')->comment('ID');
            $table->string('name')->comment('ボトル名');
            $table->integer('quantity')->default(0)->comment('数量');
            $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
            $table->softDeletes();
            $table->unsignedBigInteger('account_id');

            $table->foreign('account_id')
                ->references('id')
                ->on('accounts')
                ->onDelete('restrict')
                ->onUpdate('restrict');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('bottles');
    }
}
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->bigIncrements('id')->comment('ID');
            $table->string('name')->comment('カテゴリ名');
            $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('categories');
    }
}
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBottleCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bottle_categories', function (Blueprint $table) {
            $table->bigIncrements('id')->comment('ID');
            $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
            $table->softDeletes();
            $table->unsignedBigInteger('category_id');
            $table->unsignedBigInteger('bottle_id');

            $table->foreign('bottle_id')
                ->references('id')
                ->on('bottles')
                ->onDelete('restrict')
                ->onUpdate('restrict');

            $table->foreign('category_id')
                ->references('id')
                ->on('categories')
                ->onDelete('restrict')
                ->onUpdate('restrict');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('bottle_categories');
    }
}
php artisan migrate         
Migrating: 2017_05_28_143736_create_accounts_table
Migrated:  2017_05_28_143736_create_accounts_table
Migrating: 2017_05_29_125546_create_bottles_table
Migrated:  2017_05_29_125546_create_bottles_table
Migrating: 2017_05_30_125835_create_categories_table
Migrated:  2017_05_30_125835_create_categories_table
Migrating: 2017_05_30_130002_create_bottle_categories_table
Migrated:  2017_05_30_130002_create_bottle_categories_table

php artisan migrate:status
+------+--------------------------------------------------+
| Ran? | Migration                                        |
+------+--------------------------------------------------+
| Y    | 2017_05_28_143736_create_accounts_table          |
| Y    | 2017_05_29_125546_create_bottles_table           |
| Y    | 2017_05_30_125835_create_categories_table        |
| Y    | 2017_05_30_130002_create_bottle_categories_table |
+------+--------------------------------------------------+

よく使うコマンド

コマンド 説明
php artisan migrate マイグレーションを実行する
php artisan migrate:rollback 最後に実行したマイグレーションをまとめて元に戻す
php artisan migrate:reset 全てのマイグレーションロールバックする
php artisan migrate:refresh 全てのマイグレーションロールバックし、マイグレーションをする
php artisan migrate:status 現在のマイグレーションの状態を参照する

参考になった日本語情報

MigrationとSeederを組み合わせると便利なので、後日また記事にする予定です。