Search code examples
laravellaravel-5laravel-5.3

Access user in AppServiceProvider?


I need to be able to pass data to all views when the user is logged in.

Here is what my AppServiceProvider currently looks like:

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        if (Auth::check())
        {
            View::share('key', 'value');
        }
    }
}

However, the data is never passed to the view because I can't use Auth (for some reason) in AppServiceProvider so the if statement condition is never met.

Following a previous solution I found, I tried doing this:

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        View::composer('*', function ($view)
        {
            if (Auth::check())
            {
                View::share('key', 'value');
            }
        }
    }
}

This worked, but the problem is that the closure is called whenever a view is rendered.

For example, if my blade template includes 3 other blade templates (which it does), then the closure above will be called 4 times. Explained further here.

So how can I access the user correctly in AppServiceProvider?


Solution

  • The reason why the Auth methods do not work in a direct context in the AppSeviceProvider, is that the Auth system is not loaded yet. In the defined closure, the Auth system will be available, as it always loaded before this closure is executed. Hence, the problem is in the way the view composer is used.

    The composer method only accepts an array (or a string) of view identifiers and an *. Therefore, the following options are available:

    Define multiple views

    View::composer(['about', 'contact'], function ($view)
    {
        if (Auth::check())
        {
            View::share('key', 'value');
        }
    }
    

    Define one view, and make this the main parent view for all the relevant pages

    You could, for example, define a main.blade.php and extend this view with all relevant views.

    @extends('main')
    

    And just share the main view:

    View::composer('main', function ($view)
    {
        if (Auth::check())
        {
            View::share('key', 'value');
        }
    }
    

    There are other options available, for example filters or a parent controller. Excellent answer here.