我正在创建一个 Kohana 模块,并在该模块内动态创建一条路线。我希望该路线优先于应用程序其余部分中的路线。 (特别是默认的、包罗万象的路由)。
关于如何做到这一点有什么想法吗?
谢谢!
====== 更新:
我想我忘了提及我正在动态加载模块,如下所示:
Kohana::modules(array_merge(array($module_name=>$directory), Kohana::modules()));
然后我对模块运行 HMVC 请求,如下所示:
$response = Request::factory('versioned-api')
->method('POST')
->secure(true)
->post(array('data'=>serialize($request))) // Performing a straightforward POST
->execute();
Kohana(截至 3.2)模块和路由优先级的一些背景:
Kohana::modules
的顺序进行初始化。根据所需的路由优先级,这一点很重要。在您的示例中,Kohana::modules(array_merge(array($module_name=>$directory), Kohana::modules()));
,已放置在 Kohana::modules()
中的任何模块都已被初始化。即使您将新模块合并到列表的开头,模块也会在调用 Kohana::modules()
时初始化。如果您查看“system/classes/kohana/core.php”第 565 行,您会注意到“init.php”需要一次(如果模块中存在)。 总而言之,Kohana 本身无法将路由推送到列表的开头。当然,保证首先加载有问题的模块可以解决您的问题(只要稍后路由不被覆盖)。如果您可以透明地扩展 Route,那么如果稍后通过将路由添加到堆栈的开头来加载模块,您可以通过以下方法来实现此目的:
GitHub Gist(包括单元测试):https://gist.github.com/3148737
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Route transparently extended. Place in "classes" directory of Kohana 3+ application or module.
*/
class Route extends Kohana_Route
{
/**
* Prepend Route to beginning of stack. If name already exists further in the stack, it is
* removed.
*
* Route::prepend('default', '(<controller>(/<action>(/<id>)))')
* ->defaults(array(
* 'controller' => 'welcome'
* ));
*
* @static
* @access public
* @param string route name
* @param string URI pattern
* @param array regex patterns for route keys
* @return Route
*/
public static function prepend($name, $uri_callback = NULL, $regex = NULL)
{
// Ensure entry does not already exist so it can be added to the beginning of the stack
if (isset(Route::$_routes[$name]))
{
unset(Route::$_routes[$name]);
}
// Create reference
Route::$_routes = array_merge(array($name => NULL), Route::$_routes);
// Overwrite reference
return Route::$_routes[$name] = new Route($uri_callback, $regex);
}
}
这是一个简单的路由示例:
// APPPATH/bootstrap.php
// define route before module loading
Route::set('route1', ...);
// load module list
Kohana::module(array(
'module1' => 'module1',
'module2' => 'module2',
));
Route::set('catch-all', ...);
module1 和 module2 在
mroute1
中都有自己的路由(mroute2
和 init.php
)。因此,Kohana 将使用以下路由顺序:
1. `route1` // defined in bootstrap before modules
2. `mroute1` // from first module
3. `mroute2` // from second module
4. `catch-all` // this one was loaded after all modules
catch-all
路由之后。Kohana::modules(array('module3' => 'module3') + Kohana::modules());
将重新排序您的模块,module3
将位于列表中的第一个。但是,这不会影响模块初始化的顺序。之前的所有 Kohana::modules
调用均已初始化。尽管该模块现在位于列表的开头,但它是在其他模块之后初始化的(请参阅 http://kohanaframework.org/3.2/guide/api/Kohana_Core#modules)。