2012-07-19 101 views
0

我创建一个Kohana模块,并在该模块中动态创建一个路由。我希望路线优先于其他应用中的路线。 (特别是默认的,通用路线)。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(); 

回答

3

上Kohana的一些背景(如3.2)模块和路由的优先级:

  1. 模块在顺序Kohana::modules初始化被调用。基于期望的路线优先权,这很重要。在你的例子中,Kohana::modules(array_merge(array($module_name=>$directory), Kohana::modules()));,已经放置在Kohana::modules()中的任何模块已经被初始化。即使您正在将新模块合并到列表的开头,模块也会被初始化为Kohana::modules()。如果您查看“system/classes/kohana/core.php”第565行,您会注意到“init.php”只需要一次(如果存在于模块中)。
  2. 路由按照它们添加的顺序进行匹配。如果使用相同的路由名称,它们也会被覆盖。

总之,Kohana本身并没有将路线推到列表的开头。当然,保证首先加载相关模块将解决您的问题(只要稍后不会覆盖路由)。如果你能透明地扩展路线,下面是如果模块通过预先的路线到堆栈的开头加载以后你可以如何做到这一点:

GitHub的要点(包括单元测试):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); 
    } 
} 
+0

哇!这比我想出的要优雅得多。我要回到这个并且以这种方式实现!最后,我创建了一个类似的地方,创建了一个Route类并覆盖了set函数,在这个函数中使用了static :: $ _ routes,array_reverse'd它们,做了一个parent :: set(),然后将它们反转回去。 但我更喜欢你的解决方案。谢谢! – 2012-07-20 08:05:12

+0

太棒了!实施时,请务必查看上述Gist中的单元测试覆盖率。乐意效劳! – michealmorgan 2012-07-20 08:16:22

2

下面是一个简单的路由例如:

// 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', ...); 

模块1和模块2在init.php中都有自己的路由(mroute1mroute2)。所以,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 
  1. 请注意,如果你是在模块控制器或任何帮手的地方创建路由,将catch-all路径后添加。
  2. 您可以更改模块顺序:Kohana::modules(array('module3' => 'module3') + Kohana::modules());将对您的模块重新排序,并且module3将首先进入列表。但是,这不会影响模块初始化的顺序。以前的任何Kohana::modules调用都已初始化。尽管模块现在位于列表的开头,但它已在其他模块之后初始化(请参阅http://kohanaframework.org/3.2/guide/api/Kohana_Core#modules)。
+0

我真的很感谢你的回答。显然,当动态地执行HMVC请求时,它不会遵守该顺序。 (请参阅我上面更新的问题,了解我在做什么。)谢谢! – 2012-07-19 17:40:21