Php Zend framework 1.12前端控制器配置

Php Zend framework 1.12前端控制器配置,php,zend-framework,Php,Zend Framework,我正试图使用以下代码,使用引导类向前端控制器注册我的模块: $this->bootstrap('FrontController'); $front = $this->getResource('FrontController'); $front->addModuleDirectory(APPLICATION_PATH."/modules"); $front->setParam('prefixDefaultModule', true); 这工作正常,所有模块都已注

我正试图使用以下代码,使用引导类向前端控制器注册我的模块:

$this->bootstrap('FrontController');
$front = $this->getResource('FrontController');     
$front->addModuleDirectory(APPLICATION_PATH."/modules");
$front->setParam('prefixDefaultModule', true);
这工作正常,所有模块都已注册。但是当我执行以下操作时,我的模块目录没有注册,并且我得到了“controller not found error”


由于前端控制器实现了单例设计模式,两个代码块不应该引用同一个实例,并且我的两个代码块都应该工作吗

您需要首先引导前控制器,以便对其进行初始化。在循环中完成后,您始终可以使用静态getInstance检索它。

下面是发生的情况。蒂姆是对的。application.ini文件中的以下行就是罪魁祸首。如果将其删除,应用程序将正确加载

resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
您可能还必须删除该行,因为它也是frontcontroller的一部分

resources.frontController.params.displayExceptions = 1 
但是您还有另外两个选项可以使用
Zend\u Controller\u Front::getInstance()

备选案文1。将index.php更改为特定于引导的资源:

$application->bootstrap(array('FrontController', 'ModuleConfig'))->run();
这将首先从application.ini引导FrontController,然后运行
initModuleConfig
方法。本质上,这允许您控制加载哪些资源以及加载顺序。当您有只想在特定时间引导的资源时,这非常有用

我认为,如果您不在这里为bootstrap方法提供数组,那么它将按照声明的顺序调用以
init
为前缀的所有方法

备选案文2。您可以在application.ini中配置模块目录

resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.params.prefixDefaultModule = 1
resources.frontController.params.displayExceptions = 1 
这将完成您在代码中尝试执行的操作。需要注意的一点是,您可能希望在
bootstrap
类的构造函数中引导FrontController。这只是为了防止在自定义初始化期间需要使用它


下面是选项1工作原理的解释

这是来自
Zend\u应用程序\u引导\u引导的方法

protected function _bootstrap($resource = null)
{
    if (null === $resource) {
        foreach ($this->getClassResourceNames() as $resource) {
            $this->_executeResource($resource);
        }

        foreach ($this->getPluginResourceNames() as $resource) {
            $this->_executeResource($resource);
        }
    } elseif (is_string($resource)) {
        $this->_executeResource($resource);
    } elseif (is_array($resource)) {
        foreach ($resource as $r) {
            $this->_executeResource($r);
        }
    } else {
        throw new Zend_Application_Bootstrap_Exception('Invalid argument passed to ' . __METHOD__);
    }
}
调用public
引导
方法时,将调用此
\u引导
。示例
$this->bootstrap(“FrontController”)
$this->bootstrap()

请注意不传入参数的情况。这将调用
null
案例,这是您在
index.php
-
$application->bootstrap()->run()中得到的案例

首先它将加载您的
类资源
,然后它还将调用您的
插件资源
。请注意,
插件资源
在其他情况下不会加载

如果遵循类资源的方法调用,基本上就是在引导调用类中调用
init
方法

之后将调用插件资源和其中一个插件资源。我不完全确定所有插件资源是如何加载的,但我相信有一个源代码在您的
应用程序.ini
文件中。这些将是以
资源
开头的行。示例包括视图、frontcontroller、db

因此,在您调用
$application->bootstrap()->run()的情况下
,首先加载您的
init
方法。但是您的
FrontController
尚未启动。它最终被引导为一个插件资源,该资源取自您的
应用程序.ini
。这显然覆盖了您在引导类中所做的操作

您可能会问的另一个问题是,当您显式调用
$this->bootstrap(“FrontController”)
时,为什么FrontController实例没有被覆盖。我想这很明显,但我个人也有这个问题

在引导类中,有一个名为
\u executesource
的方法,它将检查资源是否已引导。它使用关联数组来跟踪。关联数组名为
$this->\u started


这就是为什么在您第一次显式引导前控制器时,不会调用前控制器的插件资源。因此,不会替换前控制器实例。

问题在于application.ini中的这一行:

resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
您提供的文件结构不包含此目录,因此我认为您可以删除它,它将解决您的问题

更详细地解释为什么它以一种方式工作,而不是以另一种方式工作:

使用Zend应用程序配置资源有两种方式:类资源和插件资源。Application.ini中的
资源.xxx
行是插件资源,
\u init
方法是类资源。类资源在插件资源之前运行,但如果运行
$this->bootstrap(“…”)
它将确保资源已初始化(无论类型如何)

因此,在您的第一个代码示例中,
$this->bootstrap('FrontController');
触发您在application.ini中定义的FrontController资源。这将使用您提供的路径设置控制器目录。然后添加一个模块目录,该目录似乎是您的应用程序实际使用的目录

在您的第二个代码示例中,您获得了front controller的一个实例,然后将您的模块目录添加到该实例中(都很好),但是插件资源将运行(请记住这些将在之后运行)。这将获取现有的front controller实例,但设置控制器目录会覆盖模块目录,因此这就是导致您以后出错的原因

我通常会尝试避免混合和匹配插件和类资源,因为这可能会导致一些奇怪的问题。因此,要么将其全部放在application.ini中,要么将其全部放在Bootstrap类中。我个人认为后者更具可读性

如果您确实也需要控制器目录,请将
$this->bootstrap('FrontController');
添加到代码的开头
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"