Создание динамического средства доступа Laravel
У меня есть модель Product
, а также модель Attribute
. Связь между Product
и Attribute
- это много ко многим. В моей модели Product
я пытаюсь создать динамический способ доступа. Я знаком с функциями доступа и мутаторов Laravel, описанными в документе здесь. Проблема, с которой я сталкиваюсь, заключается в том, что я не хочу создавать средство доступа каждый раз, когда я создаю атрибут продукта.
Например, у продукта может быть атрибут цвета, который можно настроить следующим образом:
/**
* 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;
}
В затем можно было бы получить доступ к цвету продукта следующим образом $product->color
.
Если бы я хотел добавить атрибут size
к продукту, мне нужно было бы настроить другой способ доступа к модели Product
, чтобы я мог получить к нему доступ вот так $product->size
.
Есть ли способ настроить один "динамический" способ доступа для обработки всех моих атрибутов при доступе в качестве свойства?
Нужно ли мне переопределять функции доступа Laravel своими собственными?
3 answers
Да, вы можете добавить свою собственную часть логики в функцию getAttribute() класса модели Eloquent (переопределите ее в своей модели), но, на мой взгляд, это не очень хорошая практика.
Может быть, у вас может быть функция:
public function getProductAttr($name)
{
foreach ($this->productAttributes as $attribute) {
if ($attribute->code === $name) {
return $attribute->pivot->value;
}
}
return null;
}
И назовем это так:
$model->getProductAttr('color');
Переопределить магический метод - __метод get().
Попробуйте это.
public function __get($key)
{
foreach ($this->productAttributes as $attribute) {
if ($attribute->code === $key) {
return $attribute->pivot->value;
}
}
return parent::__get($key);
}
Я думаю, что, вероятно, ответ Олег Шовкун правильный, но если бы вы хотели использовать обозначение атрибута модели, вы могли бы ввести требуемый аргумент в модель через переменную класса.
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;
}
}
Затем сделайте
$model->code = 'color';
echo $model->product;
Но это немного длинно и бессмысленно