Чи коли-небудь є причина віддати перевагу $ 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)

Відповіді:


23

Причиною використання методу ProductRepositorys get/ getByIdзамість методу ProductFatory є те load(), що перший має більш високий рівень, ніж другий.

A ProductRepository- так само, як ProductFactory- може повернути Product модель , але M2 це не те, що ви хочете розглянути. Це не те \Magento\Catalog\Api\ProductRepositoryInterface::getById(), що говорить блок doc. У ньому йдеться про те @return \Magento\Catalog\Api\Data\ProductInterface, який інтерфейс реалізує модель продукту .

Так, ви повинні використовувати шар API, коли це можливо, тому що:

  • Api/Data шар також використовується в Web Api
  • моделі можуть - і, ймовірно, будуть відновлені в якийсь момент; Api/Data/Productне буде.
  • Щоб отримати продукт у своїх класах, вам потрібно ввести або конкретний завод ( ProductFactory), або інтерфейс ( ProductRepository). Я не думаю, що ви хочете, щоб ваш модуль покладався ні на що, окрім інтерфейсу. Тому я не згоден з цим типом ін'єкцій .

Я вважаю, що це просто ще один крихітний шар абстракції над моделями для обслуговування веб-API (REST, SOAP тощо).

Цитуючи цю відповідь:

Сподіваємось, вам сподобаються контракти на обслуговування, коли ваш користувальницький модуль не буде порушений після наступних випусків Magento 2 (звичайно, якщо ви не обходите договори на обслуговування та не використовуєте моделі / колекції / моделі ресурсів безпосередньо). І коли ви почнете споживати / викривати веб-API Magento 2, який тепер базується на тих самих контрактах на обслуговування. Тож вам доведеться вносити зміни лише в одному місці (наприклад, за допомогою плагіна), і вони застосовуватимуться всюди. Це було неможливо в Magento 1.


Не зовсім те, про що я просив, але саме так я і подумав, дякую за підтвердження!
Фабіан Шменглер

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

14

Для мене немає причин використовувати loadметод над getById/ getметодом.

Я не кажу, що я правий, але ось, як я бачу речі.

Добре, ось ось getByIdметод ( getметод схожий, але використовує sku замість ідентифікатора):

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);

Є частиною цієї функції.

Однак додаткова умова використовує кешовані екземпляри, щоб уникнути додаткового перезавантаження, якщо ви раніше використовували getByIdабо getметод для того ж ідентифікатора (або sku у випадку getметоду) .

Ви можете подумати, що вагомою причиною для використання loadможе бути уникнення використання таких кешованих екземплярів (у цьому випадку це може бути вагомою причиною? Що я не знаю), але getByIdу getметодів є $forceReloadпараметр, для якого можна встановити значення true уникайте використання цих екземплярів кешу.

Ось чому для мене немає жодної вагомої причини застосовувати loadметод getByIdабо getметоди.


2

Будь ласка, зрозумійте різницю між сховищами та колекціями.

У вашому прикладі, якщо ви використовуєте сховища, ви отримаєте масив, Magento\Catalog\Api\Data\ProductInterfaceякий відрізняється від отримання колекції Magento\Catalog\Model\Product.

Репозиторії та інтерфейс даних забезпечують високий рівень інтерфейсу, який слід гарантувати як сумісний у майбутніх повторах . Ось чому саме такий запропонований підхід.

Сподіваюся, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.