はじめに
LaravelでOne to Manyの関係を持っているmodelのフォームをForm Model Bindingを使ってきれいに書きたいなと思った次第です。
環境はLaravel5.0で、フォーム作成にはlaravelcollectiveを用いています。
http://laravelcollective.com/
Columnが複数のParagraphを持っているというケースで考えます。
Column hasMany Paragraphs
Paragraph belongsTo Column
実装
controller
createではcolumnとparagraphをnewしてviewに渡してます。
storeではRequestを受け取ってMass Assignmentを使ってColumnとParagraphを保存しています。
ColumnとParagraphを一気にsave出来れば良いのになーと思っていたのですが、自分が調べた限りではOne to Manyの関係の場合は出来ないような感じでした。One to Oneだと出来るっぽいです。
editとupdateは省略しますが、大体似たような感じだと思います(気が向いたら載せます)。
app/Http/Controllers/Columns.php
public function create()
{
$data = [];
$column = new Column;
$paragraphs = array_fill(0, 3, new Paragraph);
$column->paragraphs = $paragraphs;
$data['column'] = $column;
return view('column.create')->with($data);
}
public function store()
{
$column = Column::create(Request::except('paragraphs'));
$paragraphs = [];
$ary_paragraphs = Request::only('paragraphs');
foreach($ary_paragraphs as $i => $ary_paragraph) {
$paragraph = new Paragraph;
$paragraph->fill($ary_paragraph);
$paragraphs[] = $paragraph;
}
$column->paragraphs()->saveMany($paragraphs);
return Redirect::action('Columns@index');
}
view
modelのカラム名をForm::textに渡せばバインディングしてくれます。
resources/views/column/create.blade.php
{!! Form::model($column, array('action' => 'Columns@store')) !!}
<div class="form-group">
{!! Form::label('column_title', 'タイトル:') !!}
{!! Form::text('column_title') !!}
</div>
@foreach ($column->paragraphs as $i => $paragraph)
<div id='paragraph-{{$i}}'>
<div class="form-group">
{!! Form::label('item-' . $i, '見出し' . ($i+1) . ':') !!}
{!! Form::text('paragraphs[' . $i . '][item]', $paragraphs[$i]['item']) !!}
</div>
<div class="form-group">
{!! Form::label('content-' . $i, '本文' . ($i+1) . ':') !!}
{!! Form::textarea('paragraphs[' . $i . '][content]', $paragraphs[$i]['content']) !!}
</div>
</div>
<div class="form-group">
{!! Form::submit('保存') !!}
</div>
@endforeach
{!! Form::close() !!}
もっと良い書き方があれば教えて下さい!