Reputation: 2855
I have a Product
model and also an Attribute
model. The relationship between Product
and Attribute
is many to many. On my Product
model I am trying to create a dynamic accessor. I am familiar with Laravel's accessors and mutators feature as documented here. The problem I am having is that I do not want to create an accessor every time I create a product attribute.
For example, A product may have a color attribute which could be setup like so:
/**
* Get the product's color.
*
* @param string $value
* @return string
*/
public function getColorAttribute($value)
{
foreach ($this->productAttributes as $attribute) {
if ($attribute->code === 'color') {
return $attribute->pivot->value;
}
}
return null;
}
The product's color could then be accessed like so $product->color
.
If I where to add a size
attribute to the product I would need to setup another accessor on the Product
model so I could access that like so $product->size
.
Is there a way I can setup a single "dynamic" accessor to handle all of my attributes when accessed as a property?
Do I need to override Laravel's accessor functionality with my own?
Upvotes: 5
Views: 5995
Reputation: 3129
I think probably Олег Шовкун answer is the right one but if you did want to use the model attribute notation you could get the required argument into the model via a class variable.
class YourModel extends Model{
public $code;
public function getProductAttribute()
{
//a more eloquent way to get the required attribute
if($attribute = $this->productAttributes->filter(function($attribute){
return $attribute->code = $this->code;
})->first()){
return $attribute->pivot->value;
}
return null;
}
}
Then do
$model->code = 'color';
echo $model->product;
But its a bit long and pointless
Upvotes: 0
Reputation: 527
Yes, you can add your own piece of logic into the getAttribute() function of the Eloquent Model class (override it in your model), but in my opinion, it's not a good practice.
Maybe you can have a function:
public function getProductAttr($name)
{
foreach ($this->productAttributes as $attribute) {
if ($attribute->code === $name) {
return $attribute->pivot->value;
}
}
return null;
}
And call it like this:
$model->getProductAttr('color');
Upvotes: 5
Reputation: 755
Override Magic method - __get() method.
Try this.
public function __get($key)
{
foreach ($this->productAttributes as $attribute) {
if ($attribute->code === $key) {
return $attribute->pivot->value;
}
}
return parent::__get($key);
}
Upvotes: 5