У меня проблема, которая сводит меня с ума; -)
Моя цель:
Я хотел бы определить список продуктов с атрибутами. И для удобства использования я также хотел бы иметь возможность комплектации продуктов.
Пример:
Product
- это автомобиль с ProductAttribute
цветом и сводными данными blue
. Product
- это крышка рулевого колеса с ProductAttribute
цветом и сводными данными brown
.
Теперь возможный пакет должен содержать оба продукта с разным сводным значением:
Пример:
Bundle
содержит два Product
Product
- это автомобиль с ProductAttribute
цвет и сводные данные yellow
. Product
- крышка рулевого колеса с ProductAttribute
цвет и сводные данные black
.
Давайте начнем:
Модели
I получил следующие модели:
Product
ProductAttribute
Bundle
Отношения
Каждый Product
может иметь множество ProductAttribute
с сводным значением (в данном случае: value
и unit
).
Пока это не проблема:
/**
* @return \Illuminate\Database\Eloquent\Relations\belongsToMany
*/
public function productAttributes()
{
return $this->belongsToMany(ProductAttribute::class)
->withPivot('value', 'unit')->withTimestamps();
}
Проблема em
Теперь начинается проблема:
Каждый Bundle
может также иметь много Product
с, и каждый Product
, принадлежащий Bundle
, должен иметь свою собственную сводную таблицу для этого. ProductAttribute
с.
грязное решение
Итак, то, что я сейчас делаю, довольно уродливое решение:
Product
получает два отношения:
/**
* @return \Illuminate\Database\Eloquent\Relations\belongsToMany
*/
public function productAttributes()
{
return $this->belongsToMany(ProductAttribute::class)
->withPivot('value', 'unit')->withTimestamps();
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function productBundleAttributes()
{
if ($this->pivot) {
return $this->belongsToMany(ProductAttribute::class,
'product_bundle_product_attribute')
->withPivot('value', 'unit')
->wherePivot('product_product_bundle_uuid', '=',
$this->pivot->uuid)->withTimestamps();
}
return $this->belongsToMany(ProductAttribute::class,
'product_bundle_product_attribute')
->withPivot('value', 'unit');
}
Теперь модель ProductAttribute
заставляет некоторые перезаписанные геттеры решать, какой стержень использовать:
/**
* @param $value
*
* @return bool
*/
public function getUnitAttribute($value)
{
return $this->isBundle() ? $this->getBundleUnit() : $this->getProductUnit();
}
[..]
public function isBundle()
{
return ($this->hasPivot()
&& $this->getPivotTable() === 'product_bundle_product_attribute')
? true : false;
}
Другие подходы
Я также думал о создании какого-то "фиктивных моделей", таких как:
Product
-> hasMany ProductAttribute
-> withPivot Bundle
-> hasMany BundleProduct
-> hasMany BundleProductAttribute
-> withPivot
Но проблема здесь в том, что мне нужно синхронизировать c BundleProduct
и BundleProductAttribute
с Product
и ProductAttribute
.
Мой вопрос
Я уверен, что есть лучший способ решить эту проблему. Я рад за все ваши мысли по этому поводу: -)