Steve
Steve

Reputation: 645

Laravel routing slug error Bad Method Call Exception

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()

Upvotes: 0

Views: 418

Answers (1)

miken32
miken32

Reputation: 42696

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'));
    }
}

Upvotes: 1

Related Questions