Тонкий PHP-маршрут в промежуточном ПО

В Slim можно получить текущий маршрут в промежуточном программном обеспечении?

class Auth extends \Slim\Middleware{
  public function call(){ 
    $currentRoute = $this->app->getRoute(); // Something like this?
  }
}

Я знаю, что вы можете вызвать $app->router()->getCurrentRoute() после вызова slim.before.dispatch, но когда вы вызываете это из промежуточного слоя, он возвращает не-объект. Любая помощь будет принята с благодарностью.

Ответы

Ответ 1

Да и нет. Если вы посмотрите на исходный код для Slim, вы увидите, что зарегистрированные Middlewares вызываются в порядке LIFO, когда вызывается метод Slim::run, а затем Slim запускает собственный метод "вызова", где начинается обработка запроса. Именно в этом методе Slim анализирует и обрабатывает маршрут. В этом случае вы не можете получить доступ к $app->router()->getCurrentRoute() в методе Middleware::call, потому что он еще не был проанализирован и определен.

Единственный способ сделать это - зарегистрировать слушателя на slim.before.dispatch внутри вашего промежуточного ПО и реализовать все, что вы хотите сделать в этом методе.

Из имени вашего класса я предполагаю, что вы пытаетесь создать базовый модуль аутентификации? Раньше я делал что-то подобное, и это выглядело примерно так:

class AuthMiddleware extends \Slim\Middleware
{
    public function call()
    {
        $this->app->hook('slim.before.dispatch', array($this, 'onBeforeDispatch'));

        $this->next->call();
    }

    public function onBeforeDispatch()
    {
        $route = $this->app->router()->getCurrentRoute();

        //Here I check if the route is "protected" some how, and if it is, check the
        //user has permission, if not, throw either 404 or redirect.

        if (is_route_protected() && !user_has_permission())
        {
            $this->app->redirect('/login?return=' . urlencode(filter_input(INPUT_SERVER, 'REQUEST_URI')));
        }
    }
}

В этом примере метод onBeforeDispatch будет запущен до того, как будут обработаны обработчики маршрута. Если вы посмотрите на исходный код, вы увидите, что события запускаются внутри блока try/catch, который прослушивает исключения, создаваемые $app->redirect() и $app->pass(), и т.д. Это означает, что мы можем реализовать нашу логику проверки/перенаправления здесь как если бы это была функция обработчика маршрута.

Выше is_route_protected и user_has_permission - это просто псевдокод, чтобы проиллюстрировать, как работает мое промежуточное ПО. Я структурировал класс, чтобы вы могли указать список маршрутов или регулярное выражение для маршрутов в защищенном конструкторе Middleware, а также передать объект службы, который реализовал проверку прав пользователя и т.д. Надеюсь, что это поможет.

Ответ 2

Существует альтернативный способ сделать это, поскольку я был в той же ситуации. То, что я хотел избежать, было сопоставить что-либо по маршруту и ​​вместо этого хотело использовать имена маршрутов, поэтому вы можете попробовать следующее:

public function call() {

    $routeIWantToCheckAgainst = $this->slimApp->router()->urlFor('my.route.name');
    $requestRoute = $this->slimApp->request()->getPathInfo();
    if ($routeIWantToCheckAgainst !== $requestRoute) {
        // Do stuff you need to in here
    }

    $this->next->call();
}

У вас может даже быть массив маршрутов, на которые вы НЕ хотите, чтобы промежуточное ПО запускалось, а затем просто проверьте, является ли оно in_array() и т.д., а если нет, сделайте то, что вам нужно.

Ответ 3

Вы должны использовать app- > request() → getPathInfo() вместо app- > getRoute().

class Auth extends \Slim\Middleware{
    public function call(){ 
        $currentRoute = $this->app->request()->getPathInfo();
    }
}