Edited at

Laravelで1回のリクエストを複数のカラムに分けてDBに登録する方法

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に保存する処理をコントローラに書きます。

実際に実装した処理はこちら


FoodsContoroller.php

<?php

...(namespaceとuse省略)

class FoodsContoroller extends Controller
{
public function insertRequest $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に登録する方法です。