How To Use View Composers

How To Use View Composers

In this tutorial we will learn how to use view composers in our little forum application. View composers are a way to make sure certain data is available to view files no matter which endpoint you may be visiting in an application. We’ll discuss placing sql queries in view files, vs having them in a controller, vs making use of view composers. As a little bonus, we’ll also cover how to automatically import a class in PHP Storm. Let’s get cooking with view composers.

SQL in template files

You may have noticed that in some prior tutorials, we placed some SQL queries right in our view, or template files. This is fine, but if you would like to remove those queries from the templates, and still have everything work, then view composers are here to help you with that. Recall that in our create.blade.php file we have this code which powers the dropdown menu for our channel selection.

Move query to the controller?

At first blush you might think of moving the query over into the controller, and why not, right? For many cases this is actually the way to go. Here is the issue however. Since the data only gets shared to the particular view being rendered by that method in the controller, other views that might need access to that same data are going to fail. You then need to visit each different method on whatever controller is creating these different views, and add in the query needed to provide the data. Not a big deal if you have 2 or 3 places you need to add the query. What if you have many more? At this point, it makes sense to lean on a view composer, where you can share the data with any view necessary.

How AppServiceProvider Works

To enable this slightly magic like feature, we visit the AppServiceProvider.php file. The AppServiceProvider.php file has a boot() method, and this is where we can start to set up a view composer. This can take a few forms. Let’s see.

In this snippet above, we are registering a view composer for the ‘threads.create’ view. In the closure, what we are saying is when that view is loaded, the ‘channels’ variable should always be available. The contents of that variable are provided via the query provided as the second argument to the with() method. In this case, that is AppChannel::all().

Remove query from the view

Now that a view composer exists for the create.blade.php template, we can actually remove the query from the view and just reference the actual $channels variable. See here.

Does the view still work?

Go ahead and visit the page and witness the power of a view composer. The page is working perfect, and the dropdown is still populating correctly with all the needed channels!
view composer working nicely

Query in the layouts/app.blade.php view

Recall we had a second place where we were making use of an sql query in a view file. This was in the layout file of app.blade.php. With view composers, we should be able to clean that instance up as well. In this snippet below we again remove AppChannel::all() and replace with $channels.

The First Argument To the View::composer() method

Now is a good time to talk about your options for passing the first argument to the View::composer() method. So far, we have specified a string of ‘threads.create’ to the method. What this says is, that the generated variable will *always* be available on that view. Now, we added also removed a query from the app.blade.php file. This is a different view. Will everything still work? Well, it turns out that if you visit everything is still in fact going to work. What happens if you visit somewhere else however? If we try to visit for example, we get a nasty error:

ErrorException thrown with message "Undefined variable: channels (View: /home/vagrant/Code/forumio/resources/views/layouts/app.blade.php) (View: /home/vagrant/Code/forumio/resources/views/layouts/app.blade.php)"

This happened because our view composer is only sharing the variable with create.blade.php. When we visit, the index.blade.php file is trying to load. Our view composer does not share with this view, nor does it share with the app.blade.php view so whammo – we get this error.

The * Wildcard Fix

Your first approach to fixing this is to simply pass an asterisk as the first argument to View::composer() like the following snippet shows. This shares the variable with every view in your application.

Now we can visit and it is working again.
asterisk in view composer

Simplify Even More With View::share()

The final way to tackle this issue of removing sql from your template files is with View::share(). Check out this one liner highlighted below:

Once again, if you go ahead and visit all of the different pages on your site, everything works perfect. The code above is making sure that the $channels variable is available anytime it is needed. Very Cool!

PHPStorm Import Class

There is one last thing we can do to clean up the AppServiceProvider just a little bit more. Notice that we used a fully qualified namespace for using the Channel model. That is to say, we had to use the full namespace of AppChannel::all() to make the query instead of just Channel::all(). This of course is because we have not placed a ‘use’ statement at the top of the file to specify we will be using the Channel model in this class. You could easily type this out, but let’s go ahead and use PHPStorm to automatically import the class for us. Here is how to do that.

First, you can click on the class that you want to import.
click on the class name phpstorm

Now, click on Alt+Enter and you will get a new sub menu. Here, you can choose to import the class.
click alt and enter same time phpstorm

Last, you can see that the class is imported automatically for you, and everything is great. Just like you, you are great.
phpstorm import class

How To Use View Composers Summary

Do you have to use view composers in your project? No it is not mandatory. It is however a nice way to clean up both your view files *and* your controller methods as well. If you have a variable that is going to need to be accessed across a high number of view files in your project, then view composers are actually a perfect solution!