0

我正在创建一个 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();
4

2 回答 2

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 中没有办法将 Route 推送到列表的开头。当然,保证首先加载有问题的模块会解决您的问题(只要以后不覆盖路由)。如果您可以透明地扩展 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);
    }
}
于 2012-07-20T04:52:12.267 回答
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', ...);

module1 和mroute1module2mroute2init.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
  1. 请注意,如果您在模块控制器或任何助手中的某处创建路由,它将在catch-all路由之后添加。
  2. 您可以更改模块顺序:Kohana::modules(array('module3' => 'module3') + Kohana::modules());将重新排列您的模块并将module3在列表中排在第一位。但是,这不会影响模块初始化的顺序。之前的任何Kohana::modules调用都已初始化。尽管该模块现在位于列表的开头,但它是在其他模块之后初始化的(请参阅http://kohanaframework.org/3.2/guide/api/Kohana_Core#modules)。
于 2012-07-19T06:33:01.990 回答