Eloquent belongsToMany 和三张表(包括数据透视表)
Eloquent belongsToMany and Three Tables (Including Pivot)
我正在使用 Laravel 框架开发一个电子商务项目。我有一个产品 table、一个口味 table 和一个 flavor_product table(我相信这被称为枢轴 table)。我有一个 Product 模型和一个 Flavor 模型(根据我的阅读,没有必要为 pivot 创建模型 table)。
在产品模型中,我定义了以下关系:
public function flavors()
{
return $this->belongsToMany('App\Flavor');
}
在风味模型中我定义了以下关系:
public function products()
{
return $this->belongsToMany('App\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 & 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}}]}
我绝对不想要所有这些。我只想通过数据透视 table.
检索与该产品关联的口味名称
我该如何处理?
编辑
以下代码在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');
你在这里所做的是告诉 Laravel 到 select 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)
在您的情况下,您不想 select 所有产品并且您已正确设置关系。所以你应该做的是在你的原始查询上调用 ->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>
您看到多个 select 是因为您在循环内打印整个 select 而不是只打印选项。
要显示当前风味的任何属性,只需调用属性名称:例如$flavor->name
。
我正在使用 Laravel 框架开发一个电子商务项目。我有一个产品 table、一个口味 table 和一个 flavor_product table(我相信这被称为枢轴 table)。我有一个 Product 模型和一个 Flavor 模型(根据我的阅读,没有必要为 pivot 创建模型 table)。
在产品模型中,我定义了以下关系:
public function flavors()
{
return $this->belongsToMany('App\Flavor');
}
在风味模型中我定义了以下关系:
public function products()
{
return $this->belongsToMany('App\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 & 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}}]}
我绝对不想要所有这些。我只想通过数据透视 table.
检索与该产品关联的口味名称我该如何处理?
编辑
以下代码在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');
你在这里所做的是告诉 Laravel 到 select 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)
在您的情况下,您不想 select 所有产品并且您已正确设置关系。所以你应该做的是在你的原始查询上调用 ->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>
您看到多个 select 是因为您在循环内打印整个 select 而不是只打印选项。
要显示当前风味的任何属性,只需调用属性名称:例如$flavor->name
。