Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Sharim's avatar

Match URL with categories & subcategories in show method

I want to show product page only if whole url is match with product->slug, products->subcategory & product->maincategory. My URL scheme is something like this:

/category/parentTagSlug/SubTagSlug/ProductSlug

Show Method:

public function show($parentSlug, $childSlug, $slug)
    {
        $tag = Ecomtag::where('slug', request()->tag)->get()->firstOrFail();
        $tags = Ecomtag::where('slug', request()->tags)->get()->firstOrFail();

        $product = Product::where('slug', $slug)->where('ecommerce', true)->firstOrFail();
       
        return view('layouts.product')->with([
            'product' => $product,
            'tags' => $tags,
            'tag'   => $tag,
            'parentSlug' => $parentSlug,
            'childSlug'   =>  $tagSlug,
        ]);
    }

Product main and sub tag is different, but if I put another tag in the url, the product page is still showing. It should give an error 404 not found.

0 likes
20 replies
SilenceBringer's avatar

@sharim because you checks just tag existance, not that tags associated with the given product

Assuming you have defined mainCategory and subCategory relationships on product

public function show($parentSlug, $childSlug, $slug)
    {
        $product = Product::where('slug', $slug)
->where('ecommerce', true)
			->whereHas('mainCategory', fn ($query) => $query->where('slug', $parentSlug)) // here
			->whereHas('subCategory', fn ($query) => $query->where('slug', $childSlug)) // and here
			->firstOrFail();

			// ...
    }
Sharim's avatar

@SilenceBringer I have belongsToMany between product and tags. I don't know how to call it in whereHas(foreach($product->tags))

Sinnbeck's avatar

@Sharim You dont. You call it exactly the same, but with a whereIn() (just guessing the names here)

->whereHas('tags', fn ($query) => $query->whereIn('name', $product->tags))
Sharim's avatar

@Sinnbeck I write something like this:

$product = Product::where('slug', $slug)->where('ecommerce', true)
        ->whereHas('tags', fn ($query) => $query->whereIn('slug', $parentSlug))
        ->firstOrFail();

but its showing me this error:

Argument 1 passed to Illuminate\Database\Query\Builder::cleanBindings() must be of the type array, string given,

Sinnbeck's avatar

@Sharim It seems that $parentSlug is a string, not an array. In you own example before you used $product->tags which I assumed was an array

If it is just a single tag

$product = Product::where('slug', $slug)->where('ecommerce', true)
        ->whereHas('tags', fn ($query) => $query->where('slug', $parentSlug))
        ->firstOrFail();
Sharim's avatar

@Sinnbeck $parentSlug is a string redirecting directly from url. But $product->tags is an array. But I want to show only first tag.

SilenceBringer's avatar

@Sharim yes. And - what's wrong?

Product::where('slug', $slug)

search product by slug.

This condition

->whereHas('tags', fn ($query) => $query->whereIn('slug', [$parentSlug, $childSlug]), '=', 2)

checks that product has both associated tags

What's the error with it? Can you provide more details

Sharim's avatar

@SilenceBringer If I do only this Product::where('slug', $slug), its showing all the products even if the $parent and $child tags are not associated with products.

With your code, nothing is showing even if the tags are matched with whole url.

That is an example of my url and product should show here:

http://localhost:8000/category/machinery/carpet-care-machines/Vac-5-Commercial-Vacuum-Cleaneri-vac-5B-im13

With my code product is showing with this url also:

http://localhost:8000/category/chemicals/trolleys/Vac-5-Commercial-Vacuum-Cleaneri-vac-5B-im13

SilenceBringer's avatar

@Sharim ok, let's test it another way

get the product as

        $product = Product::where('slug', $slug)
			->where('ecommerce', true)
			->firstOrFail();

		dd(
			$produt->tags->pluck('slug'),
			[$parentSlug, $childSlug]
		);

please show the output for correct url

http://localhost:8000/category/machinery/carpet-care-machines/Vac-5-Commercial-Vacuum-Cleaneri-vac-5B-im13

and incorrect one

http://localhost:8000/category/chemicals/trolleys/Vac-5-Commercial-Vacuum-Cleaneri-vac-5B-im13

Sharim's avatar

@SilenceBringer For this url:

http://localhost:8000/category/machinery/carpet-care-machines/Vac-5-Commercial-Vacuum-Cleaneri-vac-5B-im13

The result is

^ Illuminate\Support\Collection {#1982 ▼
  #items: array:1 [▼
    0 => "carpet-care-machines"
  ]
  #escapeWhenCastingToString: false
}
^ array:2 [▼
  0 => "machinery"
  1 => "carpet-care-machines"
]

and for

http://localhost:8000/category/carpet-care-machines/multifunction-trolley/Vac-5-Commercial-Vacuum-Cleaneri-vac-5B-im13

the result is:

^ Illuminate\Support\Collection {#1982 ▼
  #items: array:1 [▼
    0 => "carpet-care-machines"
  ]
  #escapeWhenCastingToString: false
}
^ array:2 [▼
  0 => "carpet-care-machines"
  1 => "multifunction-trolley"
]
SilenceBringer's avatar

@Sharim ok, next step. Looks like your product assocaited with the child tag only, not with parent one (why you use blongsToMany this way?)

Now I need to know how parent tag related to child tag. currently I can imagine something like

        $product = Product::where('slug', $slug)
			->where('ecommerce', true)
			->whereHas('tags', fn ($query) => $query->where('slug', $childSlug)
				->whereHas('parent', fn ($query) => $query->where('slug', $parentSlug))
			)
			->firstOrFail();

assuming tag has something lik parent relationship to parent tag

Sharim's avatar

@SilenceBringer I'm sorry I didn't realize that this information should be useful to fix this issue. Let me explain please.

Tag Schema:
name:   slug:   parent_id

When I add new tag, I select parent tag also. If I will not select any parent tag, it means that is parent tag itself. And the product is associated with child tag only.

SilenceBringer's avatar
Level 55

@Sharim this way this one

			->whereHas('tags', fn ($query) => $query->where('slug', $childSlug)
				->whereHas('parent', fn ($query) => $query->where('slug', $parentSlug))
			)

should works

Please or to participate in this conversation.