Php ZF2 Zend注册表的替代方案

Php ZF2 Zend注册表的替代方案,php,zend-framework,dependencies,zend-framework2,registry,Php,Zend Framework,Dependencies,Zend Framework2,Registry,我刚刚开始使用ZF2,我真的很喜欢它 有一件事让我有点困惑,那就是缺少注册表组件。我意识到,在大多数情况下,服务经理会使注册表过时。我非常依赖它和它的伟大 但有时我发现自己需要访问“全局”对象,而我没有访问服务管理器的权限。例如,在我的域\用户对象中,我需要访问Zend\日志 我不想让服务管理器在我的域对象中可用,因为它们美丽而原始,而且不受这些考虑的影响。我可以在需要时“新建”一个日志实例,但我经常这样做,我宁愿手头有一个预配置的实例。我可以用单件包装,但这似乎是一个倒退。我可以创建自己的迷你

我刚刚开始使用ZF2,我真的很喜欢它

有一件事让我有点困惑,那就是缺少注册表组件。我意识到,在大多数情况下,服务经理会使注册表过时。我非常依赖它和它的伟大

但有时我发现自己需要访问“全局”对象,而我没有访问服务管理器的权限。例如,在我的域\用户对象中,我需要访问Zend\日志

我不想让服务管理器在我的域对象中可用,因为它们美丽而原始,而且不受这些考虑的影响。我可以在需要时“新建”一个日志实例,但我经常这样做,我宁愿手头有一个预配置的实例。我可以用单件包装,但这似乎是一个倒退。我可以创建自己的迷你注册表,但如果这是一个好主意,我相信Zend的人会留下这样一个组件

那么,还有什么其他选择呢

编辑:


那么,我可以用Zend DI吗?我看到这个问题部分地涵盖了它,

您正是在解决依赖注入的问题。我以前写过关于这个主题的博客,如果你喜欢一个日志记录者,该如何做

其思想是注入预配置的记录器。创建域\用户对象时,将插入记录器。这使得域\用户对象仅依赖于记录器,而不知道如何创建记录器。如果您依赖于记录器接口,则更好,因此您可以切换到任何您想要的记录器实现

示例

例如,我假设您使用的是Zend\Log。您有一个类似于
Zend\Log\Logger
的记录器,附带了各种写入程序。记录器实现
Zend\Log\LoggerInterface

您的域\用户类:

namespace Domain;

Zend\Log\LoggerInterface;

class User
{
    protected $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function doSomething()
    {
        $this->logger->info('Do Something');

        //
    }
}
对于Zend Framework,您应该与工厂合作,将此记录器注入到您的对象中。最好的方法是首先将记录器定义为服务,因为您也可以将记录器重新用于其他对象

注意:我在这里使用服务管理器,而不是Zend\Di。Zend\Di已经过时,取而代之的是更快、更灵活的Zend\ServiceManager。两者都可以实现依赖注入

适用于您的工厂:

namespace MyModule\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

use Zend\Log\Logger;

class LoggerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $logger = new Logger;
        // do more with $logger here

        return $logger;
    }
}
然后注册此工厂,为您创建服务“记录器”。在module.config.php中:

'service_manager' => array(
    'factories' => array(
        'logger' => 'MyModule\Factory\LoggerFactory',
    ),
),
现在,您的服务经理中提供了
记录器
。对于您的域模型,请执行相同的操作。首先创建工厂:

namespace MyModule\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

use Domain\User;

class UserFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $logger = $serviceLocator->get('logger');

        $user = new User($logger);
        return $user;
    }
}
然后再注册这个:

'service_manager' => array(
    'factories' => array(
        'logger' => 'MyModule\Factory\LoggerFactory',
        'Domain\User' => 'MyModule\Factory\UserFactory',
    ),
),
如果您有权访问服务定位器,则可以获取域\用户并自动注入记录器:

$user = $sl->get('Domain\User');

“正确”的方法是将日志对象作为依赖项传递到域\用户对象中。不过,在域模型中,日志记录并不是你通常会做的事情——你能再解释一下为什么需要它吗?嗨,蒂姆,我用它只是为了获取变量的变量转储或打印。只是为了调试,真的。你的编辑听起来不错-Zend\Di\Di似乎是在对象构造时激发依赖关系的一个不错的选择。但是,正如您所提到的,只有当它根本不是一个真正的依赖项(如日志记录)时,才应该这样做。为什么不在服务管理器中将其注册为服务呢?将“日志记录功能”从您美丽而原始的域实体中移开怎么样?