Zend Registry for ZF2的替代品

Kim*_*nce 5 php registry dependencies zend-framework zend-framework2

我刚开始使用ZF2,我真的非常喜欢它.

令我困惑的一件事是没有注册表组件.我意识到服务管理器在大多数情况下使注册表过时.我非常依赖它而且很棒.

但有时我发现自己需要访问"全局"对象,而我无法访问服务管理器.例如,在我的Domain\User对象中,我需要访问Zend\Log.

我不希望在我的Domain对象中提供Service Manager,因为它们非常漂亮和原始,并且没有因这些考虑因素而受到影响.我可以在需要时"新建"一个日志实例,但是我经常这么做,我宁愿预先配置一个实例.我可以把它包装成单身,但这似乎是一个倒退的步骤.我可以创建自己的迷你注册表,但如果这是一个好主意,我相信Zend家伙会留下这样的组件.

那么,还有哪些其他选择?

编辑:

那么,我可以使用Zend DI吗?我看到这个问题部分涵盖了它,使用Zend\Di\Di配置类别名

Jur*_*man 3

您正在解决依赖注入的问题。我之前曾在博客中讨论过这个主题,如何重构依赖注入,以及如果您有像 Logger 这样的软依赖项该怎么办。

这个想法是您注入预先配置的记录器。创建 Domain\User 对象时,将注入记录器。这使得域\用户对象仅依赖于记录器,而不知道如何创建记录器。如果您依赖 Logger 接口,那就更好了,这样您就可以切换到您想要的任何记录器实现。

例子

作为一个例子,我假设您正在使用 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');

        //
    }
}
Run Code Online (Sandbox Code Playgroud)

对于 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后注册这个工厂来为您创建服务“logger”。在你的 module.config.php 中:

'service_manager' => array(
    'factories' => array(
        'logger' => 'MyModule\Factory\LoggerFactory',
    ),
),
Run Code Online (Sandbox Code Playgroud)

现在logger可以在您的服务管理器中使用。对于您的域模型,执行相同的操作。首先创建一个工厂:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后也注册这个:

'service_manager' => array(
    'factories' => array(
        'logger' => 'MyModule\Factory\LoggerFactory',
        'Domain\User' => 'MyModule\Factory\UserFactory',
    ),
),
Run Code Online (Sandbox Code Playgroud)

如果您有权访问服务定位器,则可以获得域\用户,并且记录器会自动注入:

$user = $sl->get('Domain\User');
Run Code Online (Sandbox Code Playgroud)