LaravelのORMを使って、POST送信されたデータをDBに登録(インサート)する際、1回のPOST送信からデータを複数のカラムに分けて登録する必要がありました。
#状況
例えば
①フォームからこのような送信があったとする
名前 :
好きな食べ物1:
好きな食べ物2:
好きな食べ物3:
好きな食べ物4:
...
これらのキーはこのようになっています
name =>
food1 =>
food2 =>
food3 =>
food4 =>
...
②このデータをDBに保存するのだが、好きな食べ物は何個データが入ってくるかわからないので、「users」テーブルと**「foods」テーブル**を作って
「users」テーブル
id
name
created_at
updated_at
「foods」テーブル
id
name
user_id
created_at
updated_at
と2つのテーブルに分けてデータを保存し、かつ『好きな食べ物』に関しては、1つの食べ物につき1つのデータとして保存した。(後々個人のデータを表示するときのことを考えて外部キーとして「user_id」を設定)
この『1つの食べ物につき1つのデータとして保存』の箇所でエラーを吐いてしまったので、その回避方法を紹介します。
#実装
『好きな食べ物』を保存する**「Food」モデル**を作りました
今回モデルとルーティングの記載は省略します。
フォームから送信されると、DBに保存する処理をコントローラに書きます。
実際に実装した処理はこちら
<?php
...(namespaceとuse省略)
class FoodsContoroller extends Controller
{
public function insert(Request $request)
{
//...ユーザー情報登録は割愛
//送信情報を一つ一つのデータとして保存
foreach ($request->all() as $key => $val){
//送信されたキー($key)に「food」を含むものを判定
if(preg_match('/food/',$key)){
//モデルをインスタンス化
$food = new Food;
//ループさせた$valを入れる
$food->name = $val;
//$user_last_insert_idは、ユーザー登録した時に取ってきたid(外部キー)
$food->user_id = $user_last_insert_id;
$food->save();
}
}
}
}
これで『好きな食べ物』のデータ1つ1つをDBに保存できます
#解説
特に自分が詰まったところを解説します。
foreach ($request->all() as $key => $val){
ループ処理をさせることは分かっていたのですが、「$request」をループさせていてエラーになりました。
「$requestr->all()」
とすることで、フォームから送られてきた「$request」を配列の形にしてforeachでループできます。
if(preg_match('/food/',$key)){
上の処理で「$request」をループで一つ一つ分けましたが、DBの「foodsテーブル」には、「food」のデータのみを保存しなければいけません。
キーが「name」のものは処理したくないので、if文を使って「food」を
含むキー
のみ処理をするようにしました。
「preg_match」 関数の引数にはキーと正規表現を取って、「food」を含むデータのみを抽出しました。
$food = new Food;
LaravelでORMを使ってデータを保存する際には、モデルをインスタンス化する必要がありますが、ループ処理の中でインスタンス化するようにします。
もしループ処理外でインスタンス化してしまった場合、モデルのインスタンスが一つしかないので、データを複数「food」テーブルに登録することができずに、最後に送られてきた『好きな食べ物』しか登録されません。
以上が、Laravelで1回のリクエストを複数のカラムに分けてDBに登録する方法です。