Home > Software engineering >  laravel9 middleware not loaded when frontend and admin are seperated
laravel9 middleware not loaded when frontend and admin are seperated

Time:06-11

I am doing the separation of frontend and admin. After several days of studying, It seems ok now. My github: https://github.com/ronrun/laravel-multiauth
Currently there are 4 versions. There are 3 branches, the branch 9.x_two-tables has two version.

commit: frontend and admin login can login separately
The structure:

app\Http\Controller\Admin\Auth\LoginController.php
app\Http\Controller\Admin\DashboardController.php  
app\Http\Controller\Auth\LoginController.php
app\Http\Controller\HomeController.php

commit: more seperation!

app\Admin\Console
app\Admin\Exceptions
app\Admin\Http\Controllers
app\Admin\Http\Middleware
app\Admin\Providers
app\Frontend\Console
app\Frontend\Exceptions
app\Frontend\Http\Controllers
app\Frontend\Http\Middleware
app\Frontend\Providers
app\Models

In short, it's

app\Admin
app\Frontend
app\Models

During the studying process, lots of questions I want to ask. Now all seems working fine. But I still have questions about the final commit: more seperation!

Question: Many files inside app\Frontend not loaded, only app\Admin's files are used.
The two files:

app\Admin\Http\Middleware\Authenticate.php
app\Frontend\Http\Middleware\Authenticate.php

I expected that when I am not logged in, but visite a page should login, the Authenticate's redirectTo() should do the redirect work. But only Admin's Authenticate.php is loaded. I clear the content of Frontend's Authenticate.php, make it compeletly empty, NO ERRORS. But If I clear the content of Admin's Authenticate.php, it says this class cannot found.

I found the RedirectIfAuthenticated.php is the same. Then I delete frontend's middleware folder, still working fine, no errors.

Then I delete app\Frontend\Console, Exceptions, no errors. The login functions of Frontend and Admin both working. But app\Frontend\Providers cannot be deleted, or error shows.

bootstrap\app.php

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Frontend\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Frontend\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Frontend\Exceptions\Handler::class
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Admin\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Admin\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Admin\Exceptions\Handler::class
);

Why does it only loads files inside app\Admin ?
Why no errors, login logout functions still work, when many Frontend files are deleted?

Any suggestions to improve the codes, I'd appreciate it.

CodePudding user response:

To keep the frontend and admin separate, basically need:

  • separate routes file (say web.php, api.php & admin.php)
  • separate redirectTo routes in RedirectIfAuthenticated
  • separate redirectTo routes in Authenticate

To achieve that keep all default middleware & providers under app folder -

|-app
    |-Http
        |-Middleware
            -Authenticate.php
            -EncryptCookies.php
            -PreventRequestsDuringMaintenance.php
            -RedirectIfAuthenticated.php
            -TrimStrings.php
            -TrustHosts.php
            -TrustProxies.php
            -VerifyCsrfToken.php
    |-Providers
        -AppServiceProvider.php
        -AuthServiceProvider.php
        -BroadcastServiceProvider.php
        -EventServiceProvider.php
        -RouteServiceProvider.php
    |-Frontend
        |-Http
            |-Controllers
                |-FrontendControllers
            |-Middleware
                |-FrontendSpecificMiddleware (if any)
            |-Requests
                |-FrontendFormRequests (if any)
        |-Languages
        |-Other
    |-Admin
        |-Http
            |-Controllers
                |-AdminControllers
            |-Middleware
                |-AdminSpecificMiddleware (if any)
            |-Requests
                |-AdminFormRequests (if any)
        |-Languages
        |-Other
        |-routes
            |-web.php

To load routes, in App\Providers\RouteServiceProvider


    $this->routes(function () {
        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));

        Route::middleware('web')
            ->group(base_path('routes/web.php'));

        Route::middleware('web')
            ->prefix('admin')
            ->as('admin.')
            ->group(app_path('Admin/routes/web.php'));
    });

To set the redirect route for successful authentication

<?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @param  string|null  ...$guards
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;

        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {
                $prefix = $request->route()->getPrefix();
                return $prefix == '/admin' ? redirect(route('admin.home') : redirect(RouteServiceProvider::HOME);
            }
        }
        
        return $next($request);
    }
}

To set redirect route for unsuccessful authentication

<?php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
                $prefix = $request->route()->getPrefix();
                return $prefix == '/admin' ? route('admin.login') : route('login);
        }
    }
}

You can also have App\Frontend\FrontendServiceProvider and App\Admin\AdminServiceProvider if you want and register them under providers array in config/app.php

To summarise, take cue from Domain Driven Design (DDD) approach. You can read about DDD at:

Stitcher - Laravel Beyond Crud - Domain Oriented Laravel

Conciliating Laravel and DDD

  • Related