Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Lopsum's avatar

Need advice on how to redirect users according to their role

Hello Laravelers 👋, I need feedback from you to check what I've done to manage access to a platform I'm developing based on roles. I've got the impression I've got something a bit messy (maybe not?) but I'm not sure how to simplify it.

So in my case, I have 4 roles: webmaster, admin, pro, private.

When you go to the basic URL, you log in and depending on your role, you're redirected to the right page. Note that if the role is equal to 3, you go through an API to check that the account is active before connecting the person.

So, here's what I did in my HomeController:

public function index(GetClientInfoAction $getClientInfoAction)
{
    // Check if the user is authenticated
    if (!auth()->check()) {
        // If not authenticated, redirect to the login page
        return view('auth.login');
    }

    // Fetch the role of the authenticated user
    $userRole = auth()->user()->roles()->first();

    // Switch based on the user role ID
    switch ($userRole['id']) {
        // Webmaster role (Page for accessing logs, clearing the cache, putting the site into maintenance, etc.)
        case 1:
            // Check if the application is down for maintenance
            if (app()->isDownForMaintenance()) {
                $token = Maintenance::first()->token;
                return view('webmaster.home', ['token' => $token]);
            }
            return view('webmaster.home');

        // Admin role (Page for managing users, roles, etc.)
        case 2:
            // Fetch latest 5 users having roles with ID 3 or 4
            $users = User::latest()->whereHas('roles', function ($q): void {
                $q->where('id', 3)->orWhere('id', 4);
            })->take(5)->get();

            // Count total users and total excel orders
            $countUsers = (new \App\Models\User())->countUsers();
            $countOrder = count(ExcelFile::all());

            return view('admin.index', ['users' => $users, 'cntUsers' => $countUsers, 'cntOrder' => $countOrder]);

        // Pro role (Pro customer page)
        case 3:
            $excel = ExcelFile::all();
            $ApiID = auth()->user()->api->identifier;

            // Check if ApiID is set
            if (isset($ApiID)) {
                // Execute the GetClientInfoAction for the given traplusID
                $response = $getClientInfoAction->execute($ApiID);

                // Handle the possible response scenarios
                if (!$response) {
                    $error = __("alerts.error.Your account does not exist or has been deactivated");
                    Auth::guard('web')->logout();
                    return redirect()->route('login')->withErrors($error);
                } elseif (true !== $response) {
                    $error = __("alerts.error.Communication problem with our API, please try again later");
                    Auth::guard('web')->logout();
                    return redirect()->route('login')->withErrors($error);
                }

                return view('pro.home', ['excel' => $excel, 'fileFormat' => null]);
            }
            break;

        // Individual role (Individual customer page)
        case 4:
            return view('individual.home');
    }
}

Does this seem like a good approach to you?

I also have another small question. I often get a [production] error when testing the platform in the browser (even though my .env is local) telling me that the encryption key doesn't exist when I log in/out and switch accounts. This forces me to clear my cache each time, but I can't quite work out where it's coming from. I haven't touched the Breeze authentication system.

Thanks for your help and feedback 😇

0 likes
4 replies
Snapey's avatar

a couple of observations. Your first auth check should be done earlier in middleware wrapped around all routes that require you to be logged in

secondly, don't use 'magic numbers' for the roles. If the roles have names, use them

also If the site is in maintenance will you even reach this function?

personally i would redirect users to their own controller and do any work before showing the view there

1 like
Lopsum's avatar

Hey @snapey. Thank you so much for your advice, it's really helpful :)

So :

  • I've removed the user login check. So I used the auth middleware in the routes call in web.php
  • I have removed the maintenance mode check
  • I created a Controller for each user role. Each controller has its own index() method

Here the results :

HomeController.php :

public function index()
{
    $user = auth()->user();
    $role = $user->roles()->first()->name;

    switch ($role) {
        case 'Webmaster':
            $webmaster = new \App\Http\Controllers\Webmaster\HomeController();
            return $webmaster->index();
        case 'Admin':
            $adminController = new \App\Http\Controllers\Admin\HomeController();
            return $adminController->index();
        case 'ContractCustomer':
            $contractCustomerController = new \App\Http\Controllers\ContractCustomer\HomeController();
            return $contractCustomerController->index($user);
        case 'BaseCustomer':
            $baseCustomerController = new \App\Http\Controllers\BaseCustomer\HomeController();
            return $baseCustomerController->index();
    }
}

Webmaster\HomeController.php :

public function index(): string {
        return view('webmaster.home')->render();
}

Admin\HomeController.php :

public function index(): string {

        $users = User::latest()->whereHas('roles', function ($q): void {
            $q->whereIn('id', [3, 4]);
        })->take(5)->get();

        $countUsers = (new \App\Models\User() )->countUsers();
        $countOrder = count(ExcelFile::all());

        return view('admin.index', ['users' => $users, 'cntUsers' => $countUsers, 'cntOrder' => $countOrder])->render();
    }

ContractCustomer\HomeController.php :

public function index($user)
{
    $excel = ExcelFile::all();
    $ApiID = $user->api->identifier;

    if (isset($ApiID)) {
        $getClientInfoAction = new GetClientInfoAction();

        $response = $getClientInfoAction->execute($ApiID);
        if ( ! $response) {
            $error = __("alerts.error.Your account does not exist or has been deactivated");
            Auth::guard('web')->logout();
            return redirect()->route('login')->withErrors($error);
        } elseif (true !== $response) {
            $error = __("alerts.error.Communication problem with our API, please try again later");
            Auth::guard('web')->logout();
            return redirect()->route('login')->withErrors($error);
        }

        return view('contractCustomer.home', ['excel' => $excel, 'fileFormat' => null])->render();
    }
}

BaseCustomer\HomeController.php :

public function index(): string {
        return view('particuliers.home')->render();
}

Does it feel cleaner?

Snapey's avatar

@Vable yes, although calling the controllers from a controller is generally a bad idea, and you lose out on the controller having its dependencies resolved by the framework.

I would have separate routes for each user type and redirect from the initial controller

1 like
Lopsum's avatar

Oh, I see ! But in my case, it's happening on the same URL (the home page). So I don't think I can redirect to multiple Controllers depending on the user's role... In that case, the simplest thing would be to put everything back into my HomeController?

Please or to participate in this conversation.