Pull to refresh

Lazy load modules bootstrap

Reading time5 min
Views5.2K
Многие как и я используют Modules ресурс, который позволяет использовать отдельные Bootstrap файлы для каждого модуля. Но этого ресурса есть один недостаток — он всегда загружает все Bootstrap файлы в независимости от того какое модули мы используем в конкретном запросе. Я решил предоставить решение данной проблемы

Для начала слегка изменим сам ресурс
<?php
class System_Application_Resource_Modules extends Zend_Application_Resource_ResourceAbstract
{
  public function init()
  {
    $modulePlugin = new System_Controller_Plugin_ModuleBootstrap();
    $modulePlugin->setBootstrap($this->getBootstrap());
    
    $this->getBootstrap()
      ->bootstrap('FrontController')
      ->getResource('FrontController')
      ->registerPlugin($modulePlugin);
      
    return $modulePlugin;
  }
}


Код прост до безобразия. Создаем новый Controller Plugin и регистрируем его в фронт контроллер FrontController
Как Вы уже догадались вся «магия» происходит в System_Controller_Plugin_ModuleBootstrap
<?php
class System_Controller_Plugin_ModuleBootstrap extends Zend_Controller_Plugin_Abstract
{
  /**
   * var Zend_Application_Bootstrap_BootstrapAbstract
   */
  protected $_bootstrap = null;
  
  /**
   * var array
   */
  protected $_bootstrapedModules = array();
  
  /**
   * Constructor
   * param array $options
   **/
  public function __construct($options = null) {
    if ($options !== null) {
      $this->setOptions($options);
    }
  }
  
  /**
   * Implement configurable object pattern
   * param array $options
   */
  public function setOptions($options)
  {
    foreach ((array)$options as $name => $value) {
      $setter = 'set'.ucfirst($name);
      if (is_callable(array($this, $setter))) {
        $this->$setter($value);
      }
    }  
  }
  
  /**
   * Bootstrap setter
   */
  public function setBootstrap(Zend_Application_Bootstrap_BootstrapAbstract $bootstrap)
  {
    $this->_bootstrap = $bootstrap;
  }
  
  /**
   * get Front Controller
   * return Zend_Controller_Front
   */
  protected function _getFront()
  {
    return Zend_Controller_Front::getInstance();
  }
  /**
   * Return is module run
   * param string $module
   * return bool
   */  
  public function isBootsraped($module)
  {
    return isset($this->_bootstrapedModules[$module]);
  }
  
  
  /**
   * Get bootstraps that have been run
   *
   * return Array
   */
  public function getExecutedBootstraps()
  {
    return $this->_bootstrapedModules;
  }
  
  /**
   * Format a module name to the module class prefix
   *
   * param string $name
   * return string
   */
  protected function _formatModuleName($name)
  {
    $name = strtolower($name);
    $name = str_replace(array('-', '.'), ' ', $name);
    $name = ucwords($name);
    $name = str_replace(' ', '', $name);
    return $name;
  }
  
  /**
   * preDispatch hook
   */
  public function preDispatch(Zend_Controller_Request_Abstract $request)
  {
    $module = $request->getModuleName();
    if (empty($module)) {
      $module = $this->_getFront()->getDefaultModule();
    }
    
    if (! $this->isBootsraped($module)) {
      $moduleDirectory = $this->_getFront()->getControllerDirectory($module);
      $bootstrapClass = $this->_formatModuleName($module). '_Bootstrap';
      
      if (!class_exists($bootstrapClass, false)) {
        $bootstrapPath = dirname($moduleDirectory). '/Bootstrap.php';
        if (file_exists($bootstrapPath)) {
          $eMsgTpl = 'Bootstrap file found for module "%s" but bootstrap class "%s" not found';
          include_once $bootstrapPath;
          if (!class_exists($bootstrapClass, false)) {
            throw new Zend_Application_Resource_Exception(sprintf(
              $eMsgTpl, $module, $bootstrapClass
            ));
          }
        } else {
          return;
        }
      }

      $moduleBootstrap = new $bootstrapClass($this->_bootstrap);
      $moduleBootstrap->bootstrap();
      $this->_bootstrapedModules[$module] = $moduleBootstrap;
    }
    
  }
}


В плагине обрабатываем событие preDispatch, в котором, загружаем и запускаем Bootstrap для текущего модуля, если он не был загружен до этого.

Для ипользования нашего класса вместо стандартного просто добавим в конфиг путь к нашим классам
pluginPaths.System_Application_Resource = «System/Application/Resource»



Приятного использования
Tags:
Hubs:
+4
Comments12

Articles

Change theme settings