官术网_书友最值得收藏!

Providing your own URL rules at runtime

When you are developing an application with pluggable module architecture, you most likely need to somehow inject your module-specific rules into an existing application.

Getting ready

  1. Set up a new application using yiic webapp.
  2. Add .htaccess, shown in official URL Management guide to your webroot.
  3. Add 'showScriptName' => false to your URL manager configuration.
  4. Generate the page module using Gii.
  5. Don't forget to add your new module to the modules list in your application configuration.

The Yii code generator is shown in the following screenshot:

How to do it...

  1. Create ModuleUrlManager.php in your protected/components directory with the following code inside:
    <?php
    class ModuleUrlManager
    {
      static function collectRules()
      {
        if(!empty(Yii::app()->modules))
        {
           foreach(Yii::app()->modules as $moduleName => $config)
           {
              $module = Yii::app()->getModule($moduleName);
              if(!empty($module->urlRules))
              {
                Yii::app()->getUrlManager()->addRules($module->urlRules);
              }
           }
        }
    
        return true;
      }
    }
  2. In your application configuration, add the following line:
    'onBeginRequest' => array('ModuleUrlManager', 'collectRules'),
  3. Now, in your page module, you can add custom rules. To do so, open PageModule.php and add:
    public $urlRules = array(
      'test' => 'page/default/index',
    );
  4. To test if it works, open your browser and go to http://example.com/test. This page should look like the one shown in the following screenshot:

    This is the view content for action "index". The action belongs to the controller "DefaultController" in the "page" module.

  5. You still can override URL rules from your main application configuration file. So, what you specify in module's urlRules is used only when the main application rules are not matching.

How it works...

Let's review the ModuleUrlManager::collectRules method.

If there are modules defined in our application, then we are checking if urlRules public property exists. If it does, then there are some rules defined in the module and they are added using CUrlManager::addRules.

CUrlManager::addRules description says "In order to make the new rules effective, this method must be called before CWebApplication::processRequest".

Now, let's check how our application works. In our index.php, we have the following line:

Yii::createWebApplication($config)->run();

After being initialized with configuration, we are calling CWebApplication::run():

public function run()
{
   if($this->hasEventHandler('onBeginRequest'))
      $this->onBeginRequest(new CEvent($this));
   $this->processRequest();
   if($this->hasEventHandler('onEndRequest'))
      $this->onEndRequest(new CEvent($this));
}

As we can see, there is an onBeginRequest event raised just before calling processRequest. That is why we are attaching our class method to it.

There's more...

As instantiating all application modules on every request is not good for performance, it is good to cache module rules. Caching strategy can vary depending on your application. Let's implement a simple one:

<?php
class ModuleUrlManager
{
  static function collectRules(){
    if(!empty(Yii::app()->modules))
    {
      $cache = Yii::app()->getCache();

      foreach(Yii::app()->modules as $moduleName => $config)
      {
         $urlRules = false;

         if($cache)
           $urlRules = $cache->get('module.urls.'.$moduleName);            

         if($urlRules===false){
           $urlRules = array();
           $module = Yii::app()->getModule($moduleName);
           if(isset($module->urlRules))
              $urlRules = $module->urlRules;

           if($cache)
              $cache->set('module.urls.'.$moduleName, $urlRules);
         }
         if(!empty($urlRules))
           Yii::app()->getUrlManager()->addRules($urlRules);
      }
   }

   return true;
  }
}

This implementation caches URL rules per module. So, adding new modules is not a problem but changing existing ones requires you to flush cache manually using Yii::app()->cache->flush().

See also

  • The recipe named Configuring URL rules in this chapter
主站蜘蛛池模板: 天门市| 岳阳市| 新闻| 霍邱县| 铁岭县| 黔西县| 灵石县| 保靖县| 徐闻县| 裕民县| 新干县| 库车县| 讷河市| 马鞍山市| 云龙县| 堆龙德庆县| 辰溪县| 陆良县| 义乌市| 中阳县| 富川| 定陶县| 绥棱县| 清远市| 邛崃市| 高密市| 馆陶县| 桑日县| 溆浦县| 宜宾市| 鄂托克前旗| 铁岭县| 兴义市| 南陵县| 青河县| 集贤县| 麻江县| 清流县| 黄大仙区| 深水埗区| 万源市|