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.