View Composer in Laravel: A Practical Guide

Updated: January 16, 2024 By: Guest Contributor Post a comment

Introduction

View Composers in Laravel provide an elegant and convenient way to share data with all views across an entire application. These are powerful feature that allow developers to organize code responsible for preparing views data in a compact and testable fashion. This streamlines the process of passing data without the need to manually bind data within each controller method. In this practical guide, we will explore view composers and how they can make your Laravel application cleaner and more efficient.

What Are View Composers?

View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to bound to a view each time that view is rendered throughout your application, a view composer can help you organize that logic into a single location.

Creating a View Composer

To start, let’s create a simple view composer. We will assume you want to share user’s profile data across all views. First, you can either use a Closure-based composer or a class-based composer. We’ll start with a Closure-based example:

// Using Closure-based composer
View::composer('layouts.app', function ($view) {
    $view->with('profile', Auth::user()->profile);
});

Put the above code in the boot method of one of your service providers, typically AppServiceProvider.

If you prefer to use a class, first generate it with Artisan:

php artisan make:provider ComposersServiceProvider

Then, within this service provider, you might bind a view composer class to a view:

public function boot()
{
    View::composer(
        'layouts.app',
        'App\Http\ViewComposers\UserProfileComposer'
    );
}

Next, create this composer class which will be called when the ‘layouts.app’ view is being rendered:

namespace App\Http\ViewComposers;

use Illuminate\View\View;
use Illuminate\Support\Facades\Auth;

class UserProfileComposer
{
    public function compose(View $view)
    {
        $view->with('profile', Auth::user()->profile);
    }
}

Attaching Composers to Multiple Views

If you need to attach a composer to multiple views, you can pass an array of views as the first argument:

View::composer([
    'dashboard',
    'profile.index',
    'layouts.app'
], UserProfileComposer::class);

Creating View Creators

View Creators are very similar to View Composers but they are invoked immediately after the view instance is created and not on view render. Here’s an example to use a View Creator:

View::creator('layouts.app', UserProfileComposer::class);

Passing Additional Data to Composers

It is also possible for a view composer to receive additional data beyond just the view instance, by type-hinting any dependencies it requires on its compose method:

use App\Segment;

class UserProfileComposer
{
    protected $segment;
    
    public function __construct(Segment $segment)
    {
        // Dependencies are automatically resolved by the service container...
        $this->segment = $segment;
    }

    public function compose(View $view)
    {
        $view->with('profile', Auth::user()->profile);
        $view->with('segment', $this->segment->get());
    }
}

Testing View Composers

Testing View Composers is straightforward with Laravel. You can render a view within a test and then make assertions on the view data. Let’s look at an example:


use Tests\TestCase;
class ViewComposerTest extends TestCase
{
    public function testProfileDataIsBoundToView()
    {
        $user = factory(User::class)->create();

        $this->actingAs($user)
            ->get('/home')
            ->assertViewHas('profile', $user->profile);
    }
}

Conclusion

Laravel View Composers offer a convenient way to share common data with all views across the Laravel application, promoting better organization and code cleanliness. By applying the concepts and examples provided in this guide, you can enhance your ability to maintain and scale the frontend of your Laravel applications.