Laravel如何通过公共列关联两表并按分类筛选展示商品?
问题描述
我有一个带6个分类按钮的页面,点击任意分类按钮后会跳转至对应页面,期望在目标页面根据分类筛选展示对应商品,但目前出现异常:要么没有数据展示,要么显示表中全部商品。比如点击Rims分类按钮后,希望在../shop/{category}页面只展示轮毂类商品。
相关代码与表结构
web.php
// shop Route::get('/shop', function () { return view('shop'); })->middleware(['auth', 'verified'])->name('shop'); // categories display Route::get('/shop', [CategoriesController::class, 'index'])->name('shop.index'); // accessing categories Route::get('/shop/{name}', [ProductsController::class, 'index'])->name('show-products');
ProductsController.php
<?php namespace App\Http\Controllers; use App\Http\Requests\ProfileUpdateRequest; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Redirect; use Illuminate\View\View; use App\Models\Categories; use App\Models\Products; use Illuminate\Support\Facades\DB; class ProductsController extends Controller { public function store(Request $product) { $product->validate([ 'name' => ['required', 'string', 'max:500'], 'brand' => ['required', 'string', 'max:500'], 'category' => ['required', 'string', 'max:500'], 'description' => ['required', 'string', 'max:500'], 'quantity' => ['required', 'string', 'max:500'], 'price' => ['required', 'string', 'max:500'], 'image' => ['required', 'string', 'max:500'] ]); $product = Products::create([ 'name' => $product->name, 'brand' => $product->brand, 'category' => $product->category, 'description' => $product->description, 'quantity' => $product->quantity, 'price' => $product->price, 'image' => $product->image, ]); return redirect('/shop'); } /** * Listeaza categoriile */ public function index(Request $product, $category) { $products = Products::all(); $categories = Categories::all(); $category = DB::table('categories') ->join('products', 'categories.category', '=', 'products.category') ->select('categories.category') ->get(); return view('products', ['category'=>$category, 'products'=>$products]); } }
表结构截图
- categories表:

- products表:

已尝试的方法
我试过在ProductController和CategoryController之间用if语句(比如$product->category == $category->category)匹配分类,也尝试关联两张表的分类字段,但问题还是没解决。
解决方案
1. 修复路由冲突与参数不匹配问题
当前/shop路由存在重复定义,会导致逻辑覆盖;同时路由参数{name}与控制器接收的$category参数名不对应,修改web.php:
// 保留一个处理分类展示的shop路由,移除重复定义 Route::get('/shop', [CategoriesController::class, 'index'])->middleware(['auth', 'verified'])->name('shop.index'); // 统一参数名为category,与控制器方法接收参数对应 Route::get('/shop/{category}', [ProductsController::class, 'index'])->name('show-products');
2. 修正ProductsController的筛选逻辑
当前方法直接查询所有商品,且覆盖了路由传入的分类参数,修改为按分类筛选:
public function index(Request $request, $categoryName) { // 根据路由传入的分类名称筛选对应商品 $products = Products::where('category', $categoryName)->get(); // 获取所有分类用于页面导航(如果需要) $categories = Categories::all(); // 将筛选结果传递给视图 return view('products', compact('products', 'categories', 'categoryName')); }
3. 确保分类按钮跳转链接正确
分类按钮的跳转链接要指向正确的路由,比如Rims分类的链接写法:
<a href="{{ route('show-products', ['category' => 'Rims']) }}">Rims</a>
4. 可选:优化模型关联(增强容错性)
如果想避免分类名称不存在的情况,可以在Categories模型定义关联:
// Categories.php public function products() { return $this->hasMany(Products::class, 'category', 'category'); }
然后控制器中可以通过关联查询,同时处理分类不存在的情况:
public function index(Request $request, $categoryName) { // 若分类不存在则返回404 $category = Categories::where('category', $categoryName)->firstOrFail(); // 通过关联获取该分类下的所有商品 $products = $category->products; $categories = Categories::all(); return view('products', compact('products', 'categories', 'category')); }
内容的提问来源于stack exchange,提问作者Marius Bocan
相关产品推荐
相关产品推荐

