Reader Stacks

How to Share Variables Across All Views in Laravel

View::share() makes a variable available to every view without passing it explicitly from each controller — the right tool for genuinely global data like site settings or unread notification counts.

A value needed in essentially every view — site-wide settings, the current user's unread notification count, a global announcement banner — is tedious to pass explicitly from every single controller method that renders a view. View::share() exists specifically to avoid that repetition.

Sharing a variable from a service provider

// AppServiceProvider::boot()
public function boot(): void
{
    View::share('appName', config('app.name'));
}
{{-- available in every single Blade view, automatically --}}
{{ $appName }}

Sharing dynamic, computed data

// AppServiceProvider::boot()
public function boot(): void
{
    View::composer('*', function ($view) {
        if (auth()->check()) {
            $view->with('unreadNotificationCount', auth()->user()->unreadNotifications->count());
        }
    });
}

View::composer('*', ...) is the more flexible tool for computed, per-request data — the closure runs fresh on every view render, unlike View::share(), which is typically better suited to values that are static or rarely change within a single request lifecycle.

Sharing with a specific view rather than every view

View::composer('layouts.app', function ($view) {
    $view->with('categories', Category::all());
});

Passing a specific view name (or an array of names) instead of the '*' wildcard restricts the composer to only run for that particular view — useful when the shared data is only actually needed in a specific layout or partial, not truly every view in the application.

Using a dedicated View Composer class for more complex logic

php artisan make:provider ViewComposerServiceProvider
class NavigationComposer
{
    public function compose(View $view): void
    {
        $view->with('categories', Category::withCount('posts')->get());
    }
}
// in a service provider's boot()
View::composer('layouts.navigation', NavigationComposer::class);

Extracting the composer logic into its own class (rather than an inline closure) keeps a service provider's boot() method clean once view composer logic grows beyond a trivial one-liner, and makes the composer logic independently testable.

Why global view data should stay genuinely minimal

Overusing shared view data for things that only a handful of specific views actually need makes it harder to trace where a given Blade variable actually comes from, since it no longer appears explicitly in the controller that renders that view — reserving View::share() and global composers for data that's genuinely needed nearly everywhere (not just "used in a few places") keeps the data flow considerably easier to follow.