Laravel 5.7如何将嵌套数组数据存入数据库
解决Laravel 5.7动态表单字段存入数据库的问题
嘿,我仔细看了你的代码和问题描述,核心问题出在模型批量赋值未配置、循环逻辑错误,还有数据库字段与表单字段的对应关系上。咱们一步步修复:
1. 先搞定模型的批量赋值(必填!)
你注释掉了$fillable,但这是Laravel实现批量赋值的关键——没有它,create()方法或者批量赋值都会被框架拦截。而且要注意数据库字段名和你要赋值的字段完全对应:
你的products表字段是client_id、product_date、product_type、comment_about_product,所以Product模型应该这样写(顺便修正类名大写,符合PHP编码规范):
class Product extends Model { protected $fillable = [ 'client_id', 'product_date', 'product_type', 'comment_about_product', ]; public function client(){ return $this->belongsTo('App\Client'); // Client类名也要大写,统一规范 } }
小提示:Laravel的模型类名和文件名建议首字母大写,比如
Product.php而不是product.php,避免自动加载时出现奇怪的问题。
2. 修正控制器的循环逻辑(解决Undefined index错误)
你第二个写法里的while循环完全多余,而且会导致$i不断递增,超出$products的索引范围(你的$products只有1、2两个键),所以才会报Undefined index。正确的做法是直接遍历$products数组的每一项:
public function storeDYNarray(Request $request) { $clientId = $request->input('client_id'); $products = $request->input('product'); // 遍历每个商品的表单数据 foreach ($products as $productData) { // 重点:字段要和数据库、表单一一对应! Product::create([ 'client_id' => $clientId, 'product_date' => $productData['date'], // 表单里的date对应数据库的product_date 'product_type' => $productData['type'], // 表单里的type对应数据库的product_type 'comment_about_product' => $productData['comment'], // 表单里的comment对应数据库的comment_about_product ]); } // 更优雅的写法:用关联关系创建(推荐) // $client = Client::findOrFail($clientId); // foreach ($products as $productData) { // $client->products()->create([ // 'product_date' => $productData['date'], // 'product_type' => $productData['type'], // 'comment_about_product' => $productData['comment'], // ]); // } return redirect()->back()->with('success', '所有商品记录已保存成功!'); }
解释下:
- 去掉了多余的
$i和while循环,直接遍历$products中的每个商品数组 - 使用
Product::create()代替手动实例化+save(),更简洁,且依赖$fillable字段 - 注意数据库字段名是
comment_about_product,而你表单传的是comment,这是之前字段存不上的关键原因之一!
3. 确认表单字段命名(确保请求数据正确)
从你的dd($all)输出看,表单字段命名是对的,应该是类似这样的动态结构:
<!-- 第一个商品 --> <input type="date" name="product[1][date]"> <input type="text" name="product[1][type]"> <textarea name="product[1][comment]"></textarea> <!-- 第二个商品 --> <input type="date" name="product[2][date]"> <input type="text" name="product[2][type]"> <textarea name="product[2][comment]"></textarea>
这部分没问题,不用改。
4. 额外优化建议
- 添加表单验证:避免无效数据存入数据库,比如在控制器开头加:
$request->validate([ 'client_id' => 'required|exists:clients,client_id', // 确保client_id存在于clients表 'product.*.date' => 'required|date', 'product.*.type' => 'required|string', 'product.*.comment' => 'nullable|string', ]);
- 修正Client模型类名:把
client改成Client,文件名对应Client.php,符合规范 - 使用事务:如果要确保所有商品要么都保存成功,要么都失败,可以加事务:
DB::transaction(function () use ($clientId, $products) { foreach ($products as $productData) { Product::create([ 'client_id' => $clientId, 'product_date' => $productData['date'], 'product_type' => $productData['type'], 'comment_about_product' => $productData['comment'], ]); } });
按照上面的修改,你的代码应该就能正常把动态表单的字段存入数据库,而且不会再出现Undefined index错误了。
内容的提问来源于stack exchange,提问作者user9643672
相关产品推荐
相关产品推荐

