我可以用Lumen获取中间件中的当前路由信息吗?

时间:2015-06-01 15:55:37

标签: php laravel lumen

我需要在中间件中找到当前找到的控制器和操作,以便我可以进行一些身份验证。但我发现这是不可能的,因为管道就像Middleware1 - > Middleware2->做调度 - > controller @ action() - > Middleware2 - > Middleware1。

因此在调度之前,我无法获得路线信息。在$ controller-> action()之后执行此操作绝对不对。

我做了一些研究并找到了这个。

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

但是在访问app/role/1之类的URI时这不起作用,因为$allRoutes只有app/role/{id}而不是app/role/1的索引。

有没有解决方法呢?

3 个答案:

答案 0 :(得分:4)

经过一番研究,我得到了解决方案。他们走了:

创建自定义调度程序

首先,你必须制作自己的自定义调度员,我的是:

App\Dispatcher\GroupCountBased

存储为:

app/Dispatcher/GroupCountBased.php

以下是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];
    }
}

在Laravel容器中注册自定义调度程序

然后,通过singleton()方法注册您自己的自定义调度程序。在之后注册所有路线!就我而言,我在bootstrap/app.php之后添加了自定义调度程序:

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

这就是它的样子:

/*
|--------------------------------------------------------------------------
| 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']);

调用中间件(UPDATE)

  

注意:我知道它并不优雅,因为在执行中间件后调用dispatch,您必须手动调度您的调度程序。

在您的中间件中,在handle方法中,执行以下操作:

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

示例:

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

用法

获取当前路线:

app('dispatcher')->current;

PoC

答案 1 :(得分:1)

我找到了这个问题的正确答案。我错过了一个名为routeMiddleware() Application的方法。此方法注册调度后调用的特定于路由的中间件。所以只需使用$app->routeMiddleware()注册中间件即可。并在中间件中通过$request->route()获取匹配的路由信息​​。

答案 2 :(得分:0)

$methodName = $request->getMethod();
$pathInfo = $request->getPathInfo();
$route = app()->router->getRoutes()[$methodName . $pathInfo]['action']['uses'];
$classNameAndAction = class_basename($route);
$className = explode('@', $classNameAndAction)[0];