In my application I'm using a many to many relationship between an SKU model and an Attributes model. So the pivot table per default is structured with two cols, namely sku_id and attribute_id. I added an extra field to the pivot table holding a value for a specific combination of sku/attribute.
Schematically it looks like the follwing:
attribute_id | sku_id | value
1 1 red
2 1 xs
3 1 v-neck
4 1 linen
1 2 red
2 2 xs
3 2 v-neck
4 2 silk
1 3 red
2 3 xs
3 3 v-neck
4 3 cotton
Problem: In the front end I want to display the values grouped by the attributes and then display the unique values. So coresponding data for the above mentioned rows would be
attribute_id 1 ==> red
attribute_id 2 ==> xs
attribute_id 3 ==> v-neck
attribute_id 4 ==> linen + silk + cotton
As one can guess it is about product variants in an ecommerce system.
Overall an example product consists out of 144 skus (4 colors, 6 sizes, 2 collars, 3 materials). So coresponding data for the full example would be
attribute_id 1 ==> red + yellow + green + blue
attribute_id 2 ==> xs + s + m + l + xl + xxl
attribute_id 3 ==> v-neck + round
attribute_id 4 ==> linen + silk + cotton
My SKU model look slike
public function attributes(){
return $this->belongsToMany(Attribute::class, 'attribute_sku', 'sku_id', 'attribute_id')->withPivot('value');
}
I already read the laravel documentation regarding pluck, filter, map and many more eloquent methods. However, I didnt find any hints.
Can anyone point me in the right direction (eg. laravel docs, tutorial, stackoverflow)
You can use laravel collections mapToGroups for desired result
I created a sample collection to check
$collection = collect([
['attribute_id' => 1, 'sku_id' => 1, 'value' => 'red'],
['attribute_id' => 2, 'sku_id' => 1, 'value' => 'xs'],
['attribute_id' => 3, 'sku_id' => 1, 'value' => 'v-neck'],
['attribute_id' => 4, 'sku_id' => 1, 'value' => 'linen'],
['attribute_id' => 1, 'sku_id' => 2, 'value' => 'red'],
['attribute_id' => 2, 'sku_id' => 2, 'value' => 'xs'],
['attribute_id' => 3, 'sku_id' => 2, 'value' => 'v-neck'],
['attribute_id' => 4, 'sku_id' => 2, 'value' => 'silk'],
['attribute_id' => 1, 'sku_id' => 3, 'value' => 'red'],
['attribute_id' => 2, 'sku_id' => 3, 'value' => 'xs'],
['attribute_id' => 3, 'sku_id' => 3, 'value' => 'v-neck'],
['attribute_id' => 4, 'sku_id' => 3, 'value' => 'cotton'],
]);
$grouped = $collection->mapToGroups(function (array $item) {
return [$item['attribute_id'] => $item['value']];
})->map->unique()->toArray();
dd($grouped);
see result below
You can use:
$productAttributes = $product->attributes->mapToGroups(function ($item) {
return [$item->attribute_id => $item->pivot->value];
})->map->unique()->toArray();