2016-01-18 70 views
2

使用Slim對我的控制器進行分組,並且通常爲每個組擴展一個抽象的BaseController。我使用基於類的路由:在Slim3控制器的類構造函數中訪問當前的路由名稱

/* 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等等。有時我需要知道我在哪條路線,所以我可以爲那條路線執行某種行爲。在這些情況下,我會有一個幫手功能,如下所示:

這會給我當前正在使用的路由名稱。所以我可以做類似...

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

,但我得到空當我嘗試

$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 

我希望有人做過類似的事情。當然,還有其他一些可以做到這一點的方法(我現在已經在考慮一些),但我更喜歡使用Slim來給我這些數據。有任何想法嗎?

注:我知道你可以用中間件做到這一點,但是我正在尋找一個不需要中間件的解決方案。在觸發路線實例化的類中可以使用的東西。 Slim2有可能會希望Slim3具有類似的功能。

回答

3

它可以通過request對象,像這樣:

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

提供更多的細節here

在你的控制器都將接受請求和響應作爲參數的方法 - 苗條將通過他們通過對你,所以例如在你的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 

    } 
} 
+0

儘管這個工作使用中間件,但它不能在觸發路由時實例化的類內工作。另外作爲一個附註,您必須將 'determineRouteBeforeAppMiddleware'的配置值設置爲true,才能使其在中間件中運行。不幸的是,這在我的情況下不起作用 – Eko3alpha

+0

@ Eko3alpha我更新了我的答案,更詳細地介紹瞭如何訪問控制器中的'$ request'。我不是苗條的專家,所以可能會有更好的方法,但這是我如何做到的。 – danjam

+0

有一些事情......當一個路由實例化一個類,在你的示例UserApiController中,它將Slim \ Container的一個實例傳遞給類__constructor,然後執行插入方法。然而,Slim3默認將3個參數傳遞給每個方法,Slim \ Http \ Request對象,Slim \ Http \ Response對象以及路由中捕獲的{參數}數組(如果有的話)。由於第一個參數Slim \ Http \ Request已經實現了\ Psr \ Http \ Message \ ServerRequestInterface,因此代碼段中的use語句是冗餘的。不幸的是,這仍然沒有幫助我的情況 – Eko3alpha

1

玩過後,我發現一種方法來做到這一點。它可能並不是最有效的方式,但它的工作原理,雖然它使用中間件來實現這一點,但我認爲還有其他應用程序可以在控制器類中共享中間件中的數據。

首先,您將創建一箇中間件,但您可以像使用路由一樣使用「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" 
    } 
} 

這可以讓你做更多的事情,然後獲取路由名稱,也可以將值從中間件傳遞給你的類構造函數。

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

+0

剛剛重訪了這個,不知道有可能用Class來連接中間件:方法 - 非常方便 – danjam

-1
$app->getCurrentRoute()->getName(); 
$request->getAttribute('route')->getName(); 
相關問題