スロットルキットType1 インナー巻取径Φ32 ホルダーカラー:ブラック ワイヤー:ステンレス金具 ACTIVE(アクティブ) CBR1000RR(04~11年)

You are here
Home > !Laravel > バリデーション (8) 配列をバリデーションする

バリデーション (8) 配列をバリデーションする

by ymikome - 0

laravel 5.2 で、バリデーションルールに配列を表す .* というプレースホルダーが使えるようになりました。

例えば 、次のような商品オプションのバリデーションを考えます。

入力行の追加UIやドラッグ&ドロップによるソートはjQueryなどで実装することにします(laravel から離れるので解説は省きます)

この場合、項目数がいくつになるかわからないので、エレメントの属性名を name="option_name[{{$id}}]" などとし、配列を返すように作りますよね。

リクエストは次のようなものになるでしょう。配列のキーは編集データに依存しますので不定です(ここでは仮に 11, 12, 13 としました)

Array
(
 [option_id] => Array
 (
 [11] => Y
 [12] => Y
 [13] => Y
 )
 [option_name] => Array
 (
 [11] => ホワイト
 [12] => ブラック
 [13] => オレンジ
 )
 [unit_price] => Array
 (
 [11] => 1000
 [12] => 1200
 [13] => 980
 )
 [inventory] => Array
 (
 [11] => 30
 [12] => 20
 [13] => 15
 )
)

最低必要なバリデーションとしては、「保存」が少なくとも1つチェックされることと、「保存」がチェックされた行は必須入力となること

タントカスタム LA600S STREET FLEX S2000 AP1/AP2 TYPE FLEX DAMPER マウント付 AP2 18インチセルシオ20系HOT STUFF クロススピード XM ブラックポリッシュ 7.5Jx18ADVAN dB V551 245/45R18 送料無料 HONDA ホンダ STEPWGN ステップワゴン ホンダ純正 コーナーポール ステップ ワゴンスパーダ用 [2016.1~次モデル][ 08V62-TAA-B00 ] ライフ JB7 ボンネットダンパー ブラックカーボン HOT STUFF CROSS SPEED XM 4.5J-15 と NANKANG ROLLNEX N-889 MUDSTAR 165/60R15の4本セット MLJ WREST COMPAK MR 5.0J-16 と TOYO TRANPATH LuK 165/45R16 の4本セット

スロットルキットType1 インナー巻取径Φ32 ホルダーカラー:ブラック ワイヤー:ステンレス金具 ACTIVE(アクティブ) CBR1000RR(04~11年) 送料無料 HONDA ホンダ NBOX エヌボックス ホンダ純正 シフトノブ LEDイルミネーション付 【対応年式2013.12~次モデル】 RB3/RB4オデッセイスクエア4本出しマフラー i-magic ハイパフォーマンスHIDシステム キット 24V シングル 4600K(ケルビン)【smtb-f】 フューエルポンプ 三菱 三菱 CP9A CE9A CN9A 4G63 容量255L/h 燃料ポンプ 【新品 汎用 エンジン 安定 セット 交換 高出力化 フィルター 大容量 ヒューエルポンプ】 14インチモコMG33系WEDS ジョーカー ショット シルバー 4.5Jx14ヨコハマ エコス ES31 155/65R14

CRIMSON(クリムソン) CLUB LINEA L612 (クラブリネア L612) 19インチ 7.5J PCD:114.3 穴数:5 inset:40 DISK TYPE:LOW カラー:ブラックサイドマシニング [ホイール1本単位]/H [ESM-1294] ESPELIR / スーパーダウンサス マツダ アテンザワゴン GJEFW H24/11~ PE-VPR 確認事項有 RS★R(RSR) ダウンサス Ti2000 1台分 ムーヴ(L910S) 4WD 660 TB / RS☆R RS-R シーエー産商 ヌーボーコンソール サイズW-190 A-228 BK【05P03Dec16】 DIXCEL Mタイプ フロント用■エテルナ 1800 89/10~92/3 E35A【ディクセル ブレーキパッド】F 341 086

【メーカー直送品】無限 サイドスポイラー GE8・9,GP1 プレミアムイエロー FIT RS 1010~ 70219-XLFD-K0S0-PY 4527377191507 純正アクセサリー マツダ CX-3 DK H27.02~ マツダスピード サイドアンダースカート ブライトシルバー QDK151P10S4 【送料無料】 175/65R14 14インチ WATANABE ワタナベ New RS8 6J 6.00-14 DUNLOP ダンロップ ルマン V(ファイブ) サマータイヤ ホイール4本セット 17インチインプレッサGE系 アネシス 17インチ装着車HOT STUFF クロススピード プレミアムRS-10 ピアノブラック/サイドマシニング 7.0Jx17エコピア PZ-X 205/50R17

17インチヴォクシー80系 5ナンバーWEDS レオニス NAVIA 05 マットブラック/リムポリッシュ 6.5Jx17エナセーブ RV504 205/50R17 CRIMSON(クリムソン) CLUB LINEA L566 KING LABEL (クラブリネア L566 キングレーベル) 24インチ 9.5J PCD:130 穴数:5 inset:49 DISK TYPE:HIGH カラー:シルバーポリッシュ [ホイール1本単位]/H カロ/KARO フロアマット FLAXY 品番:859 カラー:ブリリアントグレー他 トヨタ マーク2クオリス MCV2#W,SXV2#W FF フットレスト:有 1997年04月~2001年12月

トヨタ 新型ヴェルファイア 30系 フロアマット+ラゲッジマット+ステップマット ハイブリッド対応 【ESスタンダード】 VELLFIRE シエンタ170系 2WD/4WD/HV車 専用  送料無料 プレミアム カーマット フロアーマット クルマ 内装 車マット 自動車マット 車用品 自動車 車

326パワー シルビア S14 LS3.26 リアバンパー

、そして「販売単価」と「在庫数」の数値判定です。

苦労していた配列のバリデーションですが、5.2 からは次のようなルール定義が可能になったのです。

$rules = [
 'option_id' => 'required',
 'option_name.*' => 'required_with:option_id.*',
 'unit_price.*' => 'required_with:option_id.*|integer|min:0',
 'inventory.*' => 'required_with:option_id.*|integer|min:0',
];
$messages = [
 'option_id.required' => '保存するレコードを少なくとも1つ選択してください',
];

「オプション名」、

ブルーレンズ ドアミラースタンダードビュータイプニッサン フェアレディZ Z33 [スウェッジライン] ブレーキホース マークIIクオリス / カムリグラシア MCV20W MCV21W SXV20W 2WD スチール/クリア ※代引不可 ※本州・北海道は送料無料 沖縄・離島は送料別途 【H3991】 Artina アルティナ【ZE2 前期 インサイト】 [L/LSグレード]ロイヤルカスタムシートカバー(1台分) ダイヤキルト Clazzio/クラッツィオ CLAZZIO Giacca(ジャッカ) ランドクルーザー/UZJ100W H12/4~H19/8 パワーシート 8人乗 カラーブラック【14ETC0257K】 データシステム テレビ&ナビキット 切替タイプ HTN-36 JAN:4986651170063 ホンダ MDX YD1 2003年03月~2006年06月 パワープラグコード カローラレビン AE92 ブルーポイント 品番:2165-40 クラッチレリーズベアリング コンドル KC-MK120 用 70409 UDトラックス UD

スロットルキットType1 インナー巻取径Φ32 ホルダーカラー:ブラック ワイヤー:ステンレス金具 ACTIVE(アクティブ) CBR1000RR(04~11年) クスコ メタルディスク クラッチセット MR2 AW11(NA) 4A-GE 84/6~85/5 【ポイント2倍!・全国送料無料】BLITZ(ブリッツ) ADVANCE POWER AIR CLEANER(アドバンスパワーエアクリーナー) コペン LA400K 42225 国内優良メーカー各社 リビルトドライブシャフト 助手席側 トヨタ/TOYOTA ランドクルーザー KDJ125W 2002年10月~ 3000cc DIXCEL ディクセル エクストラクルーズタイプ フロント左右セット スズキ アルトラパン HE21S 05/01~ [ブレーキパッド] EC371082 DIXCEL ディクセル エクストラクルーズタイプ リア左右セット 三菱 エテルナ E64A 93/9~94/8 [ブレーキパッド] EC345048

DIXCEL/ディクセル ブレーキローター SD フロント  BMW F30  328i 12/01~ 3A20 SD1214947S ストライカー ストリートコンセプト フルエキゾースト マフラー ZRX1200 DAEG 4-2-1 STD チタン Mk3(チタンミラーフィニッシュサイレンサー仕様) 政府認証JMCA 941013M3-M TYPE-N(アルミニウム)鍛造ホイール ブラックメタリック R550-17 GALE SPEED(ゲイルスピード) GSX-R1100 '90~'92 【最大500円OFFクーポン付】グロンドマン バイク シートカバー ヤマハ YAMAHA スベラーヌレッド/白パイピング 張替 ビーノ[SA26/37] GH45YC440P20 HBメッセンジャーサイドバッグ ブラック Mサイズ [76276]

【メーカー在庫あり】 LSSP150M12 451-0542 (株)弥満和製作所 ヤマワ ニューロングスパイラルタップ TRUSCO トラスコ中山 工業用品 大見 G型ホールカッター 44mm 【メーカー在庫あり】 39942 451-5030 Ridge Tool Compan RIDGE クィックアクション・チューブカッター 151ーJ 【USA在庫あり】 56-2729 EPILK131 クワッドボス(QUADBOSS) リフトキット

5EA-11181-00 ヤマハ純正 ガスケット シリンダーヘッド1 57001-1835 カワサキ純正 トツププラグレーンチ37MM オグショー OGUshow トランポ用品 スーパーロングワイドボディ 防虫ネット リアゲート Wファスナー NISSAN NV350キャラバン

【USA在庫あり】 DS-174287 11190 ジェームズ JAMES アッパー プッシュロッド チューブ Oリング 91年-03年 XL 25個入り 11190 S&S CYCLE エスアンドエス サイクル ジェット類 S&S メインジェット.078 【.078 MAIN JET S&S [DS-72078]】

、「販売単価」、「在庫数」のルール定義には属性名に .* を加えることで、配列の値それぞれにバリデーションが適用されるようになります。

「保存」がチェックされた行だけ入力が必要なので、required_with の引数も option_id.* となります。一方で「保存」の必須チェックは配列全体の required です。

配列部分のエラーは array_dot() による配列ドット記法で返ってきますので、Bladeテンプレートのエラーメッセージ表示は次のような書き方になります。

{{ $errors->first("unit_price.$id") }}

 

laravel 4 や 5.1 以前での配列バリデーション

後出しジャンケンでの自慢話となってしまいますが、私たちのプロジェクトでは lavavel 4 のころから配列に対するバリデーションを、5.2 と同じルールの書き方で処理してきました。

もともと laravel のバリデーションでは、リクエストは配列のまま処理されるでのはなく、array_dot によるドット記法の一次元データに変換されて内部処理されていました。

例えば次のように、配列のキーが固定されてる入力フォームの場合ならば、

<input type="text" name="name[last]" value="{{ old('name.last') }}">
<input type="text" name="name[first]" value="{{ old('name.first') }}">
Array
(
 [name] => Array
 (
 [last] => 山田
 [first] => 太郎
 )
)

以下のようにドット記法でルールを定義することで、配列データもバリデーションできたのです。

$rules = [
 'name.last' => 'required',
 'name.first' => 'required',
];

 

最初に、「5.2 で .* というプレースホルダーに対応した」と書き、配列バリデーションそのものに対応したと書かなかった意味がここにあります。
このプレースホルダーの変換を自分で対応すれば、5.1 以前や 4 でも同様の処理ができるわけです。

定義するルール:

$rules = [
 'option_id' => 'required',
 'option_name.*' => 'required_with:option_id.*',
 'unit_price.*' => 'required_with:option_id.*|integer|min:0',
 'inventory.*' => 'required_with:option_id.*|integer|min:0',
];

変換後のルール:

$rules = [
 'option_id' => 'required',
 'option_name.11' => 'required_with:option_id.11',
 'option_name.12' => 'required_with:option_id.12',
 'option_name.13' => 'required_with:option_id.13',
 'unit_price.11' => 'required_with:option_id.11|integer|min:0',
 'unit_price.12' => 'required_with:option_id.12|integer|min:0',
 'unit_price.13' => 'required_with:option_id.13|integer|min:0',
 'inventory.11' => 'required_with:option_id.11|integer|min:0',
 'inventory.12' => 'required_with:option_id.12|integer|min:0',
 'inventory.13' => 'required_with:option_id.13|integer|min:0',
];

この変換は次のような関数で対応できます。ベースコントローラかトレイトに入れて、バリデーション直前にルールの変換を挿入してみてください。

/**
 * 配列バリデーションルールの変換
 * @param \Illuminate\Http\Request $request
 * @param array $rules
 * @param array $messages
 */
public static function setArrayRules($request, &$rules, &$messages)
{
 foreach($rules as $field => $rule)
 {
 // field文字列は foo.* か?
 if (!preg_match('/^(.+)\.\\*$/', $field, $m)) continue;
 // fooはリクエストに存在して配列か?
 $name = $m[1];
 if (!($req = $request->get($name)) || !is_array($req)) continue;
 foreach(array_keys($req) as $i)
 {
 // rulesに foo.$i を複写
 $rules["$name.$i"] = str_replace('*', $i, $rule);
 // messagesにfoo.$i.barがあれば複写
 foreach($messages as $key => $message)
 {
 if (!preg_match("/^$name\.\\*\.(.+)$/", $key, $m)) continue;
 $messages["$name.$i.{$m[1]}"] = $message;
 }
 }
 unset($rules[$field]);
 }
}

 

p.s.

上で紹介した setArrayRules() では、、、次のような配列の記述には対応してません。もし必要とするならばご自身で考えてみてくださいね。

Bladeソース:

<input type="text" name="option[{{$id}}][name]" value="old("opton.$id.name")">

バリデーションルール:

 'option.*.name' => 'required_with:option_id.*',

スロットルキットType1 インナー巻取径Φ32 ホルダーカラー:ブラック ワイヤー:ステンレス金具 ACTIVE(アクティブ) CBR1000RR(04~11年)激旬アイテム続々入荷

Top
{yahoojp}nc02-myp03-wl-2224 、