Laravel路由带额外参数:控制器接收与Blade排序链接配置咨询
Hey there! Let's take a close look at your Laravel routing and Blade setup, and go over what's working, what might be causing issues, and how to make it better.
First: Checking for Correctness
Your current setup has a couple of potential issues that might break functionality or lead to unexpected behavior:
Mismatched Route Parameter & Controller Argument
Your route defines a parameter{category-url}, but your controller method accepts$urias the first argument. Laravel maps route parameters to controller arguments by name (automatically converting kebab-case likecategory-urlto camelCasecategoryUrl). Right now, the$urivariable in your controller won't receive the value of thecategory-urlroute parameter. You can fix this in two ways:- Rename the controller argument to
$categoryUrl(or$category_url) to match the route parameter name (cleaner and more standard) - Explicitly map the parameter in your route:
Route::get('/products/{category-url}', [CategoryController::class, 'categoryProducts']) ->name('client.category.products') ->parameters(['category-url' => 'uri']);
- Rename the controller argument to
Incorrect Parameter Value in Blade Route Calls
In your Blade template, you're usingRoute::current()->urlto pass theurlparameter. This returns the full current URL (e.g.,https://website.lrv/products/electronics), but your route only expects the category slug (e.g.,electronics). Additionally, you're passing a keyurlthat doesn't match the route's required parametercategory-url— this will treaturlas a query string parameter instead of filling the route segment. Fix this by fetching the actual route parameter and using the correct key:{{ route('client.category.products', [ 'category-url' => Route::current()->parameter('category-url'), 'order' => 'article', 'by' => 'desc' ]) }}
Optimization Recommendations
Once you fix the correctness issues, here are some ways to make this setup cleaner and more maintainable:
Use Implicit Route Model Binding
If you have aCategorymodel with aurlattribute matching the slug, let Laravel automatically fetch the category for you. This eliminates manual querying in your controller:// Route Route::get('/products/{category:url}', [CategoryController::class, 'categoryProducts']) ->name('client.category.products'); // Controller public function categoryProducts(Category $category, Request $request) { // $category is already the matching model based on the url slug $products = $category->products() ->orderBy($request->get('order', 'created_at'), $request->get('by', 'asc')) ->get(); // ... rest of your code }Simplify Sort Links in Blade
Instead of rebuilding the route array every time, userequest()->fullUrlWithQuery()to preserve existing query parameters (like filters) while updating sorting values. This is shorter and more robust:{{ request()->fullUrlWithQuery(['order' => 'article', 'by' => 'desc']) }} {{ request()->fullUrlWithQuery(['order' => 'price', 'by' => 'asc']) }}Centralize Sorting Logic with a Model Scope
Avoid repeating sorting logic by adding a scope to yourProductmodel. This also adds validation to prevent unsafe or invalid sort columns:// Product.php public function scopeSort($query, $orderBy = 'created_at', $direction = 'asc') { $allowedOrders = ['article', 'price', 'created_at']; $orderBy = in_array($orderBy, $allowedOrders) ? $orderBy : 'created_at'; $direction = in_array($direction, ['asc', 'desc']) ? $direction : 'asc'; return $query->orderBy($orderBy, $direction); }Then use it in your controller:
$products = $category->products() ->sort($request->get('order'), $request->get('by')) ->get();Validate Request Parameters
Add validation to your controller to ensureorderandbyparameters are valid, preventing unexpected behavior:public function categoryProducts(Category $category, Request $request) { $validated = $request->validate([ 'order' => 'nullable|string|in:article,price,created_at', 'by' => 'nullable|string|in:asc,desc' ]); $products = $category->products() ->sort($validated['order'] ?? 'created_at', $validated['by'] ?? 'asc') ->get(); // ... }Cache Sorted Product Lists
If your product listings don't change frequently, cache the results to reduce database load:$cacheKey = "category_{$category->id}_products_{$request->get('order', 'created_at')}_{$request->get('by', 'asc')}"; $products = Cache::remember($cacheKey, 3600, function () use ($category, $validated) { return $category->products() ->sort($validated['order'] ?? 'created_at', $validated['by'] ?? 'asc') ->get(); });
内容的提问来源于stack exchange,提问作者Rosnowsky

