Eloquent относится к ToMany и трем таблицам (включая сводную) - PullRequest
0 голосов
/ 30 мая 2018

enter image description here

Я работаю над проектом электронной коммерции с использованием фреймворка Laravel.У меня есть таблица продуктов, таблица вкусов и таблица flav_product (я считаю, что это называется сводной таблицей).У меня есть модель Product и модель Flavor (из того, что я прочитал, нет необходимости создавать модель для сводной таблицы).

В модели Product я определил следующие отношения:

public function flavors()
{
    return $this->belongsToMany('App\Flavor');
}

В модели Flavor я определил следующее соотношение:

public function products()
{
    return $this->belongsToMany('App\Product');
}

Теперь в моем контроллере Product я попытался сделать следующее:

$flavors = Product::select('id')->with('flavors')->get();

, который отправляется наприменимое представление (product.blade.php).

В product.blade.php у меня есть следующее:

@foreach ($flavors as $flavor)
  <select id="product-flavor" class="bs-select">
     <option value="{{ $flavor }}">{{ $flavor }}</option>
  </select>
@endforeach

Итак, что дает мне?Ну, это показывает мне следующее:

{"id":1,"flavors":[{"id":1,"name":"Cake Batter","created_at":"2018-05-29 20:12:56","updated_at":"2018-05-29 20:12:56","pivot":{"product_id":1,"flavor_id":1}},{"id":2,"name":"Caramel Coffee","created_at":"2018-05-29 20:48:25","updated_at":"2018-05-29 20:48:25","pivot":{"product_id":1,"flavor_id":2}},{"id":3,"name":"Chocolate Milkshake","created_at":"2018-05-29 20:49:09","updated_at":"2018-05-29 20:49:09","pivot":{"product_id":1,"flavor_id":3}},{"id":4,"name":"Cookies &amp; Cream","created_at":"2018-05-29 20:49:50","updated_at":"2018-05-29 20:49:50","pivot":{"product_id":1,"flavor_id":4}},{"id":5,"name":"Vanilla Milkshake","created_at":"2018-05-29 20:50:16","updated_at":"2018-05-29 20:50:16","pivot":{"product_id":1,"flavor_id":5}}]}

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

Как я могу продолжить?

Редактировать

Следующий кодв ShopController.php (относительно того, как продукт извлекается и отображается):

/**
 * Display the specified resource.
 *
 * @param  string  $slug
 * @return \Illuminate\Http\Response
 */
public function show($slug)
{
    $product = Product::where('slug', $slug)->firstOrFail();
    $mightAlsoLike = Product::where('slug', '!=', $slug)->mightAlsoLike()->get();

    return view('product')->with([
        'product' => $product,
        'mightAlsoLike' => $mightAlsoLike,
    ]);
}

Из web.php:

Route::get('/shop/{product}', 'ShopController@show')->name('shop.show');

1 Ответ

0 голосов
/ 30 мая 2018

То, что вы здесь делаете, говорит Laravel выбрать id из всех продуктов и получить все связанные с ними ароматы.

Product::select('id') // <-- Will only select `id` attribute from the `products` table
    ->with('flavors') // <-- Will attach associated flavors to the product id
    ->get(); // <-- End the query (get all product ids and their flavours)

В вашем случае вы не хотите выбирать всепродукты, и вы правильно настроили отношения.Итак, что вы должны сделать, это вызвать ->with('flavors') в исходном запросе (на самом деле это не нужно в этом случае, так как вы не столкнетесь с n+1 проблемами, но все же с хорошей практикой):

$product = Product::where('slug', $slug)->with('flavors')->firstOrFail();
$mightAlsoLike = Product::where('slug', '!=', $slug)->mightAlsoLike()->get();

return view('product')->with([
    'product' => $product,
    'mightAlsoLike' => $mightAlsoLike,
]);

И затемпросто вызовите $product->flavors в представлении:

@foreach ($product->flavors as $flavor)
  <select id="product-flavor" class="bs-select">
     <option value="{{ $flavor }}">{{ $flavor }}</option>
  </select>
@endforeach

Приведенный выше код представления будет работать как есть, без фактического вызова ->with('flavors') для запроса.->with(...) нетерпеливо загружает отношения и рекомендуется явно звонить при загрузке нескольких родителей, чтобы избежать проблемы n+1 (производительность!).

Но в вашем случае вы толькодемонстрируя ароматы от 1 продукта, поэтому нет особого преимущества в том, чтобы называть его явно (кроме более четкого кода).

Изменить для комментария:

<select id="product-flavor" class="bs-select">
@foreach ($product->flavors as $flavor)
    <option value="{{ $flavor->id }}">{{ $flavor->name }}</option>
@endforeach
</select>

Вывы видите несколько вариантов выбора, потому что вы печатаете весь выбор внутри цикла, а не просто печатаете варианты.

И для отображения любого атрибута из текущего аромата просто вызовите имя атрибута: $flavor->name, например.

...