我有一个路由为:
((?<directory>'w+)/?)?((?<controller>'w+)/?)?((?<action>'w+)/?)?((?<id>'d+))?
它工作得很好,但它导致我的系统必须包括到子路由的所有路由的默认控制器(索引)。例如,如果我的页面URI是/blog/post
(其中博客是目录,帖子是操作),那么我的实际URI必须是blog/index/post
——我希望能够回到只使用blog/post
。
所以,我希望它被路由到:
directory = blog
controller = index
action = post
显然,当第二个参数实际上是控制器时,这会导致问题。例如,directory/controller/action
将被不正确地路由。
有没有一种路由方法可以检测有三个单词参数,可能后面跟着一个数字参数,这可以满足我的需求?
用于粘土化:
param/param/param(?/id)
将为:directory/controller/action(/id)
param/param(?/id)
将为:directory/default_controller/action(/id)
我真的认为你想用blog/post
来别名blog/index/post
;将其作为一条路线插入到您拥有的"包罗万象"路线之前;"一刀切"的方法并不总是最好的。特别是,如果您只有1个这样的特定用例。
编辑:
"科哈纳的路线系统"令人望而生畏;无法理解他们试图在那里生下的大象。。。以下是其他一些建议:
- 将此问题告知制造商;这无疑是一个常见问题
-
乱用正则表达式模式。这里有一个可能有用的片段(我把它放在PHP测试用例中,但你可以很容易地将其解耦)
public function testRoutePatterns(){ $data = array( array( //most specific: word/word/word/id '~^(?P<directory>'w+)/(?P<controller>'w+)/(?P<action>'w+)/(?P<id>.*)$~i', 'myModule/blog/post/some-id', array('directory'=>'myModule', 'controller'=>'blog', 'action'=>'post', 'id'=>'some-id'), true ), array( //less specific: word/word/id '~^(?P<directory>'w+)/(?P<action>'w+)/(?P<id>.*)$~i', 'blog/post/some-id', array('directory'=>'blog', 'action'=>'post'), //need to inject "index" controller via "defaults()" here i guess true ), ); foreach ($data as $d) { $matches = array(); list($pattern, $subject, $expected, $bool) = $d; $actual = (bool) preg_match($pattern, $subject, $matches); $this->assertEquals($bool, $actual); //assert matching $this->assertEquals(array(), array_diff($expected, $matches)); //$expected contained in $matches } }
正如这个答案所解释的,如果你有这样的路线:
Route::set('route_name', 'directory/controller/action')
->defaults(array(
'directory' => 'biz',
'controller' => 'foo',
'action' => 'bar',
));
你应该有这样的目录结构:
/application/classes/controller/biz/foo.php