Magento 2 Helper实例


11

当我认为我从Magento 2缠绕DI系统时,出现了一些问题,并将其解包。
我在核心代码中看到了访问助手的不同方式。
例如,Magento\Catalog\Controller\Category::_initCategory其中有:

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

但是在Magento\Catalog\Block\Category\View帮助器中注入了构造函数

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

这使我认为应该在控制器和块(和模型)中以不同的方式访问帮助程序,但是随后我找到了一个在构造函数中注入了帮助程序的控制器Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute

请为我清除雾气。
什么时候应该使用DI objectManager?什么时候应该使用DI ?为什么?
我已经读过这个问题:在Magento 2中实例化助手。这只是一个后续问题。

Answers:


10

我希望在可能的地方使用DI,因为使用对象管理器已经违反了demeter法则。使用对象管理器时,这些依赖项仅隐藏在方法逻辑中。


是的 我同意。我将使用DI,但是我很好奇为什么要在核心中完成?也许有人没有重构我提到的课程呢?
马里斯(Marius)

Afaik他们仍然在进行大量的重构,希望他们也能碰到这些地方。但是也不知道优先级,如果要在某个时候实际释放它们,这些优先级就必须存在。因此,也许将首先修复一些新功能或其他不良做法。
Tobias 2014年

如果您拥有10类功能并且只有1种功能需要特定型号怎么办?通过构造函数注入为10个函数中的每个函数加载模型是否会冗余(从性能角度来看),而我们只能在1个单个函数内使用对象管理器加载模型?
JohnyFree

6

我对Magento实现的了解不多,但是看起来好像ObjectManagerService Locator

通常,使用Service Locator访问对象中的依赖关系非常糟糕,请查阅本文

通过构造函数显式定义依赖项是一种更好的方法。它有助于解决未定义服务的单元测试和运行时问题。

将对象管理器注入到一个类中基本上就是将一个注册表注入到可以访问所有应用程序服务的类中,这显然是不对的。

我相当使用ZF2,通常为Service,Controller和任何需要依赖的类定义小型工厂类。这些工厂类可以访问服务定位器,并获取对象依赖的所有服务,然后通过构造函数将它们注入。在Factory类中使用Service Locator很好,因为它通常是丢弃的代码,例如这样的代码。

这些工厂仍然易于测试

IMO,尽可能使用构造函数注入。再说一次,我对Magento的实现并不太了解,如果它具有工厂的概念,从快速的外观来看,它看起来确实支持它们,但是显式定义您的类并使用Service Locator在Factory类中构建它们是更干净的方法。

这是来自对上述模式的了解有限的人,所以我也想听听其他人对此事的想法/经验!

更多阅读


感谢您的解释。我的问题是“为什么在核心中有两种访问助手的方法?” 所以这有点题外话,但它清除了我的其他疑问。:) 谢谢。
马里斯(Marius)

我可能会说这只是尚未重构的事情。要么那么简单,要么很简单。要求消费者始终将其所有依赖项注入Controller中,这可能会适得其反,特别是在执行RAD时。为消费者提供两种访问依赖关系的方式将允许使用RAD方法,但如果允许的话,仍然允许其他用户显式定义其依赖关系。
艾登·哈桑

5

使用帮助程序(在模板中)的另一种方法是:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]')->getMethodName();

如果您不知道,希望对您有所帮助。


这在某种程度上类似于使用对象管理器。不确定这是最好的主意。
Marius

1
据我所知,上述方法仅适用于模板。对象管理器用于控制器,块,模型等
。– rbncha

1
它与代码不在同一范围,因为模板上没有代码依赖性。模板只是使用者,不会污染任何封装破损的客户端。
demonkoryu

我不知道demonkoryu在说什么。但是,调用任何模块的助手的最好方法是这样。这是Magento。就像他们说的那样,每个块/段代码都旨在可调用/可修改,而不会触及内核。因此,一切都相互关联或具有依赖性。
rbncha

2

尽管这是一个古老的问题,但我不确定Marius是否得到了答案。我相信Marius可以回答得更好。我想简短地回答。为什么Magento 2建议使用DI代替助手?

  • 使单元测试中的隔离变得可能/容易
  • 明确定义一个类的依赖
  • 促进良好的设计(例如,单责任原则(SRP))
  • 当Magento更改这些接口的基础实现时,在模块中使用DI可以降低出现不兼容错误的风险。对于扩展开发人员来说,这是一个重要的概念。

为什么在某些情况下M2内核可能不使用DI?

  • 班级数量减少
  • 不创建不必要的接口
  • 不存在不兼容错误的风险

尽管Core目录模块已被用作帮助程序,但它已广泛使用DI。在我的研究中,我发现Magento 2在Core Catalog帮助文件中使用的功能很少,这些功能不适用于服务合同。

如果必须显式使用Magento定义的类(例如\ Magento \ Catalog \ Model \ Product),请通过具体实现而不是服务合同接口来使隐式依赖关系显式化。

毫无疑问,扩展开发人员应该使用DI而不是像Helper这样的Magento1。根据Magento 2的准则进行实施时,后果有限。违反建议时,会发生问题。


是的,我在此期间得到了答案。但是感谢您抽出宝贵的时间回答。对于在网上搜索此信息的人来说,这是有价值的信息。
马里斯(Marius)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.