Extracting Eloquent Queries to View Composers in Laravel

Whenever working with data using Laravel, it can be easy to write a few small Eloquent queries within your blade files to access the database. However, this practice can quickly spiral out of control if you're not careful, increasing query load time and destroying the performance of your application. 

In this post, I'll explain how to extract commonly used queries to a view composer so that they can be shared across multiple views that use different blade files. Let's start with the "before" snapshot: 

@foreach(App\Topic::all() as $topic)
    <li>{{$topic->name}}</li>
@endforeach

In this deadly simple example, we are simply looping through all the topics to display the name of each one. At first this seemed reasonable, but what if there are 50 topics? Or 500? More importantly, what if this list of topics needs to be shared with multiple views? Or what if it needs to persist in some kind of navigation menu? We can do better. 

Implementation actually involves relatively little overhead. You can either create a custom service provider or attach the functionality to the AppServiceProvider's boot method. For the simplicity of this tutorial, I'm going to do the latter. 

# app/Providers/AppServiceProvider.php
    public function boot()
    {
        \View::composer('*', function ($view) {
            $view->with('topics', Topic::all());
        });
    }

Let's unpack what happens here. We have instantiated a view composer that handles the Eloquent query that was previously delegated to the view. Additionally, by passing a wildcard (*) to the function, we ensure that this data is available on every view. 

All that's left now is to return to the view and call our newly introduced variable, channels. 

@foreach($topics as $topic)
    <li>{{$topic->name}}</li>
@endforeach

It's also important to understand the impact of this refactor. Although the functionality is identical for the user, we've decreased our dependency on loading items from the database and ensured that we aren't ever loading the same items twice. Happy coding!