Remove the () from categories here in your view
$product->categories->first()->slug
You want to work on the categories property (which is a collection) that was already retrieved, not the relationship method which will execute a new query.
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hello,
I need some help optimising a query, and putting the correct syntax in to blade. At the moment, I am generating 12 SQL queries. I know 6 of them, come from blade, but the other 6, I am a bit lost on.
public function index()
{
$products = Product::with('media')->enabled()->promote()->inRandomOrder()->take(6)
->with(['categories' => function ($categories) {
$categories->with('media')->enabled()->first();
}])->get();
//return response()->json($products);
return view('home', compact('products'));
}
This returns all the correct data I need...
https://ek1.ams3.digitaloceanspaces.com/1.png
However, in blade, with the debugbar it gets awfully messy...
https://ek1.ams3.digitaloceanspaces.com/2.png
The first 6, I presume are to do with my above query - is that normal? Can it be improved? Of course I can cache it, but at the moment I am trying to optimise the queries themselves.
I know that the bottom 6 are due to the following line, but not sure how to correct that in my blade...
<a href="/{{ $product->categories()->first()->slug}}/{{ $product->slug }}">
I would have presumed that the first() wouldn't execute another query given the data is already passed, but I am fairly new to Laravel.
Any advice greatly received.
Ok that makes sense.
So to only return one Category per Product where should the first() be?
When i put it inside the closure, only 1 of the 6 returned Products has a Category, the other 5 are empty. If I remove it, all 6 Products return 2 Categories each (which would be correct).
$products = Product::enabled()->promote()->with('media')
->with(['categories' => function ($categories) {
$categories->enabled()->first()->with('media');
}])->inRandomOrder()->take(6)->get();
I could leave it without the first() and do that in blade, as I will cache the results anyway, but would be nice to bottom it out.
Please or to participate in this conversation.