Zend Framework 2 - 应用程序/模块/服务经理 - 哦,我的

Aar*_*ray 6 zend-db zend-log zend-framework2

我刚开始学习Zend Framework 2作为Zend Framework 1的长期开发人员.围绕新术语缠绕我有点麻烦.

回到ZF1,如果我想创建一个对应用程序是全局的记录器,我会将配置添加到application.ini文件中,引导程序会将其初始化为资源(我希望我说的是正确的).那么从我的任何模块控制器,我可以通过bootstrap资源访问记录器.

输入ZF2,模块是一个有点不同的野兽,它们是自包含的,但我对它们如何与应用程序交互有点困惑.在我看来,这就是ServiceManager发挥作用的地方.我的目标是,让我的模块(不是控制器,而不是模块本身)检查应用程序是否定义了记录器,如果有,则在整个模块中使用该记录器.如果应用程序没有定义记录器,我希望模块为模块范围的日志记录定义记录器.

这个问题也与数据库有关,假设我想让应用程序定义数据库连接的逻辑,而我希望模块定义它所需的表的逻辑.我究竟如何配置它,以及如何在应用程序中定义数据库资源时如何/在何处判断.

注意:我已经浏览了Rob Allen的快速入门(相当充分的信息和我发现的唯一缺乏默默无闻的资源)和ZF2(readthedocs),并且已经用谷歌搜索过了.我发现的是,当涉及到某些拼图的"哪里"时,信息通常是非常模糊的.

Ocr*_*ius 6

您从Zend Framework 1.x中了解到的是"应用程序资源".

"应用程序资源"的概念在Zend Framework 2中被所谓的"服务"取代(这里是介绍)

另一个变化是模块本身.在ZF1中,模块主要是应用程序的一个子部分,用于处理某些请求.在ZF2中不再如此:如果您的模块定义了服务或控制器,那么现在所有应用程序都可以访问该模块.Gary Hockin对ZF1和ZF2之间的一些差异进行了很好的介绍.

但无论如何,模块不是独立的.它们应该在绝缘环境中开发,并尽可能少依赖,但它们提供了影响所有应用程序的交叉关注功能.

对于记录器的特定情况,我建议您的模块始终定义记录器并使用它.有条件地定义记录器的方法如下:

class MyModule
{
    public function onBootstrap($e)
    {
        // $e->getTarget() is the \Zend\Mvc\Application
        $sm = $e->getTarget()->getServiceManager();

        if (!$sm->has('some-logger-name')) {
            $sm->setFactory('some-logger-name', function ($sl) {
                return new MyLogger($sl->get('some-db'));
            });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您就可以在所有应用程序中使用"some-logger-name".

另一种方法是仅定义记录器服务,并让其他模块或配置稍后覆盖它:

class MyModule
{
    public function getConfig()
    {
        return array(
            'service_manager' => array(
                'factories' => array(
                    'some-logger-name' => 'My\Logger\Factory\ClassName'
                ),
            ),
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

同样可以实现getServiceConfig,灵活性较低且无法缓存,但优先级高于getConfig(允许覆盖),并允许您将服务工厂定义为闭包:

class MyModule
{
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'some-logger-name' => function ($sl) {
                    return new MyLogger($sl->get('some-db'));
                },
            ),
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您甚至可以定义一个必须用于决定使用哪个记录器(服务名称)的配置密钥.

模块和配置的概念是"最后一个模块获胜",因此您可以'some-logger-name'在模块中或在之前加载的任何模块中定义服务.

相同的概念也适用于您的数据库连接.

如您所见,迁移到服务已经给了您一定程度的自由.

请记住,"应用程序"并不是为您定义的东西:模块定义您的服务/配置/事件等......然后,正在运行的应用程序将所有这些内容组合在一起.