Одна модель, разные сводные таблицы - PullRequest
0 голосов
/ 12 апреля 2020

У меня проблема, которая сводит меня с ума; -)

Моя цель:

Я хотел бы определить список продуктов с атрибутами. И для удобства использования я также хотел бы иметь возможность комплектации продуктов.

Пример:

  • 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.

Мой вопрос

Я уверен, что есть лучший способ решить эту проблему. Я рад за все ваши мысли по этому поводу: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...