1

Zend_Application_Module_Autoloader 的手册说明如下:

当使用 Zend_Application 的模块引导时,默认情况下会为每个离散模块创建一个 Zend_Application_Module_Autoloader 实例,允许您自动加载模块资源。

来源: http: //framework.zend.com/manual/zh/zend.loader.autoloader-resource.html#zend.loader.autoloader-resource.module

这需要我为每个模块创建一个空的引导类,否则每个模块的资源自动加载将无法与内置自动加载器一起使用。

现在我有两个问题

  • 什么是离散模块?
  • 有没有办法让这个资源自动加载器默认为每个模块注册,而无需为每个模块创建引导文件?我希望它在每个模块中都可用,并且创建这么多空引导类是我宁愿阻止的。
4

5 回答 5

7

我理解您不愿意为每个模块添加一个空的引导类。但是,请考虑重用的情况:如果您能够单独捆绑您的模块,您可以稍后将其放入另一个应用程序中,自动加载将立即工作,无需额外工作。这是具有模块引导程序的用例之一,也是它目前以这种方式工作的原因。

(在这种情况下,“离散”表示“自包含”,而不是“应用程序”模块的一部分。)

如果你不喜欢它的操作方式,你可以省略模块引导程序——你只需要以某种方式自己为模块添加资源自动加载器。这可以通过引导资源方法相当容易地完成。但是,正如之前有人发布的那样:为什么要在经过测试和记录的东西完成工作时重新发明轮子?:)

于 2010-05-11T11:49:24.363 回答
2

模块引导程序启用自动加载的原因是因为它们扩展了 Zend_Application_Module_Bootstrap ,它像这样在构造函数中设置自动加载器

public function __construct($application)
{
  //...
  if ($application->hasOption('resourceloader')) {
      $this->setOptions(array(
          'resourceloader' => $application->getOption('resourceloader')
      ));
  }
  $this->initResourceLoader();
  //...
}

这是因为模块资源为 init 函数中的每个模块运行引导程序...

       foreach ($modules as $module => $moduleDirectory) {
        $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 (($default != $module)
                    && !class_exists($bootstrapClass, false)
                ) {
                    throw new Zend_Application_Resource_Exception(sprintf(
                        $eMsgTpl, $module, $bootstrapClass
                    ));
                } elseif ($default == $module) {
                    if (!class_exists($bootstrapClass, false)) {
                        $bootstrapClass = 'Bootstrap';
                        if (!class_exists($bootstrapClass, false)) {
                            throw new Zend_Application_Resource_Exception(sprintf(
                                $eMsgTpl, $module, $bootstrapClass
                            ));
                        }
                    }
                }
            } else {
                continue;
            }
        }

        if ($bootstrapClass == $curBootstrapClass) {
            // If the found bootstrap class matches the one calling this
            // resource, don't re-execute.
            continue;
        }

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

简短的回答是,如果您不编写空引导文件,则必须将一些功能良好、经过良好测试的代码抽象到您自己的全局引导文件中,然后在 / 时失去为模块提供引导的灵活性如果您需要稍后在您的应用程序中引导它们。

于 2010-05-10T23:41:09.937 回答
2

模块允许您将应用程序分成特定的关注点。通常我的大型应用程序会有一个用户默认模块和一个包含所有管理功能的管理模块。我使用 Zend Framework MVC 应用程序的推荐项目结构 -> Zend Framework 文档的模块结构部分中推荐的目录结构。

至于你的第二个问题,答案是肯定的和否定的。如果您想利用默认的自动加载功能(从 admin/forms 目录加载 Admin_Form_Settings),您将需要在每个模块中都有一个引导程序。有关更多信息,请参阅 Matthew Weier O'Phinney 关于Zend 框架中的模块引导:Do's and Don'ts的文章。您可能还想在 Google 上搜索并查看 Rob Allen 的帖子“ZF 1.8 及更高版本中的引导模块”。

对您的第二个问题回答“否”:我喜欢使用的一种不需要每个模块中的空引导程序的技术是将所有应用程序类放在应用程序的 lib 文件夹中,并模仿 Zend 框架的目录结构。如果我的应用程序名为 Example,我将在 /lib 目录中创建一个名为 Example 的文件夹。我的用户注册表单将放在 /lib/Example/Form 中,并且可能命名为 UserRegistration.php。我的课程将命名为 Example_Form_UserRegistration。自动加载我的表单需要 Bootstrap.php 文件中的以下内容:

protected function _initAppAutoload() {

    $autoloader = Zend_Loader_Autoloader::getInstance();

    return $autoloader;
}

我的 application.ini 将包含以下行

resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] = 
autoloaderNamespaces[] = "Example_"

使用这种技术,您应该能够在应用程序的任何位置自动加载 /lib/Example 中的任何类,而无需在每个模块中放置空引导程序。

注意:我尝试将链接直接发布到文档和 Rob Allen 的文章,但由于我是新人,我只被允许一个链接。很抱歉让您搜索应该是链接的 Google 项目。

于 2010-05-11T11:17:31.460 回答
2

有两种方法(我知道)来启用模块资源自动加载器。第一个已在上述答案中涵盖,即:

在 application.ini 中添加模块资源行:

resources.modules[] =

然后创建一个空的模块引导文件。

第二种是将以下引导方法添加到您的应用程序范围(非模块)引导程序中:

protected function _initModuleAutoload()
{
    $autoloader = new Zend_Application_Module_Autoloader(array(
        'namespace' => 'Foo',
        'basePath' => APPLICATION_PATH . "/modules/Foo",
    ));
    return $autoloader;
}

但是您需要单独创建每个模块的自动加载器。就个人而言,出于上述原因,我更喜欢空引导文件 - 这对我来说感觉更手动。

注意:我相信这是上面提到的@weierophinney 的“引导资源方法”。

于 2011-04-03T19:51:24.687 回答
0

引导程序:

$uri = explode('/',$_SERVER['REQUEST_URI']);
if($uri['1'] == 'flok'){
    $flok = new Zend_Controller_Router_Route('flok/:controller/:action/:id/*',  array('module' => 'flok', 'controller' => 'index', 'action' => 'index',  'id' =>null));
    $router->addRoute('flok', $flok);

    $resourceLoader = new Zend_Application_Module_Autoloader(array(
        'basePath'  => APPLICATION_PATH . "/flok/flok",
        'namespace' => 'Flok',
    ));

    //Init
    $frontController->registerPlugin(new Flok_Plugin_Init(),'flok');
    //Auth
    $frontController->registerPlugin(new Flok_Plugin_Auth(),'flok');

    // dynamic modules
    $ruta = APPLICATION_PATH.'/flok';
    foreach(scandir($ruta) as $mod) {
        if(!is_dir($mod) and $mod != '.DS_Store'){
            $Modululflok = new Zend_Controller_Router_Route('flok/'.$mod.'/:controller/:action/:id/*',  array('submodules' => 'flok','module' => $mod , 'controller' => 'index', 'action' => 'index',  'id' =>null));
            $router->addRoute($mod, $Modululflok);
            $resourceLoader = new Zend_Application_Module_Autoloader(array(
                'basePath'  => APPLICATION_PATH . "/flok/".$mod,
                'namespace' => ucfirst($mod),
            ));
        }
    }

    $layout = Zend_Layout::getMvcInstance();

    $layout
        ->setLayout('layout')
        ->setLayoutPath(APPLICATION_PATH . '/flok/flok/views/scripts');

    $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
    $viewRenderer->initView();
    $viewRenderer->view->addHelperPath(APPLICATION_PATH . '/flok/flok/helpers');
} else {
    $default = new Zend_Controller_Router_Route('*',  array('module' => 'default', 'controller' => 'index', 'action' => 'index'));
    $router->addRoute('default', $default);
}

这个助手在核心模块中插入数据(菜单、视图等):

class Zend_View_Helper_Models
{
    public function Models($tipo)
    {
        // load modules
        $ruta = APPLICATION_PATH.'/flok';
        foreach(scandir($ruta) as $mod) {
            if(!is_dir($mod) and $mod != '.DS_Store'){
                $rutaphp = $ruta.'/'.$mod.'/'.$mod.'.php';
                if(file_exists($rutaphp)){ 
                include_once($rutaphp);
                    $modul = new $mod;
                    if(isset($modul->$tipo) and $modul->$tipo === true){
                       $data = $tipo.'Data';
                       $m[] = $modul->$data;
                    } 
                }
            }
        }
        return $m;
    }

} 
于 2012-08-04T14:01:24.793 回答