laravellaravel-6laravel-7laravel-authorizationlaravel-authentication

How to use One Laravel Controller with Multiple Guard instead of Duplicating the Controller


I have two Guards

Admin
User

Also i have created controllers where user can manage his own data and admin can also manage user data. So i created two Controllers

Controllers
    Admin
        EducatonBackgroundController
    User
        EducationBackgroundController

In User/EducationBackgroundController i have this function which fetch education background of a current logged user and display on the user view

 public function index(Education $education)
    {
        try {
            $educations = $education->where('user_id',$this->userLoggedID())->with('organization','program','country','city')->get();
            return view('users.education.index',compact('educations'));
        }
        catch (Exception $e) {
            abort(404);
        }
    }

In Admin/EducationBackgroundController i have this function which fetch education background of all users and display on the admin view

 public function index(Education $education)
    {
        try {
            $educations = $education->with('organization','program','country','city','user')->get();
            return view('admin.users.education.index',compact('educations'));
        }
        catch (Exception $e) {
            abort(404);
        }
    }

From observation these functions are similar but differ on view return and data fetch.

So How can i create a one Controller which can be used by both Admin and User guards instead of duplicate Controller and View for both Guards.


Solution

  • I did something similar by adding a second set of routes, like this:

    <?php
    
        Route::middleware(['auth:admin_api'])->group(function () {
            Route::prefix('admin')->group(function () {
                Route::name('api.admin.')->group(function () {
    
                    ////////////////////////////////////////////////////////////
                    /// PLACE ADMIN API ROUTES HERE ////////////////////////////
                    ////////////////////////////////////////////////////////////
                    Route::apiResource('test','App\Http\Controllers\API\MyController');
                    ////////////////////////////////////////////////////////////
                });
            });
        });
    
        Route::middleware(['auth:api'])->group(function () {
            Route::name('api.')->group(function () {
                ////////////////////////////////////////////////////////////
                /// PLACE PUBLIC API ROUTES HERE ///////////////////////////
                ////////////////////////////////////////////////////////////
                Route::apiResource('test', 'App\Http\Controllers\API\MyController');
                ////////////////////////////////////////////////////////////
            });
        });
    
    

    So when an admin user goes to admin/test, it uses the admin auth guard, and when a normal user goes to /test it uses the standard auth guard. Both of these use the same controller.

    I then created a base controller for my app. Here is how I determined with guard is being used to access the route in the constructor:

    <?php
    
    
    use Illuminate\Http\Response;
    use App\Http\Controllers\Controller;
    
    class BaseController extends Controller
    {
        protected $user;
    
        protected $isAdmin = false;
    
        public function __construct()
        {
            if(Auth::guard('admin_api')->check()) {
                $this->user = Auth::guard('admin_api')->user();
                $this->isAdmin = true;
            } elseif(Auth::guard('api')->check()) {
                $this->user = Auth::guard('api')->user();
                $this->isAdmin = false;
            } else {
                return response()->json([
                    'message' => 'Not Authorized',
                ], 401);
            }
        }