Czy kiedykolwiek istnieje powód, aby preferować $ model-> load () nad umowami serwisowymi?

24

Rozumiem, że preferowanym sposobem pracy między modułami w Magento 2 jest korzystanie z umów serwisowych.

Więc jeśli chcę załadować produkt, korzystam z repozytorium produktów:

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

czyli na podstawie umowy zwracającej instancję Magento\Catalog\Api\Data\ProductInterface.

Ale zamiast tego mógłbym również użyć starego sposobu, wywołując bezpośrednio warstwę domeny:

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

Czy jest jakiś przypadek, w którym byłoby to konieczne lub przydatne?

Devdocs mówią (wyróżnienie dodane):

Moduł może bezpośrednio wywoływać inny moduł. To ściśle powiązane rozwiązanie nie jest zalecane w większości sytuacji, ale czasami jest nieuniknione .

[...]

Twoja strategia wywoływania kodu warstwy domeny innego modułu jest wysoce zależna od unikalnej konfiguracji i potrzeb twojego systemu.

Źródło: http://devdocs.magento.com/guides/v2.0/architecture/archi_perspectives/domain_layer.html

A komentarz do powiązanego pytania brzmiał:

użycie repozytorium da model danych produktu ( Api/Data/Product), który jest modelem produktu przekonwertowanym na głupi DTO. Coś do rozważenia, ponieważ są one zupełnie różne

Ale o ile widzę, obiekty są takie same w normalnych warunkach, tylko typy zwracane na phpDoc różnią się ( Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product)

Fabian Schmengler
źródło

Odpowiedzi:

23

Powodem użycia metody ProductRepository„s get/ getByIdzamiast metody ProductFatory” load()jest to, że ta pierwsza jest na wyższym poziomie niż druga.

ProductRepository- podobnie jak ProductFactory- może powrócić do Product modelu , ale to nie to, co chce, M2 do rozważenia. To nie to, co \Magento\Catalog\Api\ProductRepositoryInterface::getById()mówi, jest blok doc. Mówi @return \Magento\Catalog\Api\Data\ProductInterface, że jest interfejsem, który implementuje model produktu .

W związku z tym należy w miarę możliwości korzystać z warstwy API, ponieważ:

  • Api/Data warstwa jest również używana w interfejsie WWW
  • modele mogą - i prawdopodobnie będą - w pewnym momencie zostać refaktoryzowane; Api/Data/Productnie będzie.
  • Aby uzyskać produkt w swoich klasach, musisz wstrzyknąć konkretną fabrykę ( ProductFactory) lub interfejs ( ProductRepository). Nie sądzę, żebyś chciał, aby twój moduł polegał wyłącznie na interfejsie. Dlatego nie zgadzam się z tego typu zastrzykami .

Uważam, że jest to kolejna drobna warstwa abstrakcji nad modelami, która obsługuje interfejs API sieci Web (REST, SOAP itp.).

Cytując odpowiedź:

Mamy nadzieję, że pokochasz kontrakty serwisowe, gdy Twój moduł niestandardowy nie zostanie zepsuty po kolejnych wydaniach Magento 2 (oczywiście, jeśli nie ominiesz umów serwisowych i nie użyjesz bezpośrednio modeli / kolekcji / modeli zasobów). A kiedy zaczniesz korzystać z interfejsu API Magento 2, który jest teraz oparty na tych samych umowach serwisowych. Musisz więc wprowadzać zmiany tylko w jednym miejscu (np. Przez wtyczkę) i będą one stosowane wszędzie. W Magento 1 było to niemożliwe.

nevvermind
źródło
Nie do końca o to prosiłem, ale tak też myślałem, dzięki za potwierdzenie!
Fabian Schmengler 18.04.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?. Tak: gdy trzeba wywołać metodę modelu , a nie metodę Api/Data/Product. Czy to jest lepsze? :)
nevvermind,
Tak, to ma sens :)
Fabian Schmengler 18.04.16
14

Dla mnie nie ma powodu, aby używać loadmetody zamiast metody getById/ get.

Nie mówię, że mam rację, ale oto, jak widzę różne rzeczy.

Ok, więc oto getByIdmetoda ( getmetoda jest podobna, ale używa sku zamiast 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];
}

Jak widać wklejony kod:

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

Jest częścią tej funkcji.

Jednak dodatkowy warunek używa buforowanych instancji, aby uniknąć dodatkowego przeładowania w przypadku, gdy wcześniej używałeś metody getByIdlub getdla tego samego identyfikatora (lub SKU w przypadku getmetody) .

Możesz myśleć, że to dobry powód do użytku loadmoże być do uniknięcia stosowania tych buforowane instancji (w tym przypadku to może być dobry powód? Że nie wiem), ale getByIdi te getmetody mają $forceReloadparametr, który może być ustawiony na true, aby unikaj używania tych instancji pamięci podręcznej.

Dlatego dla mnie nie ma żadnego powodu, aby używać loadmetody getByIdlub getmetod.

Raphael at Digital Pianism
źródło
2

Proszę zrozumieć różnicę między repozytoriami a kolekcjami.

W twoim przykładzie, jeśli używasz repozytoriów, otrzymasz tablicę, Magento\Catalog\Api\Data\ProductInterfacektóra różni się od pobierania kolekcji Magento\Catalog\Model\Product.

Repozytoria i interfejs danych zapewniają wysoki poziom interfejsu, który powinien być zagwarantowany jako kompatybilny w przyszłych wersjach . Właśnie dlatego jest to sugerowane podejście.

Mam nadzieję, że to pomoże.

Phoenix128_RiccardoT
źródło