Laravel有一个了不起的路由系统,但我特别挣扎了一点。
我想删除为路由定义控制器时创建的额外可选路由。
在Laravel 3中,您显然可以执行以下操作,但从未使用过v3我不知道这是否是我正在寻找的,无论如何,它在v4中都不起作用。
Router::$segments = 0;
例如,当我像这样定义我的路线时:
Route::group(array('prefix' => 'monitoring'), function() {
// Handle hosts
Route::controller('hosts/', 'Apm\Controllers\Monitoring\Hosts\Index');
Route::controller('hosts/{host}', 'Apm\Controllers\Monitoring\Hosts\Host');
Route::controller('hosts/{host}/{service}', 'Apm\Controllers\Monitoring\Hosts\Service');
});
我的路线将在artisan routes
命令中显示如下:
+--------+------------------------------------------------------------------------------------------------+------+---------------------------------------------------------+----------------+---------------+
| Domain | URI | Name | Action | Before Filters | After Filters |
+--------+------------------------------------------------------------------------------------------------+------+---------------------------------------------------------+----------------+---------------+
| | GET|HEAD / | | Closure | | |
| | GET|HEAD monitoring/hosts/status/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Index@getStatus | | |
| | GET|HEAD monitoring/hosts/details/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Index@getDetails | | |
| | GET|HEAD monitoring/hosts/report/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Index@getReport | | |
| | GET|HEAD monitoring/hosts/thresholds/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Index@getThresholds | | |
| | GET|HEAD monitoring/hosts/timeline/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Index@getTimeline | | |
| | GET|HEAD monitoring/hosts/index/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Index@getIndex | | |
| | GET|HEAD monitoring/hosts | | Apm\Controllers\Monitoring\Hosts\Index@getIndex | | |
| | GET|HEAD monitoring/hosts/{host}/status/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Host@getStatus | | |
| | GET|HEAD monitoring/hosts/{host}/details/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Host@getDetails | | |
| | GET|HEAD monitoring/hosts/{host}/report/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Host@getReport | | |
| | GET|HEAD monitoring/hosts/{host}/thresholds/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Host@getThresholds | | |
| | GET|HEAD monitoring/hosts/{host}/timeline/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Host@getTimeline | | |
| | GET|HEAD monitoring/hosts/{host}/index/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Host@getIndex | | |
| | GET|HEAD monitoring/hosts/{host} | | Apm\Controllers\Monitoring\Hosts\Host@getIndex | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/status/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getStatus | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/details/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getDetails | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/report/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getReport | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/thresholds/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getThresholds | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/timeline/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getTimeline | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/self-healing/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getSelfHealing | | |
| | GET|HEAD monitoring/hosts/{host}/{service}/index/{one?}/{two?}/{three?}/{four?}/{five?} | | Apm\Controllers\Monitoring\Hosts\Service@getIndex | | |
| | GET|HEAD monitoring/hosts/{host}/{service} | | Apm\Controllers\Monitoring\Hosts\Service@getIndex | | |
简单地说,我想摆脱{one?}/{two?}/{three?}/{four?}/{five?}
部分,因为我总能预测我的参数,而且我经常想要指定必须使用的控制器并命名它们。
更新
我们决定不隐式列出所有路由,因为这会使我们的routes.php极度膨胀(如果不是数千条路线就必须制作数百条)。除了路由器解析的额外参数之外,控制器设置就像我们现在完美地工作一样,当隐式定义具有Route::get
的路由时,这些参数不存在。
我应该提一下,我们稍微修改了Router
类,以便能够使子资源成为可能。
答案 0 :(得分:1)
要回答我自己的问题,我们已经做的是对Router
类进行覆盖。我现在明白这也是解决这个问题的关键。
Route::controller
基本上允许您将其中的所有方法隐式注册为路由的终点。如上所述,这不是您通常要做的事情,但我们在采取这种方式之前做出了明智的决定。为了解决不能正确地说哪些参数可以传递给函数的问题,他们添加了这些5'通配符'参数。我们在问题中使用类,这些参数不是必需的。
我想指出,使用ReflectionMethod::getParameters
可能会使用更多反射法来解决这个问题。虽然,也有很多人可以反对使用类似的东西。
所以,正如您可能已经猜到的那样,简而言之,Laravel使用您传递给Route::controller
的类的反射类,并以这种方式从代码中提取路径端点。
参数被添加到类Illuminate\Routing\ControllerInspector@addUriWildcards
中,因此为了防止添加这些参数,我们需要覆盖此类。因为此类已实例化,然后在Illuminate\Routing\Router
类中使用,我们还需要覆盖Router
。
在Laravel中,您需要创建IoC container来为核心类创建覆盖。对于Router
,这没有什么不同。虽然标准文档(目前)并不是特别清楚如何做到这一点。
(我们实现了psr-4并将名称空间Apm
设置为app/
以自动加载我的类)
在app/Lib/Routing/RoutingServiceProvider.php
<?php namespace Apm\Lib\Routing;
use Illuminate\Routing\RoutingServiceProvider as LaravelRoutingServiceProvider;
class RoutingServiceProvider extends LaravelRoutingServiceProvider
{
protected function registerRouter()
{
$this->app['router'] = $this->app->share(function($app)
{
$router = new Router($app['events'], $app);
// If the current application environment is "testing", we will disable the
// routing filters, since they can be tested independently of the routes
// and just get in the way of our typical controller testing concerns.
if ($app['env'] == 'testing')
{
$router->disableFilters();
}
return $router;
});
}
}
这将路由器类设置为Apm\Lib\Routing\Router
,替换Illuminate\Routing\Router
。
所以app/Lib/Routing/Router.php
我们有
<?php namespace Apm\Lib\Routing;
use Illuminate\Routing\Router as LaravelRouter;
class Router extends LaravelRouter
{
/**
* Get a controller inspector instance.
*
* @return \Apm\Lib\Routing\ControllerInspector
*/
public function getInspector()
{
return $this->inspector ?: $this->inspector = new ControllerInspector;
}
}
将Controller Inspector设置为Apm\Lib\Routing\ControllerInspector
而不是Illuminate\Routing\ControllerInspector
。
最后在app/Lib/Routing/ControllerInspector.php
我们有:
<?php namespace Apm\Lib\Routing;
use Illuminate\Routing\ControllerInspector as LaravelControllerInspector;
class ControllerInspector extends LaravelControllerInspector
{
/**
* Add wildcards to the given URI.
*
* @param string $uri
* @return string
*/
public function addUriWildcards($uri)
{
return $uri;//.'/{one?}/{two?}/{three?}/{four?}/{five?}';
}
}
然后为了确保Laravel使用我们的类而不是它自己的类,我们需要在app/config/app.php
数组的'providers'
中注册服务提供者。
'providers' => array(
'Apm\Lib\Routing\RoutingServiceProvider',
),
当然,以某种方式能够明确地传递要用于每个端点/函数方法的参数会更好,但是这会破坏隐式设置端点的点。
如果仍然使用此机制,您可能希望更进一步,根据方法接受的参数获取/使用路径参数。虽然没有添加已在被检查控制器的基本路径模式中设置的参数。
Enfin,这解决了我们的问题,因为我们不需要在任何地方添加到路线末尾的参数。
答案 1 :(得分:0)
我不熟悉您可以摆脱这些额外参数的方法,但使用隐式路由不被视为最佳做法,可能会导致许多问题。查看this post了解详情。如果您可以预测参数,我认为最好用Route::get
等明确定义您的路线。