如何同步 Laravel 中同一属性的多个值?
How to sync multiple values of the same Attribute in Laravel?
我正在使用 Laravel 5.4 开发一个电子商务(具有多个产品属性功能)网站。一切正常。但是,当我尝试在 Pivot table 中同步同一属性的多个值时。 Laravel 忽略重复的 pares。例如,我有一个名为 "Network" 的属性,它有 3 个值:2G、3G、4G。手机支持3G和4G网络。我想在数据库中同步 3G 和 4G 值。 Laravel 忽略其中之一。
Products Table:
ID - Product Name
1 - Test Mobile
Attributes Table
ID - AttributeName
1 - Network
AttributeValues Table
ID - AttributeID - AttributeValue
1 - 1 - 2G
2 - 1 - 3G
3 - 1 - 4G
ProductAttributes Table
ID - AttributeID - ProductID - AttributeValue
1 - 1 - 1 - 3G
1 - 1 - 1 - 4G
我想将产品属性存储在 "ProductAttributes" table 类似的东西中。但是Laravel忽略其中一个。
我正在这样保存数据:
$product = Product::create([
'name' => 'Test Mobile'
]);
$product->attributes()->sync([
1 => ['AttributeValue' => '3G'],
1 => ['AttributeValue' => '4G']
]);
有什么建议、想法吗?
sync()
Laravel 中的函数自动读取重复项。你可以用
强制它
$product->attribute()->syncWithoutDetaching([
1 => ['AttributeValue' => '3G'],
1 => ['AttributeValue' => '4G']
]);
祝你好运!
使用同步方法store/update控制器中的数据使用关系:
$product-> attribute()->sync($request->input('product_ids', []));
我知道这已经晚了两年,但我今天正在处理同样的问题,我想我可以把解决方案留在这里,以防将来有人寻找它。如果您使用原始代码:
$product->attributes()->sync([
1 => ['AttributeValue' => '3G'],
1 => ['AttributeValue' => '4G']
]);
数组中的第二项会覆盖第一项,所以最终数据库中只会有一个“4G”条目。这不是真正的 laravel 问题,而是 PHP 关联数组的实现方式 - 数组中的两个项目基本上不能位于同一索引上。
实际上有两种方法可以解决这个问题
1) 第一个效率很低,但是很实用。我把它留在这里只是为了记录,因为那是我解决问题的最初方式。而不是你的代码,你需要这样的东西
$product->attributes()->sync([]); // empty relation completely
// add first item
$product->attributes()->syncWithoutDetaching([
1 => ['AttributeValue' => '3G'],
]);
// add second item without detaching the first one
$product->attributes()->syncWithoutDetaching([
1 => ['AttributeValue' => '4G'],
]);
这是非常低效的,因为它需要一个查询来从关系中删除所有现有数据,然后一项一项地添加新项。您还可以 运行 循环内的 syncWithoutDetaching
,整体效率低下很大程度上取决于您需要同步的项目数量。
2) 第一个解决方案不够好,所以我不断地挖掘和试验,想出了一个方法来实现这个目标。您可以发送没有给定特定索引的数组,并将 ID 放在数组本身中,而不是将您的项目放在数组中的特定索引上。像这样
$product->attributes()->sync([
['AttributeID' => 1, 'AttributeValue' => '3G'],
['AttributeID' => 1, 'AttributeValue' => '4G']
]);
通过这种方式,您实际上可以将具有相同 AttributeID
的两个项目发送到 sync() 方法,而不会一个覆盖另一个
查看 Becquerel 4 月 5 日的回复,回复 #2,并阅读 /laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
中 sync()
方法的源代码(我认为,这是 Laravel 2.4) ,我没有看到 (或者,无法识别) 支持此 "array of array" 功能的代码。事实上,这里是整个方法的源代码:
public function sync($ids, $detaching = true)
{
$changes = [
'attached' => [], 'detached' => [], 'updated' => [],
];
if ($ids instanceof Collection) {
$ids = $ids->modelKeys();
}
// First we need to attach any of the associated models that are not currently
// in this joining table. We'll spin through the given IDs, checking to see
// if they exist in the array of current ones, and if not we will insert.
$current = $this->newPivotQuery()->pluck($this->otherKey);
$records = $this->formatSyncList($ids);
$detach = array_diff($current, array_keys($records));
// Next, we will take the differences of the currents and given IDs and detach
// all of the entities that exist in the "current" array but are not in the
// the array of the IDs given to the method which will complete the sync.
if ($detaching && count($detach) > 0) {
$this->detach($detach);
$changes['detached'] = (array) array_map(function ($v) {
return is_numeric($v) ? (int) $v : (string) $v;
}, $detach);
}
// Now we are finally ready to attach the new records. Note that we'll disable
// touching until after the entire operation is complete so we don't fire a
// ton of touch operations until we are totally done syncing the records.
$changes = array_merge(
$changes, $this->attachNew($records, $current, false)
);
if (count($changes['attached']) || count($changes['updated'])) {
$this->touchIfTouching();
}
return $changes;
}
现在,Laravel 充满了依赖注入和其他 Magick(显然类似于 Perl 的 "map?" 概念),但我在这里看不到任何东西可以实现 Becquerel 所说的将要。而且,一般来说,Laravel 的文档真的不会出来说明它 对 对多对多关系中的重复值做了什么,或者如果它是完全认识他们。
我还注意到,上面显示的方法的实现实际上与他引用的 "alternative #1" 非常相似 "extremely inefficient." 似乎将键分为三个桶......从来没有似乎允许重复,通过我的阅读……然后根据需要执行插入、更新和删除操作。 (没有 SQL "transactions" 我能看到的任何地方,这也让我非常惊讶......他们 "magickally" 不知何故在那里吗?)
我根本无法确定 Laravel,当在 (相关记录集) 中多次出现一个值时 =43=],像 return 那样把它们作为一个数组做任何有意义的事情。
我做了这个冗长的回复,希望能引起更多的评论。谢谢
目前,
$product->attributes()->sync([]);
$product->attributes()->sync([
['AttributeID' => 1, 'AttributeValue' => '3G'],
['AttributeID' => 1, 'AttributeValue' => '4G']
]);
我正在使用 Laravel 5.4 开发一个电子商务(具有多个产品属性功能)网站。一切正常。但是,当我尝试在 Pivot table 中同步同一属性的多个值时。 Laravel 忽略重复的 pares。例如,我有一个名为 "Network" 的属性,它有 3 个值:2G、3G、4G。手机支持3G和4G网络。我想在数据库中同步 3G 和 4G 值。 Laravel 忽略其中之一。
Products Table:
ID - Product Name
1 - Test Mobile
Attributes Table
ID - AttributeName
1 - Network
AttributeValues Table
ID - AttributeID - AttributeValue
1 - 1 - 2G
2 - 1 - 3G
3 - 1 - 4G
ProductAttributes Table
ID - AttributeID - ProductID - AttributeValue
1 - 1 - 1 - 3G
1 - 1 - 1 - 4G
我想将产品属性存储在 "ProductAttributes" table 类似的东西中。但是Laravel忽略其中一个。
我正在这样保存数据:
$product = Product::create([
'name' => 'Test Mobile'
]);
$product->attributes()->sync([
1 => ['AttributeValue' => '3G'],
1 => ['AttributeValue' => '4G']
]);
有什么建议、想法吗?
sync()
Laravel 中的函数自动读取重复项。你可以用
$product->attribute()->syncWithoutDetaching([
1 => ['AttributeValue' => '3G'],
1 => ['AttributeValue' => '4G']
]);
祝你好运!
使用同步方法store/update控制器中的数据使用关系:
$product-> attribute()->sync($request->input('product_ids', []));
我知道这已经晚了两年,但我今天正在处理同样的问题,我想我可以把解决方案留在这里,以防将来有人寻找它。如果您使用原始代码:
$product->attributes()->sync([
1 => ['AttributeValue' => '3G'],
1 => ['AttributeValue' => '4G']
]);
数组中的第二项会覆盖第一项,所以最终数据库中只会有一个“4G”条目。这不是真正的 laravel 问题,而是 PHP 关联数组的实现方式 - 数组中的两个项目基本上不能位于同一索引上。
实际上有两种方法可以解决这个问题
1) 第一个效率很低,但是很实用。我把它留在这里只是为了记录,因为那是我解决问题的最初方式。而不是你的代码,你需要这样的东西
$product->attributes()->sync([]); // empty relation completely
// add first item
$product->attributes()->syncWithoutDetaching([
1 => ['AttributeValue' => '3G'],
]);
// add second item without detaching the first one
$product->attributes()->syncWithoutDetaching([
1 => ['AttributeValue' => '4G'],
]);
这是非常低效的,因为它需要一个查询来从关系中删除所有现有数据,然后一项一项地添加新项。您还可以 运行 循环内的 syncWithoutDetaching
,整体效率低下很大程度上取决于您需要同步的项目数量。
2) 第一个解决方案不够好,所以我不断地挖掘和试验,想出了一个方法来实现这个目标。您可以发送没有给定特定索引的数组,并将 ID 放在数组本身中,而不是将您的项目放在数组中的特定索引上。像这样
$product->attributes()->sync([
['AttributeID' => 1, 'AttributeValue' => '3G'],
['AttributeID' => 1, 'AttributeValue' => '4G']
]);
通过这种方式,您实际上可以将具有相同 AttributeID
的两个项目发送到 sync() 方法,而不会一个覆盖另一个
查看 Becquerel 4 月 5 日的回复,回复 #2,并阅读 /laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
中 sync()
方法的源代码(我认为,这是 Laravel 2.4) ,我没有看到 (或者,无法识别) 支持此 "array of array" 功能的代码。事实上,这里是整个方法的源代码:
public function sync($ids, $detaching = true)
{
$changes = [
'attached' => [], 'detached' => [], 'updated' => [],
];
if ($ids instanceof Collection) {
$ids = $ids->modelKeys();
}
// First we need to attach any of the associated models that are not currently
// in this joining table. We'll spin through the given IDs, checking to see
// if they exist in the array of current ones, and if not we will insert.
$current = $this->newPivotQuery()->pluck($this->otherKey);
$records = $this->formatSyncList($ids);
$detach = array_diff($current, array_keys($records));
// Next, we will take the differences of the currents and given IDs and detach
// all of the entities that exist in the "current" array but are not in the
// the array of the IDs given to the method which will complete the sync.
if ($detaching && count($detach) > 0) {
$this->detach($detach);
$changes['detached'] = (array) array_map(function ($v) {
return is_numeric($v) ? (int) $v : (string) $v;
}, $detach);
}
// Now we are finally ready to attach the new records. Note that we'll disable
// touching until after the entire operation is complete so we don't fire a
// ton of touch operations until we are totally done syncing the records.
$changes = array_merge(
$changes, $this->attachNew($records, $current, false)
);
if (count($changes['attached']) || count($changes['updated'])) {
$this->touchIfTouching();
}
return $changes;
}
现在,Laravel 充满了依赖注入和其他 Magick(显然类似于 Perl 的 "map?" 概念),但我在这里看不到任何东西可以实现 Becquerel 所说的将要。而且,一般来说,Laravel 的文档真的不会出来说明它 对 对多对多关系中的重复值做了什么,或者如果它是完全认识他们。
我还注意到,上面显示的方法的实现实际上与他引用的 "alternative #1" 非常相似 "extremely inefficient." 似乎将键分为三个桶......从来没有似乎允许重复,通过我的阅读……然后根据需要执行插入、更新和删除操作。 (没有 SQL "transactions" 我能看到的任何地方,这也让我非常惊讶......他们 "magickally" 不知何故在那里吗?)
我根本无法确定 Laravel,当在 (相关记录集) 中多次出现一个值时 =43=],像 return 那样把它们作为一个数组做任何有意义的事情。
我做了这个冗长的回复,希望能引起更多的评论。谢谢
目前,
$product->attributes()->sync([]);
$product->attributes()->sync([
['AttributeID' => 1, 'AttributeValue' => '3G'],
['AttributeID' => 1, 'AttributeValue' => '4G']
]);