我的module_config中定义了各种Logger。需要特定记录器的每个控制器或服务都需要通过其工厂注入记录器。
理想情况下,我不想担心这种注射,并且可以使记录器可以访问(没有我的服务/控制器中的服务定位器)。只有当我需要它们时,它们应该是懒惰加载/实例化的。
有没有办法这样做?我在考虑初始化,处理或使用事件管理器。
我知道,这听起来像回到了服务定位器。
有什么想法吗?
答案 0 :(得分:1)
我想最干净的方法是使用controller plugin从控制器调用记录器。
实施非常简单:
创建一个新的PHP类并使其扩展Zend\Mvc\Controller\Plugin\AbstractPlugin
。
它的构造函数应该接受logger作为依赖,并且它的__invoke方法可以用来“神奇地”检索记录器。
接下来,为它创建一个工厂,实现Zend\ServiceManager\FactoryInterface
并使用它来注入依赖项(即记录器)
在servicemanager配置中注册工厂:
'controller_plugins' => array(
'factories' => array(
'Logger' => 'MyApp\Controller\Plugin\Logger',
)
),
然后您可以在控制器中调用它,如下所示:
$this->logger();
(有关创建自定义控制器插件的详细信息,请参阅http://lab.empirio.no/custom-controller-plugin-in-zf2.html)。
延迟加载记录器可以通过在lazy_services
配置的service_manager
密钥下注册为延迟服务来处理。
对于您的服务,您可以实现自己的ServiceLocator
版本(也称为插件管理器)。
它会像ViewHelperManager
,ControllerPluginManager
,ValidatorPluginManager
等一样工作。
我不会解释如何做到这一点,因为它有很多代码,网上有很多关于如何创建代码的方法。
修改强> 正如下面提到的@tasmaniski你可以使用基于标记接口的注入使用初始化器(ZF2在内部通过'Aware'接口使用它)。 请注意,初始化程序相对较慢,尤其是在使用不当时,即作为Module.php或module.config.php文件中的闭包。
此外,初始化程序会被ServiceManager
的{{1}} mtehod提取的每个服务调用,因此会增加很多开销。
然而,这是一个比编写自己的插件管理器实现更容易,更快速的解决方案。
答案 1 :(得分:0)
我在我的应用程序/架构中有完全相同的问题。 所以解决方案是:
在Controllers的范围内,正如@FuST所说,你必须创建控制器插件。比所有控制器都可以使用记录器。
在服务范围内,我可以进行"接口注入"。 因此,在您的服务中,您必须添加3件事:
// #1 Create interface with setLogger($logger); method
class YourService implement LoggerInterface {
private $logger; // #2 Define private $logger;
// #3 Add method that you will use to inject the $logger later
public function setLogger($logger){
$this->logger = $logger;
}
}
创建初始化程序并在每个实现 LoggerInterface 的类中注入$ logger。