有没有理由比服务合同更喜欢$ model-> load()?


24

我知道在Magento 2的模块之间工作的首选方法是使用服务合同。

因此,如果要加载产品,请使用产品存储库:

$product = $productRepository->getById($id);

通过合同返回的实例Magento\Catalog\Api\Data\ProductInterface

但是我也可以改用旧方法,直接调用域层:

$product = $productFactory->create()->load($id);

在任何情况下这是必要还是有用的?

devdocs说(突出显示):

一个模块可以直接调用另一个模块。在大多数情况下,不建议使用这种紧密耦合的解决方案,但有时不可避免的

[...]

您调用另一个模块的域层代码的策略在很大程度上取决于系统的独特配置和需求。

来源:http : //devdocs.magento.com/guides/v2.0/architecture/archi_perspectives/domain_layer.html

关于一个相关问题的评论说:

使用存储库将为您提供一个产品数据模型Api/Data/Product),该模型是转换为精简DTO的产品模型。需要考虑的东西,因为它们完全不同

但据我所见,正常情况下对象是相同的,只是每个phpDoc的返回类型不同(Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product

Answers:


23

之所以使用ProductRepository's get/ getById而不是ProductFatory的load()方法,是因为前者的级别高于后者。

A- ProductRepository就像a- ProductFactory可能会返回Product 模型,但这不是 M2希望您考虑的。这不是什么\Magento\Catalog\Api\ProductRepositoryInterface::getById()的文档块说。它说@return \Magento\Catalog\Api\Data\ProductInterface,这是产品模型正在实现的接口。

因此,您应该尽可能使用API​​层,因为:

  • Api/Data Web Api也使用了图层
  • 模型可以在某个时候重构,并且很可能会重构;Api/Data/Product将不会。
  • 要获得课堂上的产品,您需要注入具体的工厂(ProductFactory)或界面(ProductRepository)。我认为您不希望模块仅依赖接口。因此,我不同意这种注射

我认为它只是模型之上的另一个小抽象层,可以满足Web API(REST,SOAP等)的需要。

引用答案:

希望您会喜欢服务合同,因为在下一个Magento 2版本之后自定义模块不会被破坏(当然,如果您不绕过服务合同而直接使用模型/集合/资源模型)。当您开始使用/公开Magento 2 Web API时,该API现在基于相同的服务合同。因此,您只需要在一个地方进行更改(例如通过插件),这些更改将被应用到所有地方。在Magento 1中这是不可能的。


不完全是我要的,但这也是我的想法,感谢您的确认!
Fabian Schmengler '16

1
But I could also use the old way instead, calling the domain layer directly: (use factory). Is there any case where this would be necessary or useful?。是的:当您需要调用模型的方法而不是模型的方法时Api/Data/Product。这是否更好?:)
nevvermind

是的,这很有意义:)
Fabian Schmengler '16

14

对我来说,没有理由loadgetById/ get方法上使用该方法。

我并不是说我是对的,但这是我看待事情的方式。

好的,这是getById方法(get方法类似,但使用sku而不是id):

public function getById($productId, $editMode = false, $storeId = null, $forceReload = false)
{
    $cacheKey = $this->getCacheKey(func_get_args());
    if (!isset($this->instancesById[$productId][$cacheKey]) || $forceReload) {
        $product = $this->productFactory->create();
        if ($editMode) {
            $product->setData('_edit_mode', true);
        }
        if ($storeId !== null) {
            $product->setData('store_id', $storeId);
        }
        $product->load($productId);
        if (!$product->getId()) {
            throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
        }
        $this->instancesById[$productId][$cacheKey] = $product;
        $this->instances[$product->getSku()][$cacheKey] = $product;
    }
    return $this->instancesById[$productId][$cacheKey];
}

您会注意到粘贴的代码:

$productFactory->create()->load($id);

是此功能的一部分。

但是,额外条件使用缓存的实例来避免额外的重载,以防您先前将getByIdget方法用于相同的id(或sku get

您可能会认为,使用的一个很好的理由load可能是避免使用那些缓存的实例(在这种情况下,这可能是一个很好的理由?我不知道),但是getByIdget方法具有$forceReload可以设置为true 的参数。避免使用那些缓存实例。

这就是为什么对我而言,没有充分的理由使用loadmethod over getByIdgetmethods。


2

请了解存储库和集合之间的区别。

在您的示例中,如果使用存储库,则将获得与Magento\Catalog\Api\Data\ProductInterface的集合不同的数组 Magento\Catalog\Model\Product

存储库和数据接口为您提供了较高的接口级别,应该保证在以后的版本中它们都兼容。这就是为什么它是建议的方法。

希望能帮助到你。

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.