
When you are building an application and utilizing Eloquent it’s very easy to hit the N+1 problem. This is where you select a model and then later use lazy loading to fetch child records.
As an example pretend you are selecting a user:
User::where('name', 'Eric')->first();
Then in your view you might do something like:
@foreach ($user->posts as $post)
Because the posts haven’t been initially loaded with the User Eloquent has to perform a new query for each of these records.
The solution is to utilize the with
method on the select.
User::where('name', 'Eric')->with('posts')->first();
Of course, finding these can get tricky and one solution is to use something like the Laravel Debugbar in local development. It will print out a list of all queries and give you a heads up if they are getting out of control.
Over on the Laravel Reddit channel, the user magkopian shared another quick solution to see all the queries ran on a page.
Inside AppServiceProvider.php
add the following to the boot method:
use DB;
use Event;
//..
public function boot()
{
if (env('APP_ENV') === 'local') {
DB::connection()->enableQueryLog();
}
if (env('APP_ENV') === 'local') {
Event::listen('kernel.handled', function ($request, $response) {
if ( $request->has('sql-debug') ) {
$queries = DB::getQueryLog();
dd($queries);
}
});
}
}
Now while you are developing on any URL you can append ?sql-debug=1
and get an output of all the queries ran.
One minor improvement instead of using dd
is to use the dump
helper so you can get a little nicer output:
Granted this is quick and dirty but I have came across situations where I just need to see what all is happening on a specific page and this will solve that without installing a dedicated package.
Do you have a better way of handling this? Let me know on Twitter or Facebook.