在Slim3控制器的类构造函数中访问当前路由名称

时间:2016-01-18 16:39:21

标签: php slim slim-3

使用Slim我对我的控制器进行分组,并且通常有一个抽象的BaseController我为每个组扩展。我使用基于类的路由:

/* SLIM 2.0 */
// Users API - extends BaseApiController
$app->post('/users/insert/'   , 'Controller\Api\UserApiController:insert');
.
.
// Campaigns - extends BaseAdminController
$app->get('/campaigns/', 'Controller\CampaignController:index')->name('campaigns');

并且需要密码保护一些路由,有时我需要稍微不同的配置。 BaseApiController,BaseAdminController ...等等。有时候我需要知道我在哪条路线,所以我可以为那条路线执行某种行为。在这些情况下,我会有一个像这样的辅助函数:

/* SLIM 2.0 */
// returns the current route's name
function getRouteName()
{
    return Slim\Slim::getInstance()->router()->getCurrentRoute()->getName();
}

这将为我提供当前正在使用的路线名称。所以我可以做点像......

namespace Controller;
abstract class BaseController
{
    public function __construct()
    {
        /* SLIM 2.0 */
        // Do not force to login page if in the following routes
        if(!in_array(getRouteName(), ['login', 'register', 'sign-out']))
        {
            header('Location: ' . urlFor('login'));
        }
    }
}

我找不到访问正在执行的路由名称的方法。我找到了这个链接

Slim 3 get current route in middleware

但是当我尝试

时我得到NULL
$request->getAttribute('routeInfo');

我也尝试过建议:

'determineRouteBeforeAppMiddleware' => true

我已经检查了每个Slim3对象的属性和方法,我似乎找不到Slim3的等价物,或者可以访问命名路径。看起来Slim3甚至没有跟踪它执行的路线,它只是......执行它。

这些是路由器类具有的以下方法,我怀疑这个值是:

//get_class_methods($container->get('router'));

setBasePath
map
dispatch
setDispatcher
getRoutes
getNamedRoute
pushGroup
popGroup
lookupRoute
relativePathFor
pathFor
urlFor

我希望有人做过类似的事情。当然,还有其他一些hacky方法可以做到这一点(我现在已经考虑过了一些),但我更喜欢使用Slim给我这些数据。任何想法?

注意:我知道你可以用中间件做到这一点,但是我正在寻找一种不需要中间件的解决方案。我可以在被触发路由实例化的类中使用的东西。有可能Slim2,希望Slim3有类似的功能。

3 个答案:

答案 0 :(得分:4)

可通过request对象获取,如下所示:

$request->getAttribute('route')->getName();

更多详细信息here

控制器中的方法都会接受请求和响应作为参数 - slim会为您传递它们,例如在您的insert()方法中:

use \Psr\Http\Message\ServerRequestInterface as request;

class UserApiController {
    public function insert( request $request ) {

    // handle request here, or pass it on to a getRouteName() method

    }
}

答案 1 :(得分:2)

在玩完之后我找到了办法。它可能不是最有效的方式,但它可以工作,虽然它使用中间件来实现这一点,但我认为还有其他应用程序可以在中间件中与控制器类共享数据。

首先,您创建一个中间件但使用"类:方法"字符串就像你在路线中一样。无论你喜欢什么,都可以命名。

//Middleware to get route name
$app->add('\Middleware\RouteMiddleware:getName');

然后你的中间件:

// RouteMiddleware.php

namespace Middleware;
class RouteMiddleware
{
    protected $c; // container

    public function __construct($c)
    {
        $this->c = $c; // store the instance as a property
    }

    public function getName($request, $response, $next)
    {
        // create a new property in the container to hold the route name
        // for later use in ANY controller constructor being 
        // instantiated by the router

        $this->c['currentRoute'] = $request->getAttribute('route')->getName();
        return $next($request, $response);
    }
}

然后在您的路线中创建一个带有路线名称的路线,在这种情况下,我将使用" homePage"作为名称

// routes.php
$app->get('/home/', 'Controller\HomeController:index')->setName('homePage');

在你的班级管理员中

// HomeController.php
namespace Controller;
class HomeController
{
    public function __construct($c)
    {
     $c->get('currentRoute'); // will give you "homePage"
    }
}

这将允许您执行更多操作,然后只需获取路由名称,您还可以将值从中间件传递到类构造函数。

如果其他人有更好的解决方案,请分享!

答案 2 :(得分:-1)

$app->getCurrentRoute()->getName();
$request->getAttribute('route')->getName();