Can I get current route information in middleware with Lumen?

谁说胖子不能爱 提交于 2019-12-23 16:51:14

问题


I need to have the current found controller and action in a middleware, so that I can do some authentication. But I found it impossible, because the pipe is like Middleware1 -> Middleware2-> do the dispatching -> controller@action() -> Middleware2 -> Middleware1.

Therefore before the dispatching, I cannot get the route info. It is definitely not right to do it after the $controller->action().

I did some research and found this.

$allRoutes = $this->app->getRoutes();
$method = \Request::getMethod();
$pathInfo = \Request::getPathInfo();
$currentRoute = $allRoutes[$method.$pathInfo]['action']['uses'];

But this does not work when visiting URI like app/role/1, because $allRoutes only have index of app/role/{id} instead of app/role/1.

Is there any workaround about this?


回答1:


After do some research, I got solution. Here they go:

Create Custom Dispatcher

First, you have to make your own custom dispatcher, mine is:

App\Dispatcher\GroupCountBased

Stored as:

app/Dispatcher/GroupCountBased.php

Here's the content of GroupCountBased:

<?php namespace App\Dispatcher;

use FastRoute\Dispatcher\GroupCountBased as BaseGroupCountBased;

class GroupCountBased extends BaseGroupCountBased
{
    public $current;

    protected function dispatchVariableRoute($routeData, $uri) {
        foreach ($routeData as $data) {
            if (!preg_match($data['regex'], $uri, $matches)) continue;

            list($handler, $varNames) = $data['routeMap'][count($matches)];

            $vars = [];
            $i = 0;

            foreach ($varNames as $varName) {
                $vars[$varName] = $matches[++$i];
            }

            // HERE WE SET OUR CURRENT ROUTE INFORMATION
            $this->current = [
                'handler' => $handler,
                'args' => $vars,
            ];

            return [self::FOUND, $handler, $vars];
        }

        return [self::NOT_FOUND];
    }
}

Register Your Custom Dispatcher in Laravel Container

Then, register your own custom dispatcher via singleton() method. Do this after you register all your routes! In my case, I add custom dispatcher in bootstrap/app.php after this line:

require __DIR__.'/../app/Http/routes.php';

This is what it looks like:

/*
|--------------------------------------------------------------------------
| Load The Application Routes
|--------------------------------------------------------------------------
|
| Next we will include the routes file so that they can all be added to
| the application. This will provide all of the URLs the application
| can respond to, as well as the controllers that may handle them.
|
*/

require __DIR__.'/../app/Http/routes.php';

// REGISTER YOUR CUSTOM DISPATCHER IN LARAVEL CONTAINER VIA SINGLETON METHOD
$app->singleton('dispatcher', function () use ($app) {
    return FastRoute\simpleDispatcher(function ($r) use ($app) {
        foreach ($app->getRoutes() as $route) {
            $r->addRoute($route['method'], $route['uri'], $route['action']);
        }
    }, [
        'dispatcher' => 'App\\Dispatcher\\GroupCountBased',
    ]);
});

// SET YOUR CUSTOM DISPATCHER IN APPLICATION CONTEXT
$app->setDispatcher($app['dispatcher']);

Call In Middleware (UPDATE)

NOTE: I understand it's not elegant, since dispatch called after middleware executed, you must dispatch your dispatcher manually.

In your middleware, inside your handle method, do this:

app('dispatcher')->dispatch($request->getMethod(), $request->getPathInfo());

Example:

public function handle($request, Closure $next)
{
    app('dispatcher')->dispatch($request->getMethod(), $request->getPathInfo());
    dd(app('dispatcher')->current);
    return $next($request);
}

Usage

To get your current route:

app('dispatcher')->current;




回答2:


I found the correct answer to this problem. I missed one method named routeMiddleware() of Application. This method registers the route-specific middleware which is invoked after dispatching. So Just use $app->routeMiddleware() to register you middleware. And get the matched route info by $request->route() in your middleware.



来源:https://stackoverflow.com/questions/30577949/can-i-get-current-route-information-in-middleware-with-lumen

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!