Zend framework2 Zend Framework 2-应用程序/模块/服务管理器-哦,天哪

Zend framework2 Zend Framework 2-应用程序/模块/服务管理器-哦,天哪,zend-framework2,zend-db,zend-log,Zend Framework2,Zend Db,Zend Log,作为Zend Framework 1的长期开发人员,我刚刚开始学习Zend Framework 2。我在理解新术语时有点困难 回到ZF1,如果我想创建一个应用程序全局的记录器,我会将配置添加到application.ini文件中,引导程序会将其初始化为资源(我希望我说的是正确的)。因此,从我的任何模块控制器,我都可以通过引导资源访问记录器 进入ZF2,模块有点不同,它们是自包含的,但我对它们如何与应用程序交互有点困惑。在我看来,这就是ServiceManager发挥作用的地方。我的目标是让我的模

作为Zend Framework 1的长期开发人员,我刚刚开始学习Zend Framework 2。我在理解新术语时有点困难

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

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

这个问题也与数据库有关,假设我想让应用程序定义数据库连接的逻辑,而我想让模块定义它需要的表的逻辑。我该如何准确地配置它,以及如何/在何处判断应用程序中是否已经定义了数据库资源


注意:我已经看过了Rob Allen的Quickstart(相当多的信息,也是我发现的唯一一个缺乏晦涩度的资源),ZF2(readthedocs)和Google tons。我发现,当涉及到某些谜题的“位置”时,信息通常非常模糊。

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

Zend Framework 2中的“应用程序资源”概念被所谓的(简介)取代

另一个变化是模块本身。在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'));
            });
        }
    }
}
然后,您就可以在所有应用程序中使用“某个记录器名称”

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

class MyModule
{
    public function getConfig()
    {
        return array(
            'service_manager' => array(
                'factories' => array(
                    'some-logger-name' => 'My\Logger\Factory\ClassName'
                ),
            ),
        );
    }
}
使用
getServiceConfig
也可以实现同样的效果,它灵活性较低,无法缓存,但比
getConfig
具有更高的优先级(允许覆盖),还允许您将服务工厂定义为闭包:

class MyModule
{
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'some-logger-name' => function ($sl) {
                    return new MyLogger($sl->get('some-db'));
                },
            ),
        );
    }
}
然后,您甚至可以定义一个配置键,该键必须用于决定使用哪个记录器(服务名称)

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

同样的概念也适用于数据库连接

正如你所看到的,转向服务业已经给了你一定程度的自由


请记住,并不是“应用程序”为您定义了什么:模块定义了您的服务/配置/事件等。。。运行中的应用程序就是所有这些东西的组合。

我认为,特别是在日志记录的情况下,有一种可能比使用
ServiceManager
更好、当然更封装的方法。ZF2本质上是一个事件驱动的框架,支持此事件驱动体系结构的功能可以发挥我们的优势。日志记录就是一个很好的例子。您不需要定义工厂,只需要附加一个可以从应用程序中任何位置触发的记录器事件

Module.php
中附加一个
log
事件侦听器:

public function onBootstrap(MvcEvent $e)
{
    //setup some $logger

    $sharedManager = $e->getApplication()->getEventManager()->getSharedManager();

    $sharedManager->attach('*', 'log', function($e) use ($logger) {
        /** @var $e MvcEvent */
        $target   = get_class($e->getTarget());
        $message  = $e->getParam('message', 'No message provided');
        $priority = $e->getParam('priority', Logger::INFO);
        $message  = sprintf('%s: %s', $target, $message);
        $logger->log($priority, $message);
    });
}
然后从应用程序中的任何位置触发它,例如控制器:

$this->getEventManager()->trigger('log', $this, array(
    'priority' => \Zend\Log\Logger::INFO, 
    'message' => 'just some info to be logged'
));

我非常感谢您的写作(并快速浏览了您提供的链接,今天晚些时候我将深入阅读)。由于我一直在努力(在上面的问题帖子中部分提到),我也开始阅读ZF2源代码,以便更好地理解工作流。你的回答解释得很好,再加上阅读源代码,我开始更好地理解这些片段是如何组合在一起的。我期待着阅读(链接)您提供的快速一瞥,它看起来正是我需要从ZF1移动到ZF2!考虑到ZF2的发布有多新,以及流程向服务管理/事件驱动风格的大量变化,到目前为止,可用信息中存在大量的模糊性(至少从我所遇到的情况来看),我非常感谢您提供的链接,因为它似乎很好地描述了过渡过程。@AaronMurray master
ServiceManager
EventManager
,一切看起来都会简单得多。“但无论如何,模块不是独立的。它们应该在隔离的环境中开发,并且具有尽可能少的依赖性,但是它们提供了影响所有应用程序的交叉关注点功能。“-更多关于这个主题的内容,基本上这就是我所说的自包含的意思-几乎没有依赖项或根本没有依赖项,因此任何人都可以将模块放入自己的应用程序中,并在自己的应用程序中利用其功能。正确,但不要将模块与容器混淆。模块不是的容器。它提供共享的功能/行为。这不是真正的