Laravel Глубокие отношения для вариантов продукта

У меня есть следующая структура базы данных: https://dbdiagram.io/d/5c4b590def2dd100140d5997

Надеюсь, диаграмма поможет объяснить настройку лучше, чем слова.

У меня есть продукт, и я сгенерировал возможные варианты на основе параметров/ценностей продукта. Теперь я перечисляю варианты в таблице, чтобы я мог изменить цену для каждой комбинации, используя следующий код:

@foreach($product->variants as $variant)
<tr>
    <td>{!! Form::text('variants[' . $variant->id . '][sku]', (is_null($variant->sku) ? $variant->reference : $variant->sku)) !!}</td>
    <td>{!! Form::number('variants[' . $variant->id . '][price]', $variant->price) !!}</td>
    <td>{{ $variant->image }}</td>
    <td>{!! Form::number('variants[' . $variant->id . '][stock]', $variant->stock) !!}</td>
    @foreach($variant->productoptions() as $productoption)
        <td>{{ $productoption->product_option_value_name }}</td>
    @endforeach
</tr>
@endforeach

В модели ProductVariant у меня есть следующий метод для получения конкретных имен для параметров продукта:

/**
 * @return mixed
 */
public function productoptions()
{
    return $this->select('product_options.name as product_option_name', 'product_option_values.name as product_option_value_name')
        ->where('product_variants.id', '=', $this->id)
        ->join('product_variant_values', 'product_variants.id', '=', 'product_variant_values.product_variant_id')
        ->join('product_options', 'product_options.id', '=', 'product_variant_values.product_option_id')
        ->join('product_option_values', 'product_option_values.id', '=', 'product_variant_values.product_option_value_id')->get();
}

Однако это приводит к проблеме n + 1 (которая может быть сотнями вызовов, если продукт, например, футболка, имеет много размеров, цветов и т. д.), поскольку он будет выполнять вызов базы данных для каждого варианта, поэтому я ищу при попытке загрузить это вместо этого. Но это означает, что я должен рассмотреть возможность использования Eloquent Relationship.

Вот что я пробовал до сих пор, используя пакет staudenmeir/eloquent-has-many-deep:

/**
 * @return mixed
 */
public function productoptions()
{
    return $this->hasManyDeep(ProductOptionValue::class, [ProductVariantValue::class, ProductOption::class], ['product_variant_id', 'id', 'product_option_id'], ['id', 'product_option_id', 'id']);
}

Проблема с этим заключается в том, что он получает все значения параметров, а не те, которые специфичны для этого варианта.

Надеюсь, все это имеет смысл, если нет, пожалуйста, не стесняйтесь запрашивать дополнительную информацию.


person Karl    schedule 25.01.2019    source источник
comment
Попробуйте добавить ->whereColumn('product_option_values.id', '=', 'product_variant_values.product_option_value_id') к отношениям.   -  person Jonas Staudenmeir    schedule 25.01.2019
comment
Я буквально только что делал это сейчас, я знал, что недалек от достижения того, к чему стремился. Большое спасибо! :)   -  person Karl    schedule 25.01.2019


Ответы (1)


Используйте whereColumn(), чтобы добавить отсутствующее ограничение:

public function productoptions()
{
    return $this->hasManyDeep(ProductOptionValue::class, [ProductVariantValue::class, ProductOption::class], ['product_variant_id', 'id', 'product_option_id'], ['id', 'product_option_id', 'id'])
        ->whereColumn('product_option_values.id', '=', 'product_variant_values.product_option_value_id');
}
person Jonas Staudenmeir    schedule 25.01.2019