I have a table that contains foreign keys of product properties and their values.
product_id | feature_id | value_id |
---|---|---|
1 | 1 | 2 |
1 | 1 | 3 |
1 | 2 | 4 |
How to get a collection of that values using Eloquent?
Something like this
product => [
id => 1,
...
features => Collection: [
Feature: [
id => 1,
name => Size,
values => [
Value: [
id => 2,
name => M
],
Value: [
id: 3,
name: L
]
]
],
Feature: [
id => 2,
name => Color,
values => [
Value: [
id => 4,
name => Red
]
]
]
]
]
This is my solution.
class Product extends Model
{
protected $appends = ['features'];
protected array $features;
protected bool $featuresAppend = false;
public function getFeaturesAttribute(): Collection
{
if ($this->featuresAppend === false) {
$this->appendFeatures();
}
return collect($this->features);
}
public function productFeatures(): BelongsToMany
{
return $this->belongsToMany(Feature::class, 'product_features');
}
public function productFeatureValues(): BelongsToMany
{
return $this->belongsToMany(
FeatureValue::class,
'product_features',
'product_id',
'value_id'
);
}
protected function appendFeatures(): void
{
// Get futures and values by relationships
$features = $this->productFeatures()->get()->keyBy('id');
$values = $this->productFeatureValues()->get()->keyBy('id');
// Create features-values structure
$features->each(
function ($f) {
$this->features[$f->id] = new StdClass();
$this->features[$f->id]->feature = $f;
}
);
// Appends values to future
$values->each(
function ($v) {
if (array_key_exists($v->feature_id, $this->features)) {
$this->features[$v->feature_id]->values[$v->id] = $v;
}
}
);
$this->featuresAppend = true;
}
}
I’m looking for a better solution to this problem or a solution using native Laravel features.
Source: Laravel