Home > database >  Laravel routing slug error Bad Method Call Exception
Laravel routing slug error Bad Method Call Exception

Time:12-02

I'm trying to create a route with three slugs, which include category, brand name and product name.

web.php

Route::get('/shop/{category:slug}/{brand:slug}/{product:slug}', [ProductController::class, 'index']);

Controller

<?php

namespace App\Http\Controllers;

use App\Brand;
use App\Category;
use App\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index(Category $category, Brand $brand, Product $product)
    {
        $product = Product::where('id', $product->id)->with('related', function($q) {
            $q->with('brand')->with('categories');
        })->with('brand')->first();

        return view('product', compact('product', 'category'));
    }
}

For some reason i get this error, which i don't understand why.

BadMethodCallException Call to undefined method App\Category::brands()

CodePudding user response:

The route resolver is assuming the parameters are all related to each other. From the documentation:

When using a custom keyed implicit binding as a nested route parameter, Laravel will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent.

So you should have a brands() relationship set up in your Category model, as well as a products() relationship in your Brand model.

If it's not possible to set up a relationship, simply stop using the route model binding and do it manually:

Route::get('/shop/{category}/{brand}/{product}', [ProductController::class, 'index']);
<?php

namespace App\Http\Controllers;

use App\Brand;
use App\Category;
use App\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index(string $category, string $brand, string $product)
    {
        $category = Category::where('slug', $category);

        $product = Product::where('slug', $product)
            ->with(['category', 'brand'])->first();

        return view('product', compact('product', 'category'));
    }
}
  • Related