Laravel5のEloquentORMで1対多のリレーション(その3)
今日は、Gathersに詳細データを添付したいと思います。新たに、detailsテーブルと、itemsテーブルを作成します。detailsテーブルに詳細情報を登録するのですが、detailsの詳細情報の項目名は、itemsテーブルから参照することにします。
- detailsテーブル
- カラム(id,gather_id,item_id,.content+タイムスタンプ)
- itemsテーブル
- カラム(id,name,sort)
テーブルの作成
SetupControllerのgetCreateメソッドを下記のように修正します。
app/Http/Controllers/SetupController.php
public function getCreate($db_table) { //テーブルの存在確認 if(Schema::hasTable($db_table)){ return redirect() ->back() ->withMessage("{$db_table}テーブルが存在しますので、処理を中止します") ->withAlert("alert alert-danger"); } if($db_table == 'gathers'): Schema::create($db_table, function(Blueprint $table) { $table->increments('id'); $table->string('name',100); $table->integer('category_id')->index(); $table->string('code',100)->index(); $table->text('description')->nullable(); $table->timestamps(); $table->timestamp('deleted_at',null)->nullable(); }); return redirect() ->back() ->withMessage("{$db_table}テーブルを作成しました") ->withAlert('alert alert-success'); elseif($db_table == 'categories'): Schema::create($db_table, function(Blueprint $table) { $table->increments('id'); $table->string('name',100); $table->text('description')->nullable(); }); return redirect() ->back() ->withMessage("{$db_table}テーブルを作成しました") ->withAlert("alert alert-success"); elseif($db_table == 'details'): Schema::create($db_table, function(Blueprint $table) { $table->increments('id'); $table->integer('gather_id'); $table->integer('item_id'); $table->text('content'); $table->timestamps(); $table->timestamp('deleted_at',null)->nullable(); }); return redirect() ->back() ->withMessage("{$db_table}テーブルを作成しました") ->withAlert("alert alert-success"); elseif($db_table == 'items'): Schema::create($db_table, function(Blueprint $table) { $table->increments('id'); $table->string('name',100); $table->integer('sort')->default(1); }); return redirect() ->back() ->withMessage("{$db_table}テーブルを作成しました") ->withAlert("alert alert-success"); else: Schema::create($db_table, function(Blueprint $table) { $table->increments('id'); $table->string('name'); $table->text('description')->nullable(); $table->timestamps(); $table->timestamp('deleted_at',null)->nullable(); }); return redirect() ->back() ->withMessage("{$db_table}テーブルを作成しました") ->withAlert('alert alert-success'); endif; }
setupビューを下記のように修正します。
app/resources/views/setup/index.blade.php
@extends('app') @section('content') <div class="container"> <h2>テーブルの作成</h2> @if(Session::has('message')) <p class="{{Session::get('alert')}}"> {{ Session::get('message') }} </p> @endif <a href="{{ url('setup/create/gathers') }}" type="button" class="btn btn-primary btn-lg btn-block">gathersテーブルの作成</a> <a href="{{ url('setup/create/categories') }}" type="button" class="btn btn-primary btn-lg btn-block">categoriesテーブルの作成</a> <a href="{{ url('setup/create/details') }}" type="button" class="btn btn-primary btn-lg btn-block">detailsテーブルの作成</a> <a href="{{ url('setup/create/items') }}" type="button" class="btn btn-primary btn-lg btn-block">itemsテーブルの作成</a> </div> @endsection
下記のようなテーブルが生成されます。
モデルの生成
detailsテーブルと、itemsテーブルを作成したら、モデルを生成します。
コマンドプロンプトから下記のように入力します。
php artisan make:model Detail php aritsan make:model Item
生成したモデルを下記のように修正します。
app/Detail.php
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Detail extends Model { //複数代入のブラックリスト protected $guarded=['id','created_at','updated_at','deleted_at']; /* * 1対多のリレーション * DetailはItemに従属している */ public function item(){ return $this->belongsTo('App\Item'); } }
14-16行目:1対多のリレーションを設定します。belongsToメソッドの第1引数は、リレーションを行うモデルを指定します。Laravel4では、ここは単にItem(モデル名)でしたので、名前空間付きのApp\Itemに変更になっていることを忘れないでください。私は、ここでかなりはまってしまいました。第2引数は、外部ID、第3引数は、内部IDですが、いずれも規約通り(外部IDが、item_id、内部IDがid)に作成していれば、省略できます。
app/Item.php
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Item extends Model { //複数代入のブラックリスト protected $guarded=['id']; //自動タイムスタンプの無効化 public $timestamps=false; }
ここでは、リレーションを設定していませんが、Itemモデルから、Detailモデルを呼び出す場合は、hasManyメソッドでApp\Detailを指定する必要があります。
又、Itemモデルには、created_atとupdated_atは作成していませんので、自動タイムスタンプを無効にしておく必要があります。
Gatherモデルの修正
ついでにGatherモデルにもリレーションを設定します。下記を追加します。
app/Gather.php
public function detail(){ return $this->hasMany('App\Detail'); } }
GatherモデルとDetailモデルをリレーションでつなぎます。これで、下記のようにアクセスすることができます。
- $gather=Gather::find($id);
foreach($gather->detail as $detail):
$detail->item->name; //Itemモデルのnameプロパティにアクセス
$detail->content; //Detailモデルのcontentプロパティにアクセス
endforeach;
本日は、ここまでにします。
2015年5月28日 | コメント/トラックバック(0) | トラックバックURL |
カテゴリー:Laravel