Slim 3 получает текущий маршрут в промежуточном ПО

Я хочу получить имя текущего маршрута в классе промежуточного программного обеспечения. Ранее (в Slim 2.*) вы могли получить текущий маршрут следующим образом:

$route = $this->app->router->getCurrentRoute();

Но эта функция была удалена в версии 3.0 Slim. Я нашел следующий код в __invoke метод Slim\App:

    // Get the route info
    $routeInfo = $request->getAttribute('routeInfo');

    /** @var \Slim\Interfaces\RouterInterface $router */
    $router = $this->container->get('router');

    // If router hasn't been dispatched or the URI changed then dispatch
    if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) {
        $request = $this->dispatchRouterAndPrepareRoute($request, $router);
        $routeInfo = $request->getAttribute('routeInfo');
    }

Это указывает на то, что текущий маршрут хранится как атрибут routeInfo в Request, Но кажется, что мой пользовательский класс промежуточного программного обеспечения вызывается до того, как атрибут установлен ($this->dispatchRouterAndPrepareRoute($request, $router); метод). Потому что зовет $request->getAttribute('routeInfo') решает в NULL,

Итак, мой вопрос: как я могу получить текущий маршрут (или название маршрута) из функции / класса промежуточного программного обеспечения?

Или я должен просто скопировать фрагмент кода из Slim\App?

6 ответов

Решение

Для Slim3, вот пример, показывающий, как получить информацию о маршрутизации из промежуточного программного обеспечения, которая на самом деле представляет собой комбинацию предыдущих ответов вместе взятых.

<?php

$slimSettings = array('determineRouteBeforeAppMiddleware' => true);

// This is not necessary for this answer, but very useful
if (ENVIRONMENT == "dev")
{
    $slimSettings['displayErrorDetails'] = true;
}

$slimConfig = array('settings' => $slimSettings);
$app = new \Slim\App($slimConfig);


$myMiddleware = function ($request, $response, $next) {

    $route = $request->getAttribute('route');
    $routeName = $route->getName();
    $groups = $route->getGroups();
    $methods = $route->getMethods();
    $arguments = $route->getArguments();

    print "Route Info: " . print_r($route, true);
    print "Route Name: " . print_r($routeName, true);
    print "Route Groups: " . print_r($groups, true);
    print "Route Methods: " . print_r($methods, true);
    print "Route Arguments: " . print_r($arguments, true);
};

// Define app routes
$app->add($myMiddleware);


$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
    # put some code here....
})

В моем случае я хотел добавить промежуточное программное обеспечение, которое обеспечивало бы вход пользователя в систему на определенных маршрутах, и перенаправлять его на страницу входа, если это не так. Я нашел самый простой способ сделать это, чтобы использовать ->setName() на маршрутах вот так:

$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
    return $response->withRedirect('/home');
})->setName('index');

Тогда, если этот маршрут был согласован, $routeName в примере промежуточного программного обеспечения будет "index", Затем я определил список массивов маршрутов, которые не требуют аутентификации, и проверил, был ли текущий маршрут в этом списке. Например

if (!in_array($routeName, $publicRoutesArray))
{
    # @TODO - check user logged in and redirect if not.
}
$request->getUri()->getPath()

Получить текущий маршрут, даже в middleware,

Очевидно, вы можете настроить Slim для определения маршрута перед переходом в промежуточное ПО с помощью этого параметра:

$app = new Slim\App([
    'settings'  => [
        'determineRouteBeforeAppMiddleware' => true,
    ]
]);

Я не уверен, какое влияние это оказывает, но это работает для меня:)

Предоставляет ли следующее достаточную информацию, которая вам требуется, или вам также нужен бит запроса в routeInfo?

$app->getContainer()->get('router')->dispatch($req);

Если вам также требуется бит "запрос", то вам нужно будет сделать то же самое вручную dispatchRouterAndPrepareRoute делает.

if ($routeInfo[0] === Dispatcher::FOUND) {
            $routeArguments = [];
            foreach ($routeInfo[2] as $k => $v) {
                $routeArguments[$k] = urldecode($v);
            }

            $route = $router->lookupRoute($routeInfo[1]);
            $route->prepare($request, $routeArguments);

            // add route to the request's attributes in case a middleware or handler needs access to the route
            $request = $request->withAttribute('route', $route);
        }

        $routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()];

Надеюсь это поможет.

Вот как вы получаете текущий маршрут в промежуточном программном обеспечении в Slim Framework 3:

$routeInfo = $request->getAttribute('routeInfo');

Обратите внимание, что вы должны использовать это внутри __invoke() функционировать в вашем промежуточном программном обеспечении. Вот пример использования:

public function __invoke($request, $response, $next)
    {
        ....
        $routeInfo = $request->getAttribute('routeInfo');
        ....
    }

$ routeInfo должен содержать такой объект, как:

{
    "0": 1,
    "1": "route6",
    "2": {
      "name": "loremipsum"
    },
    "request": [
      "POST",
      "http://example.org/loremipsum"
    ]
  }

Если вы используете Slim 4, попробуйте следующее:

      $route = $request->getAttribute('username');

Рабочий пример:

      $app->post('/test/[{username}]', function(Request $request, Response $response, $args){

$route = $request->getAttribute('username');
$response->getBody()->write(json_encode($route));
return $response->withHeader('Content-type', 'application/json')->withStatus(201);});

Подробнее о маршрутизации в Slim 4: https://akrabat.com/routing-in-slim-4/

Другие вопросы по тегам