我知道这是一个老问题,但这总是困扰着我。我不知道 ZF 2 是否已经解决了这个问题(我还没有机会玩它),但我为 ZF 1 编写了一个插件加载器插件来处理这个问题!
当然,问题是即使设置了模块自动加载器并将插件保存在模块的插件文件夹中,这也只会设置自动加载(无论如何都是跨模块)而不是注册。这意味着您可以在 application.ini 中使用一行来实例化插件,但它将为每个模块自动加载和注册。
无论如何,这里有一个可能的解决方案来确保模块插件只为活动模块注册。或者,您可以遍历模块插件目录中的所有文件,而不是提供类映射,但这感觉很难看……而且可能很慢。
<?php
class BaseTen_Controller_Plugin_ModulePluginLoader extends Zend_Controller_Plugin_Abstract {
private $_pluginMap;
public function __construct(array $pluginMap) {
$this->_pluginMap = $pluginMap;
}
public function routeShutdown(Zend_Controller_Request_Abstract $request) {
$module = $request->getModuleName();
if(isset($this->_pluginMap[$module])) {
$front = Zend_Controller_Front::getInstance();
foreach($this->_pluginMap[$module] as $plugin) {
$front->registerPlugin(new $plugin());
}
}
}
}
因为我们需要传递一个 classMap 给构造函数,所以我们需要显式地实例化和注册这个插件到 Front Controller 而不是在 application.ini 中的一行:
public function _initPluginLoader() {
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new BaseTen_Controller_Plugin_ModulePluginLoader(array(
'default' => array(
'Plugin_Foo',
'Plugin_Bar',
...
),
'foo' => array(
'Foo_Plugin_Foo',
'Foo_Plugin_Bar',
...
)
)));
}
插件可以运行的最早时间是在,routeShutdown
否则我们将不知道活动模块。这意味着任何其他使用此方法注册的插件只能从dispatchLoopStartup
以后运行。大多数情况下,我们可能对钩子感兴趣,preDispatch
但postDispatch
值得牢记。