要件
一つのページで1:Nの親子関係にある入力項目がある。
これをsubmitしてサーバ側にPOSTする。ただしNは可変で、1であったり8であったりする。
サーバ側のロジックを簡潔にするために、例えば以下のようなオブジェクトをコントローラ側で取得したい。
{
company_name:会社名
company_sections:[
{
section_name:部署1
},
{
section_name:部署2
},
]
}
解答
以下のようなname指定にしてformで括ってsubmitすればOK。
コントローラの$request->post()で先述のオブジェクトが取得できる。
<input type="text" name="company_name" value="会社名"></div>
<input type="text" name="company_sections[0][section_name]" value="部署1"></div>
<input type="text" name="company_sections[1][section_name]" value="部署2"></div>
PHPは内部的には配列と連想配列の区別がない(全て連想配列)ので、
company_sections[0]の指定でcompany_sectionsはキー0を持つ。
company_sections[0]のキーsection_nameの値は部署1。
として解釈されるのだろう。
他言語・フレームワークで同じことをするとどうなるかは今の所不明。
補足
バリデーションのかけ方
Laravel 配列で渡されたリクエストデータにバリデーションをかける
以下のような指定が可能。
'company_sections.0.section_name' => ''
バリデーションエラーで前画面に戻った際にまとめて前回入力値をセットする
JS作りました。連想配列のキーと同名のHTML要素が連想配列のvalueを返すようにHTMLを編集する.
のset-old-input.blade.phpを@include
すればマッピングされます。
配列の数が不明な場合
バリデーションをコントローラー内でループで回すしか無いかなと思っています。
より良い解法があればコメント頂けると助かります。
$company_data = $request->post();
$company_validator = Validator::make($company_data , ['company_name'=>'required']);
if (!$company_validator ->passes()) {
return $company_validator;//会社単位でバリデーションをかけて検証NGならこの時点で返す
}
$sections_data = $company_data ['company_sections'];
foreach($sections_data as $section_data){
$section_validator = Validator::make($section_data, ['section_name'=>'required']);
if (!$section_validator ->passes()) {
return $office_validator;//部署単位でバリデーションをかけて検証NGならこの時点で返す
}
}
※まとめてバリデーションを全てにかけてエラーメッセージを結合したいケースが多い気もしますがここでは省略。
その他同様の問題への解決策
【JavaScript】「formをjsonにしてpost」する。
チェックボックス、ラジオボタンなどの対応などが気にかかったが、サーバー側の挙動に依らない一般的な解決策。
nameが冗長にならないのも利点。