ZF 的模块自动装载机

发布于 2024-08-31 15:59:29 字数 657 浏览 1 评论 0原文

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

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

现在我有两个问题

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

The manual on Zend_Application_Module_Autoloader states the following:

When using module bootstraps with Zend_Application, an instance of Zend_Application_Module_Autoloader will be created by default for each discrete module, allowing you to autoload module resources.

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

This requires me to create an empty bootstrap class for each of my modules or else resource autoloading per module won't work with the build-in autoloader.

Now I have two questions

  • What is a discrete module?
  • Is there a way to have this resource autoloader registered by default for each module without the need to create a bootstrap file for each module? I want it available in each module and creating so many empty bootstrap classes is something i'd rather prevent.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧情勿念 2024-09-07 15:59:29

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

(在这种情况下,“离散”意味着“独立”,而不是“应用程序”模块的一部分。)

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

I understand your reluctance to add an empty bootstrap class to each module. However, consider the case for re-use: if you are able to bundle your module separately, you can then drop it into another application later, and autoloading will work immediately, with no extra work. This was one of the use cases for having module bootstraps, and why it currently works the way it does.

("Discrete" in this case means "self-contained", and not part of the "application" module.)

If you don't like how this operates, you're free to omit the module bootstrap -- you'll simply need to add in a resource autoloader for the module yourself somehow. This can be done via a bootstrap resource method fairly easily. However, as someone earlier posted: why re-invent the wheel when something that's tested and documented gets the job done? :)

我不咬妳我踢妳 2024-09-07 15:59:29

模块引导程序启用自动加载的原因是因为它们扩展了 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;
    }

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

The reason modules bootstraps enable autoload is because they extend Zend_Application_Module_Bootstrap which sets the autoloader in the constructor like so

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

This runs because the modules resource runs the bootstrap for each module in the init function ...

       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;
    }

The short answer is if you don't write the empty bootstrap files, you'll have to abstract some of this well functioning, well tested code into your own global bootstrap file, and then lose the flexibility of having bootstraps for you modules when / if you need to bootstrap them later in your app.

聆听风音 2024-09-07 15:59:29

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

至于你的第二个问题,答案是肯定的,也不是。如果您想利用默认的自动加载功能(从 admin/forms 目录加载 Admin_Form_Settings),则每个模块中都需要一个引导程序。请参阅 Matthew Weier O'Phinney 的文章 Zend Framework 中的模块引导:注意事项 了解更多信息。您可能还想通过 Google 搜索并查看 Rob Allen 的帖子“ZF 1.8 及更高版本中的引导模块”。

对第二个问题的回答是否定的:我喜欢使用的一种不需要每个模块中都有空引导程序的技术是将所有应用程序类放置在应用程序的 lib 文件夹中,并模仿 Zend Framework 的目录结构。如果我的应用程序名为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 搜索应该是链接的项目。

Modules allow you to separate your application into specific concerns. Frequently my larger applications will have a default module for users and an admin module to contain all administrative functions. I use the directory structure recommended in the Recommended Project Structure for Zend Framework MVC Applications -> Module Structure section of the Zend Framework Documentation.

As to your second question, the answer is yes and no. If you want to take advantage of the default autoloading functionality (loading Admin_Form_Settings from the admin/forms directory), you will need a bootstrap in each module. See Matthew Weier O'Phinney's article on Module Bootstraps in Zend Framework: Do's and Don'ts for more info. You may also want to Google for and review Rob Allen's post "Bootstrapping modules in ZF 1.8 and up."

Answering no to your second question: one technique that I like to use that doesn't require empty bootstraps in each module is placing all of your application classes in the application's lib folder, and mimic the Zend Framework's directory structure. If my application is named Example, I'll create a folder named Example in my /lib directory. My user registration form would be placed in /lib/Example/Form, and might be named UserRegistration.php. My class would be named Example_Form_UserRegistration. Autoloading my form would require the following in the Bootstrap.php file:

protected function _initAppAutoload() {

    $autoloader = Zend_Loader_Autoloader::getInstance();

    return $autoloader;
}

My application.ini would include the lines

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

Using this technique you should then be able to autoload any class in /lib/Example anywhere in your application without placing empty bootstraps in each module.

NOTE: I tried posting links directly to the docs and to Rob Allen's article, but since I'm a new guy I was only allowed a single link. Apologies for asking you to Google items that should be links.

山有枢 2024-09-07 15:59:29

有两种方法(据我所知)可以启用模块资源自动加载器。第一个已在上面的答案中涵盖,即:

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

resources.modules[] =

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

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

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

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

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

There are two ways (that I know of) to enable the module resource autoloaders. The first has been covered in above answers, namely:

Add the modules resource line in your application.ini:

resources.modules[] =

And then create an empty module bootstrap file.

The second is to add the following bootstrap method to your application-wide (non-module) bootstrap:

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

But you would need to create each module's autoloader individually. Personally, I prefer the empty bootstrap files for reasons mentioned above - this feels more manual to me.

Note: I believe this is the "bootstrap resource method" @weierophinney mentions above.

上课铃就是安魂曲 2024-09-07 15:59:29

Bootstrap:

$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;
    }

} 

Bootstrap:

$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);
}

This helper to insert data (menus, views, etc.) in the core module:

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;
    }

} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文