Automatically detect right guard for logged in user in laravel

Viewed 1886

I'm using laravel 5.4 and added a new guard named website to my application and I did all things that are required for that.

But a problem that I have is that some views are shared between both default and website guard. for example when I want to show current logged in user I used this :

        <div class="pull-left info">
            @if(Auth::guard('website')->check())
                <p>{{Auth::guard('website')->user()->name}} Website</p>
            @elseif (Auth::check())
                <p>{{Auth::user()->name}}</p>
            `@endif
            <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
        </div>

And this is just one place that I must to check which guard is logged in and it is Naturally difficult,time consuming and dirty way.

On the other hand some operations is same for both guards. for example there is a bannerController store method that can save some banner model for them like this (Of course this example is written just for website guard as you can see ):

public function store($website,StoreBannerAds $request)
{
    $allData = $request->all();
    $website = Auth::guard('website')->user();

    $ads = $website->banner_ads()->create($allData);

    $result = ['success' => true, 'generated_id' => $ads->banner_ads_id];
    return $result;

}

In this case if I want to store some banners for default user logged in User I should use an if () or completely another store method:

public function store($website,StoreBannerAds $request)
    {
        $allData = $request->all();
        if (Auth::guard('website')->check()) {
            $model = Auth::guard('website')->user();
        } else if (Auth::check()){
            $model = Auth::user();
        }

        $ads = $model->banner_ads()->create($allData);

        $result = ['success' => true, 'generated_id' => $ads->banner_ads_id];
        return $result;

    }

I want know are there any clean and appropriate ways to do that Or I must to use this approach still؟

Update:

What I changed before in auth.php configuration file are these:

'defaults' => [
            'guard'     => 'web',
            'passwords' => 'users',
        ],

'guards' => [
            'web' => [
                'driver'   => 'session',
                'provider' => 'users',
            ],
            'website' => [
                'driver'   => 'session',
                'provider' => 'websites',
            ],

            'api'     => [
                'driver'   => 'token',
                'provider' => 'users',
            ],
        ],

'providers' => [
            'users'    => [
                'driver' => 'eloquent',
                'model'  => App\User::class,
            ],
            'websites' => [
                'driver' => 'eloquent',
                'model'  => App\Website::class,
            ]
        ],

'passwords' => [
            'users' => [
                'provider' => 'users',
                'table'    => 'password_resets',
                'expire'   => 60,
            ],
        ],
2 Answers

I don't get it from your explanation. But, I do have a little solution from my understanding. For example using helpers.

if (! function_exists('auth_user')) {
    function auth_user($guard = 'website', $attr = null, $force = false)
    {
        $user = auth($guard)->check()
            ? auth($guard)->user()
            : $force && auth()->check()
                ? auth()->user()
                : null;

        return $user
            ? $attr
                ? $user->$attr
                : $user
            : null;
    }
}

Then you can use it like this:

// get name of the user
$name = auth_user('website', 'name');

// get the user
$user = auth_user()

PS. What do you think if user is not authenticated? What is the value of the $model? Your example is very strange.

With this approach, at least you can simplify your code.

@if ($name = auth_user('website', 'name'))
    <p>{{ $name }} Website</p>
@elseif ($name = auth_user(null, 'name')) // or auth_user('website', 'name', true)
    <p>{{ $name }}</p>
@endif

and,

// force get user data although `website` guard fails
$model = auth_user('website', null, true);

You should only need to hit the default guard to get the user. Auth::user() will use the current default guard.

If you always have any routes needing an authenticated user behind the default auth middleware, the default guard should be the correct guard for getting the user. If the route isn't behind the auth middleware and the user is a guest currently, it doesn't matter what guard check is called on.

The Request object will have access to the current user as well. Regardless of guard $request->user() should give you the current user.

Checking what guard is used could be done when calling check on a guard or asking the AuthManager for what the default guard is.

Some options:

@if (Auth::check())
    {{ Auth::user()->name }}
    @if (Auth::getDefaultDriver() == 'website')
        Website
    @endif
@endif

OR

@if (Auth::check())
    {{ Auth::user()->name }}
    @if (Auth::guard('webiste')->check())
        Website
    @endif
@endif

OR (if on 5.5)

@auth
    {{ Auth::user()->name }}
    @auth('website')
        Website
    @endauth
@endauth

Slims the lines down a little.

$model = $request->user();
// or
$model = Auth::user();
Related