如何使用关联数组更新所有记录?
Posted
技术标签:
【中文标题】如何使用关联数组更新所有记录?【英文标题】:How can i UPDATE all records using associative array? 【发布时间】:2021-06-20 13:42:08 【问题描述】:我有一张包含我的网站设置的表格:
我想使用来自表单的数据一次更新所有记录。 数据如下所示:
$data = [
"brand" => "bbb"
"mail" => "kontakt@aaa.pl"
"phone" => "111"
"site-name" => "test"
];
现在我想用关联数组的键和它的值来更新它。 我试过了:
DB::table('settings')->update($data);
但是有一个错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'brand' in 'field list' (SQL: update `settings` set `brand` = bbb, `mail` = kontakt@aaa.pl, `phone` = 111, `site-name` = test)
显然它认为brand
是一个列名。
所以我将$data
转换为这个数组:
$data = [
0 => [
"name" => "brand"
"value" => "bbb"
]
1 => [
"name" => "mail"
"value" => "kontakt@aaa.pl"
]
2 => [
"name" => "phone"
"value" => "111"
]
3 => [
"name" => "site-name"
"value" => "test"
]
];
现在错误是:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'field list' (SQL: update `settings` set `0` = "name":"brand","value":"bbb", `1` = "name":"mail","value":"kontakt@aaa.pl", `2` = "name":"phone","value":"111", `3` = "name":"site-name","value":"test")
所以现在它认为数组中每一行的索引是列名,在这个地方我不知道该怎么做...... 谁能帮帮我?
【问题讨论】:
我想这个问题在这里已经有了答案:***.com/questions/25674737/…> 你应该清楚你的意图。 【参考方案1】:您可以使用upsert
更新多条记录
首先转换数据以使用集合添加列名
$data=collect($data)->transform(function ($value,$name)
return ["name"=>$name,"value"=>$value];
)->values()->toArray();
这里我使用了模型
Setting::upsert($data,["name"],["value"]);
了解Upserts
Upsert 在单个查询中执行多个“upsert”
第一个参数包含要插入或更新的值
第二个参数列出了在关联表中唯一标识记录的列。
第三个也是最后一个参数是一个列数组,如果数据库中已经存在匹配记录,则应该更新这些列。
同样重要的一点
除 SQL Server 之外的所有数据库系统都需要 提供给 upsert 方法的第二个参数具有“主要”或 “唯一”索引。
这意味着在您的 mysql 表设置列中 name
为 unique index
否则它将作为新行插入
参考:https://laravel.com/docs/8.x/eloquent#upserts
【讨论】:
【参考方案2】:您的表格看起来就像您只能获取一组数据并随时间更新。为什么是因为没有外键关系。
如果是这种情况,那么为什么不在设置列中设置品牌名称、邮件、电话和站点名称,
您的迁移
public function up()
Schema::create('settings', function (Blueprint $table)
$table->string('brand_name');
$table->string('mail');
$table->string('phone');
$table->string('site_name');
$table->timestamps();
);
在你的模型中?
protected $fillable = ['brand_name', 'mail', 'phone', 'site_name'];
或
protected $guarded = [];
在你的控制器中
public function method(Request $request)
// You can also abstract this in to a custom request class
$request->validate([
'brand_name' => 'required',
'mail' => 'required',
'phone' => 'required',
'site_name' => 'required',
]);
// Add data if record doesn't exist, update when it does
// To use the validated method on request all needed fields must be required
Settings::updateOrCreate($request->validated())
万一我错了,你仍然可以查看 Laravel 大规模更新 https://laravel.com/docs/8.x/eloquent#mass-updates
Laravel Upserts https://laravel.com/docs/8.x/eloquent#upserts
【讨论】:
问题是随着时间的推移我计划添加更多设置,这意味着使用您的解决方案会有更多行或更多列。所以我必须坚持行。无论如何感谢您的回答【参考方案3】:我来到了这个解决方案,虽然我认为它看起来很丑,应该有更好的方法来做到这一点,如果没有更好的答案,我会将我的答案标记为正确
$data = [
"brand" => "bbb"
"mail" => "kontakt@aaa.pl"
"phone" => "111"
"site-name" => "test"
];
foreach($data as $key=>$d)
DB::table('settings')->where('name','=',$key)->update(['value' => $d]);
【讨论】:
以上是关于如何使用关联数组更新所有记录?的主要内容,如果未能解决你的问题,请参考以下文章