Laravel5のEloquentORMで1対多のリレーション(その4)

前回は、新しいテーブルを作成して、そのモデルとGatherモデルにリレーションを設定するところまでを作業しました。本日は、実際に新しいモデル(DetailモデルとItemモデル)と、基本となるモデル(Gatherモデル)とのリレーションを利用しながら、コードを記述していきたいと思います。

Gathersコントローラの修正

GathersControllerを下記のように修正します。

app/Http/Controllers/GathersController.php

<?php namespace App\Http\Controllers;

use App\Http\Requests;
use App\Http\Controllers\Controller;

use Illuminate\Http\Request;
use App\Http\Requests\GathersPostRequest;
use App\Http\Requests\ItemsPostRequest;
use App\Gather;
use App\Category;
use App\Item;
use App\Detail;

class GathersController extends Controller {

 public function getIndex()
 {
 $gathers=Gather::paginate(5);
 return view('gathers.index')
 ->with('gathers',$gathers);
 }
 public function getCreate()
 {
 $categories=Category::lists('name','id');
 $items=Item::all();
 return view('gathers.create',compact('categories','items'));
 }
 public function postCreate(GathersPostRequest $request)
 {
 $gather=Gather::firstOrCreate([
 'name'=>$request->name,
 ]);
 $gather->code=$request->code;
 $gather->category_id=$request->category_id;
 $gather->description=$request->description;
 $gather->save();
 foreach($request->item as $key=>$item):
 if($item):
 $detail=Detail::firstOrCreate([
 'gather_id'=>$gather->id,
 'item_id'=>$key,
 ]);
 $detail->content=$item;
 $detail->save();
 endif;
 endforeach;
 return redirect()->to("gathers");
 }
 public function postCategoryCreate(Request $request){
 $category=Category::firstOrCreate($request->only('name'));
 $category->description=$request->description ?: null;
 $category->save();
 return redirect()->back();
 }
 public function postItemCreate(ItemsPostRequest $request){
 if($request->name):
 $item=new Item();
 $item->name=$request->name;
 $item->save();
 endif;
 return redirect()->back();
 }
 public function postDetailCreate(Request $request){
 if($request->id):
 $gather=Gather::find($request->id);
 foreach($request->detail as $key=>$value):
 if($value):
 $detail=Detail::firstOrCreate([
 'gather_id'=>$gather->id,
 'item_id'=>$key,
 ]);
 $detail->content=$value;
 $detail->save();
 endif;
 endforeach;
 endif;
 return redirect()->back();
 }
 public function getShow($id)
 {
 $gather=Gather::find($id);
 return view('gathers.show',compact('gather'));
 }
 public function getUpdate($id)
 {
 $gather=Gather::find($id);
 $lists=$gather->detail->lists('item_id');
 $items=Item::whereNotIn('id',$lists)->get();
 return view("gathers.update")
 ->with('gather',$gather)
 ->with('items',$items);
 }
 
 public function postUpdate(GathersPostRequest $request){
 $gather=Gather::find($request->id);
 $gather->name=$request->name;
 $gather->category_id=$request->category_id;
 $gather->code=$request->code;
 $gather->description=$request->description;
 $gather->save();
 foreach($request->detail as $key=>$value):
 if($value):
 $detail=Detail::firstOrCreate([
 'gather_id'=>$gather->id,
 'item_id'=>$key,
 ]);
 $detail->content=$value;
 $detail->save();
 endif;
 endforeach;
 return redirect()->to("gathers");
 }
 public function postDelete(Request $request)
 {
 $gather=Gather::find($request->id);
 $gather->delete();
 return redirect()->to('gathers');
 }
}

8行目:説明は省略していますが、Itemモデル用のフォームリクエストを作成して、useでインポートしています。内容的には、下記のようなバリデーション(項目名が重複しない)を設定しています。

public function rules()
{
return [
‘name’ => [‘required’,’unique:items’],
];
}

9-12行目:各モデルをインポートしています。これで、Model::find()みたいに使用することができます。use演算子を使用しない場合は、App\Model::find()と記述することで、モデルを使用することができます。

30-32行目:フォームから送られてくるnameフィールドの値がユニークなら新規モデルオブジェクトを作成し、もし同じ値のnameカラムが存在したらその値のモデルオブジェクトを選択します。このfirstOrCreateメソッドは、同じ値のデータを重複させないために便利なメソッドですので、大変重宝します。只、このfirstOrCreateメソッドを使用するには、複数代入のホワイトリスト($fillable)か、ブラックリスト($guraded)を設定する必要がありますので、気をつけてください。

37-46行目:フォームビューから送られてきたitem配列を$keyと$valueの両方を利用してitem_idとitemのcontentフィールドを取得するために使用しています。フォームビューから {!! Form::text(“item[$item->id]”) !!} のような形で送信します。

86-88行目:既に入力済み以外の詳細項目のオブジェクトを取得します。

createビューの修正

createビューを下記のように修正します。

app/resources/view/gathers/create.blade.php

@extends('app')
@section('content')
<div class="container">
 <h2>新規作成</h2>
 @if($errors->all())
 @foreach($errors->all() as $error)
 <p class="alert alert-danger">
 {{ $error }}
 </p>
 @endforeach
 @endif
 {!! Form::open(["class"=>"form-horizontal"]) !!}
 <div class="form-group">
 {!! Form::label("category_id","カテゴリ",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::select("category_id",$categories) !!}
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("category","カテゴリの作成",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 <a href="#" data-toggle="modal" data-target="#category" class="btn btn-warning">カテゴリの新規作成</a>
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("name","名前",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::text("name","",["class"=>"form-control"]) !!}
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("code","Code",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::text("code","",["class"=>"form-control"]) !!}
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("description","説明",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::textarea("description","",["class"=>"form-control"]) !!}
 </div>
 </div>
 <div class="form-group">
 <div class="col-sm-10 col-sm-push-2">
 <a href="#" data-toggle='modal' data-target='#item'>新規項目の作成</a>
 </div>
 </div>
 @foreach($items as $item)
 <div class="form-group">
 {!! Form::label("item",$item->name,["class"=>"control-label col-sm-2"]) !!}
 <div class="col-sm-10">
 {!! Form::text("item[$item->id]",'',["class"=>"form-control"]) !!}
 </div>
 </div>
 @endforeach
 <div class="form-group">
 <div class="col-sm-10">
 {!! Form::submit("新規作成",["class"=>"btn btn-primary col-sm-offset-2"]) !!}
 </div>
 </div> 
{!! Form::close() !!}
 <div class="modal fade" id="category">
 <div class="modal-dialog">
 {!! Form::open(['url'=>'gathers/category-create']) !!}
 <div class="modal-content">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
 <h4 class="modal-title alert alert-success">新規カテゴリの作成</h4>
 </div>
 <div class="modal-body">
 {!! Form::label("name","カテゴリ名*",["class"=>"control-label"]) !!}
 {!! Form::text('name','',["class"=>"form-control","required"=>"required"]) !!}
 {!! Form::label("description","説明",["class"=>"control-label"]) !!}
 {!! Form::textarea('description','',["class"=>"form-control"]) !!}
 </div>
 <div class="modal-footer">
 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
 <input type="submit" class="btn btn-primary" value="作成">
 </div>
 </div><!-- /.modal-content -->
 {!! Form::close() !!}
 </div><!-- /.modal-dialog -->
 </div><!-- /.modal -->
 <div class="modal fade" id="item">
 <div class="modal-dialog">
 {!! Form::open(['url'=>'gathers/item-create']) !!}
 <div class="modal-content">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
 <h4 class="modal-title alert alert-success">新規項目の作成</h4>
 </div>
 <div class="modal-body">
 {!! Form::label("name",'項目名',["class"=>"control-label"]) !!}
 {!! Form::text('name','',["class"=>"form-control","required"=>"required"]) !!}
 </div>
 <div class="modal-footer">
 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
 <input type="submit" class="btn btn-primary" value="作成">
 </div>
 </div><!-- /.modal-content -->
 {!! Form::close() !!}
 </div><!-- /.modal-dialog -->
 </div><!-- /.modal -->
</div>
@endsection

下記のようなビューが生成されます。

2015-05-26 14-56-44

updateビューの修正

updateビューも下記のように修正します。

app/resources/views/gathers/update.blade.php

@extends('app')
@section('content')
<div class="container">
 <h2>修正</h2>
 @if($errors->all())
 @foreach($errors->all() as $error)
 <p class="alert alert-danger">
 {{ $error }}
 </p>
 @endforeach
 @endif
 {!! Form::open(["class"=>"form-horizontal"]) !!}
 <div class="form-group">
 {!! Form::label("category_id","カテゴリ",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::select("category_id",$gather->category->lists('name','id'),$gather->category_id) !!}
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("category","カテゴリの作成",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 <a href="#" data-toggle="modal" data-target="#category" class="btn btn-warning">カテゴリの新規作成</a>
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("name","名前",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::text("name",$gather->name,["class"=>"form-control"]) !!}
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("code","Code",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::text("code",$gather->code,["class"=>"form-control"]) !!}
 </div>
 </div>
 <div class="form-group">
 {!! Form::label("description","説明",["class"=>"col-sm-2 control-label"]) !!}
 <div class="col-sm-10">
 {!! Form::textarea("description",$gather->description,["class"=>"form-control"]) !!}
 </div>
 </div>
 @foreach($gather->detail as $detail)
 <div class="form-group">
 {!! Form::label("detail",$detail->item->name,["class"=>"control-label col-sm-2"]) !!}
 <div class="col-sm-10">
 {!! Form::text("detail[$detail->item_id]",$detail->content,["class"=>"form-control"]) !!}
 </div>
 </div>
 @endforeach
 <div class="form-group">
 <div class="col-sm-10">
 {!! Form::hidden("id",$gather->id) !!}
 {!! Form::submit("修正",["class"=>"btn btn-primary col-sm-offset-2"]) !!}
 </div>
 </div> 
{!! Form::close() !!}
 <div class="modal fade" id="category">
 <div class="modal-dialog">
 <div class="modal-content">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
 <h4 class="modal-title alert alert-success">新規カテゴリの作成</h4>
 </div>
 {!! Form::open(['url'=>'gathers/category-create']) !!}
 <div class="modal-body">
 {!! Form::label("name","カテゴリ名*",["class"=>"control-label"]) !!}
 {!! Form::text('name','',["class"=>"form-control","required"=>"required"]) !!}
 {!! Form::label("description","説明",["class"=>"control-label"]) !!}
 {!! Form::text('description','',["class"=>"form-control"]) !!}
 </div>
 <div class="modal-footer">
 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
 <input type="submit" class="btn btn-primary" value="作成">
 {!! Form::close() !!}
 </div>
 </div><!-- /.modal-content -->
 </div><!-- /.modal-dialog -->
 </div><!-- /.modal -->
 <div class="form-group">
 <div class="col-sm-10 col-sm-push-2">
 <a href="#" data-toggle='modal' data-target='#item'>項目の追加</a>
 </div>
 </div>
 <div class="modal fade" id="item">
 <div class="modal-dialog">
 {!! Form::open(['url'=>'gathers/detail-create']) !!}
 <div class="modal-content">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
 <h4 class="modal-title alert alert-success">項目の追加</h4>
 </div>
 <div class="modal-body">
 @foreach($items as $item)
 {!! Form::label("detail",$item->name,["class"=>"control-label"]) !!}
 {!! Form::text("detail[$item->id]",'',["class"=>"form-control"]) !!}
 {!! Form::hidden('id',$gather->id) !!}
 @endforeach
 </div>
 <div class="modal-footer">
 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
 <input type="submit" class="btn btn-primary" value="項目追加">
 </div>
 </div><!-- /.modal-content -->
 {!! Form::close() !!}
 </div><!-- /.modal-dialog -->
 </div><!-- /.modal -->
</div>
@endsection

ブラウザで表示してみましょう。

2015-05-30 17-25-38

本日は、以上です。

このエントリーを含むはてなブックマーク Buzzurlにブックマーク livedoorクリップ Yahoo!ブックマークに登録

トラックバック&コメント

この投稿のトラックバックURL:

コメントをどうぞ

このページの先頭へ