John Magnolia
John Magnolia

Reputation: 16823

Laravel get middleware for current route

How do you retrieve the middlewares for the current route?

I'm trying to set the exception handler to work differently based on if you're within a particular part of the website by checking if a middleware has been added to the route.

<?php

namespace App\Exceptions;

//use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Abrigham\LaravelEmailExceptions\Exceptions\EmailHandler as ExceptionHandler;

use Illuminate\Routing\Exceptions\InvalidSignatureException;
use Illuminate\Support\Facades\Route;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Throwable  $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $exception)
    {
        switch(true) {
            case $exception instanceof \Illuminate\Session\TokenMismatchException:
                // Redirect back if form invalid
                return redirect()
                    ->back()
                    ->withInput($request->except($this->dontFlash))
                    ->withErrors('The form has expired due to inactivity. Please try again');

                break;
            case $exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException:
                // Redirect back with message if model not found error
                $redirect = app('redirect');

                // Check for different url to prevent redirect loop
                if (request()->fullUrl() === $redirect->back()->getTargetUrl()){
                    
                    // $currentRouteMiddleware = request()->route()->controllerMiddleware() returns empty array
                    // $currentRouteMiddleware = Route::current()->router->getMiddleware(); router is private

                    $response = $redirect->to(isset($currentRouteMiddleware['admin.user']) ? '/admin' : '/');
                } else {
                    $response = $redirect->back();
                }

                return $response
                    ->withInput($request->except($this->dontFlash))
                    ->withErrors('That page could not be found. Please try again or report the broken link: ' . $request->getRequestUri());

                break;
        }

        return parent::render($request, $exception);
    }
}

If I dump the current route inside the router it shows the middleware array that I need to check against: dd(Route::current()) but there doesn't appear to be a way of accessing the current router e.g: $currentRouteMiddleware = Route::current()->router->getMiddleware();

route dump

Upvotes: 5

Views: 9429

Answers (4)

Rubens
Rubens

Reputation: 143

List middlewares applied in the current route inside App\Exceptions\Handler. Using in unauthenticated method.

/**
 * Convert an authentication exception into a response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Auth\AuthenticationException  $exception
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function unauthenticated($request, AuthenticationException $exception)
{
    return $request->expectsJson()
        ? response()->json(['message' => $exception->getMessage()], 401)
        : redirect()->guest(in_array('admin', $request->route()->middleware(), true) ? route('admin.login') : route('login'));
}

I used this to get the "admin" middleware and redirect the user to the correct login page.

Upvotes: 0

patricus
patricus

Reputation: 62368

There are a couple options based on what you're looking for.

If you want all the middleware aliases assigned to the route, you can use:

Route::current()->gatherMiddleware();

This does not expand assigned middleware groups, so the result from this might look something like:

[
    'web',
    'admin.user'
]

If you want all of the middleware classes assigned to the route, you can use:

Route::gatherRouteMiddleware(Route::current());

This will give you the classes, but it will not have the associated aliases or groups for the classes. The result from this might look like:

[
    "App\Http\Middleware\EncryptCookies",
    "Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse",
    "Illuminate\Session\Middleware\StartSession",
    "Illuminate\View\Middleware\ShareErrorsFromSession",
    "App\Http\Middleware\VerifyCsrfToken",
    "Illuminate\Routing\Middleware\SubstituteBindings",
    "TCG\Voyager\Http\Middleware\VoyagerAdminMiddleware"
]

Upvotes: 14

Been Kyung-yoon
Been Kyung-yoon

Reputation: 1764

The Route::getMiddleware() in the Handler is simply a list of \App\Http\Kernel::$routeMiddleware.

dd(Route::getMiddleware());

array:7 [▼
  "auth" => "App\Http\Middleware\Authenticate"
  "auth.basic" => "Illuminate\Auth\Middleware\AuthenticateWithBasicAuth"
  "guest" => "App\Http\Middleware\RedirectIfAuthenticated"
  "admin" => "App\Http\Middleware\AdminMiddleware"
  // ...
]

It is recommended to declare a constant (or global variable) and check whether the corresponding constant is declared in the Handler to check whether AdminMiddleware has passed.

// app/Http/Middleware/AdminMiddleware.php

    public function handle($request, Closure $next)
    {
        // if ... return ...

        define('__APP_IS_ADMIN', true);

        return $next($request);
    }
// app/Exceptions/Handler.php

    public function render($request, Exception $e)
    {
        // ...

        $response = $redirect->to(defined('__APP_IS_ADMIN') ? '/admin' : '/');

Upvotes: 2

zrkb
zrkb

Reputation: 116

request()->route()->controllerMiddleware();

Upvotes: 0

Related Questions