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 在中间件中获取当前路由

但是当我尝试时我得到 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 有类似的功能。

4

3 回答 3

4

它可以通过request对象获得,如下所示:

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

此处提供了更多详细信息

您的控制器中的方法都将接受请求和响应作为参数 - 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

    }
}
于 2016-01-18T16:57:22.023 回答
4

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

首先,您创建一个中间件,但您使用“Class:Method”字符串,就像在路由中一样。随便取个名字就行。

//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);
    }
}

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

// 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"
    }
}

这将允许您做更多的事情,而不仅仅是获取路由名称,您还可以将值从中间件传递给您的类构造函数。

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

于 2016-01-19T20:22:32.680 回答
-1
$app->getCurrentRoute()->getName();
$request->getAttribute('route')->getName();
于 2016-01-26T15:56:21.503 回答