※この記事は人狼GM支援ツールを作る(環境構築編)の続きとなります。
はじめに
前回、Laravel Homesteadを利用してVM上に環境を構築しました。
今回から実装に入るのですが、まずは私が最初につまづいたDBのマイグレーションとLaravelのモデルから整理していきます。
以下、各ソフトウェアのバージョンは
- PHP 7.2.5
- MySQL 5.7.22
- Laravel 5.6
です。
マイグレーション
今回用意した環境(Laravel Homestead)には、デフォルトでMySQLが用意されています。ユーザ名とパスワードもあらかじめ設定してある状態です。
接続情報はプロジェクト内の.env
ファイルに書かれています
今回は、あらかじめ用意したテーブル定義に沿ってテーブルを作成していきます。
テーブル定義の例は以下のようになります。
- room表
カラム | 型 | 制約 |
---|---|---|
room_id | int | Primary Key |
player_num | int | Not Null |
- player表
カラム | 型 | 制約 |
---|---|---|
player_id | int | Primary Key |
player_name | varchar | Not Null |
room_id | int | Foreign Key |
テーブルを作成する
早速定義通りにテーブルを作成していきます。
以下のコマンドをプロジェクトのルートで実行します。
> php artisan make:migration CreateRoomTable
このコマンドで、database/migrations
に {timestamp}_create_room_table.php
というファイルが生成されます。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRoomTable extends Migration
{
/**
* マイグレーション実行
*
* @return void
*/
public function up()
{
Schema::create('room', function (Blueprint $table) {
// ここにテーブル定義を記述
});
}
/**
* マイグレーションを元に戻す
*
* @return void
*/
public function down()
{
Schema::drop('room');
}
}
日本語ドキュメントを参考にしつつ、(Laravel 5.6 データベース:マイグレーション)createメソッドのクロージャ内にカラム名と型、制約などをバシバシ記述していきます。
public function up()
{
Schema::create('room', function (Blueprint $table) {
$table->increments('room_id');
$table->integer('player_num');
});
}
increments(カラム名)
はMySQLの AUTO_INCREMENT
に対応しています。
この調子で、Player表の定義も書いていきます
public function up()
{
Schema::create('player', function (Blueprint $table) {
$table->increments('player_id');
$table->integer('room_id')->unsigned();
$table->string('player_name', 10);
$table->foreign('room_id')->references('room_id')->on('room')->onDelete('cascade');
});
}
ここで注意すべき点として、外部キーに指定したカラムの型があります。
room_id
は符号なしINTなので、外部キーでもそれに合わせてやる必要があります。
加えて、$table->foreign('room_id')->references('room_id')->on('room')->onDelete('cascade');
で外部キー制約を指定します。
初期値を挿入する
一部のテーブルには、あらかじめデータを入れておきたいことがあります。(マスタ表とか)
そこで、テーブルに初期値を挿入するシーダクラスを生成し、テーブル定義同様に書いていきます。
> php artisan make:seeder HogeMstSeeder
このコマンドをプロジェクトルートで実行すると、database/seeds
に HogeMstSeeder.php
が生成されます。
やはり日本語ドキュメントを参考にしつつ、(Laravel 5.6 データベース:シーディング)初期値を書いておきます。
マイグレーションを実行する
一通りのテーブル定義と初期値設定を書いたら、マイグレーションを実行してMySQLにデータを流し込みます。
> php artisan migrate --seed
SQLのエラーが吐き出されなければ成功です。
これで、PHPのコードを書くだけでテーブル生成と値の挿入ができました。
エラー吐いたんだけど……?
もしエラーを吐いた場合、原因として以下のものが挙げられます。
- 外部キーの型があってない
- 外部キー制約が追加できない
前者のエラーは前述のとおり、外部キーに指定したカラムにunsigned()をつなげてやれば解決します。
後者のエラーの場合、外部キーで指定したいテーブルがまだ作成されていない可能性があります。
というのも、マイグレーションの実行順は タイムスタンプ順が古い順 だからです。
手あたり次第にテーブル定義を書き散らすとハマります。(ハマりました)
私はファイル名のタイムスタンプをいい感じに弄って実行順を変えることで解決しました。
※力技です。もっとスマートに解決できると思います。
また、再度マイグレーションを実行する際は migrate:fresh
か migrate:refresh
のコマンドを使います。
migrate:fresh
では今あるテーブルをすべてdropして再度実行し、migrate:refresh
ではすべての操作をロールバックして再度実行するという違いがあります。
モデル生成
今までで作成したテーブルに対するモデルクラスを生成します。
以下のコマンドでRoom表に対するモデルが生成されます。
> php artisan make:model Room
これで、app
ディレクトリ下にRoom.php
が生成されます。
Laravelでは、モデルクラスをどこに配置してもよい、というルールになっていますので、各々好きなところに配置してください。
このモデルクラスですが、eloquentというORMになっています。
(eloquentの解説はここでは省略します。余裕があれば後日……)
生成したままの状態では、
- CalemCase単数形のクラス名がsnake_case複数形のテーブル名と紐づく(ex.
RoleStatus
クラス →role_statuses
表) - 主キーのカラム名は
id
だと認識されます。これを実際のテーブル定義に合わせるよう、モデルクラスに追記していきます。
class Room extends Model
{
protected $table = 'room'; // (1)
protected $primaryKey = 'room_id'; // (2)
protected $fillable = [ /* insertを許可するカラム名 */]; // (3)
public $timestamps = false; // (4)
}
(1)ではテーブル名、(2)では主キーの変数を書き換えています。
(3)のように$fillable
に対して追加すると、挿入を許可するカラムを配列にまとめて指定することで予期せぬ操作を防ぐことができます。
(4)では、created_at
とupdated_at
という2つのカラムを使わないよう指定しています。今回のようにテーブル定義にこれらのカラムを含めなかった場合は、この指定を忘れるとモデルを操作したときにエラーを吐きます。
準備完了!
eloquentの操作やリレーションの定義といった話をかなーり省略しましたが、これでデータベースとその操作の準備は完了です。
SQLを一行たりとも書かずに、データベースにテーブルを作成することができました!
おまけ
今回はテーブル生成 → モデルクラス生成の順に作業しました。
実はこれを同時に行うコマンドがあります。
> php artisan make:model Room -m
このコマンドで、Room.php
と{timestamp}_create_rooms_table.php
が同時に生成されます。
※rooms、と複数形になっていることに注目!
テーブル定義の際、主キーのカラム名はid
に、外部キーのカラム名は{参照するテーブル名}_id
としておくと便利です。