C'è mai un motivo per preferire $ model-> load () rispetto ai contratti di assistenza?


24

Comprendo che il modo preferito di lavorare tra i moduli in Magento 2 sta usando i contratti di servizio.

Quindi, se voglio caricare un prodotto, utilizzo il repository del prodotto:

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

che è contrattualmente restituito un'istanza di Magento\Catalog\Api\Data\ProductInterface.

Ma potrei anche usare il vecchio modo, chiamando direttamente il livello di dominio:

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

Esiste un caso in cui ciò sarebbe necessario o utile?

I devdocs dicono (punto culminante aggiunto):

Un modulo può chiamare direttamente in un altro modulo. Questa soluzione strettamente accoppiata non è consigliata per la maggior parte delle situazioni, ma a volte è inevitabile .

[...]

La tua strategia per chiamare il codice del livello di dominio di un altro modulo dipende fortemente dalla configurazione unica e dalle esigenze del tuo sistema.

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

E un commento su una domanda correlata ha dichiarato:

l'utilizzo del repository ti darà un modello di dati del prodotto ( Api/Data/Product), che è un modello di prodotto convertito in un DTO minimizzato. Qualcosa da considerare, poiché sono abbastanza diversi

Ma per quanto posso vedere gli oggetti sono gli stessi in condizioni normali, solo i tipi di ritorno per phpDoc differiscono ( Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product)

Risposte:


23

La ragione per usare ProductRepositorys' get/ getByIdanziché di un ProductFatory load()metodo, è perché il primo è di un livello superiore rispetto al secondo.

A ProductRepository- proprio come un ProductFactory- potrebbe restituire un Product modello , ma non è quello che M2 vuole che tu consideri. Questo è non quello che \Magento\Catalog\Api\ProductRepositoryInterface::getById()'s blocco doc dice. Dice @return \Magento\Catalog\Api\Data\ProductInterfaceche è un'interfaccia che sta implementando un modello di prodotto .

Quindi, dovresti usare il livello API quando possibile, perché:

  • Api/Data il layer viene utilizzato anche nell'API Web
  • i modelli possono - e probabilmente lo saranno - saranno rifattorizzati a un certo punto; Api/Data/Productno.
  • Per ottenere un prodotto nelle tue classi, devi iniettare una factory concreta ( ProductFactory) o un'interfaccia ( ProductRepository). Non credo che tu voglia che il tuo modulo si basi su un'interfaccia. Quindi non sono d'accordo con questo tipo di iniezione .

Ritengo che sia solo un altro piccolo livello di astrazione sopra i modelli, per soddisfare l'API Web (REST, SOAP ecc.).

Citando questa risposta:

Si spera che adorerai i contratti di servizio quando il tuo modulo personalizzato non verrà rotto dopo le prossime versioni di Magento 2 (ovviamente se non bypassi i contratti di servizio e utilizzi direttamente modelli / collezioni / modelli di risorse). E quando inizi a consumare / esporre l'API Web Magento 2, che ora si basa sugli stessi contratti di servizio. Quindi devi apportare modifiche solo in un posto (ad es. Tramite plugin) e saranno applicate ovunque. Questo era impossibile in Magento 1.


Non esattamente quello che stavo chiedendo, ma è anche quello che ho pensato, grazie per la conferma!
Fabian Schmengler,

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?. Sì: quando è necessario chiamare il metodo di un modello e non quello di un modelloApi/Data/Product . È meglio questo? :)
nevvermind,

Sì, ha senso :)
Fabian Schmengler,

14

Per me, non c'è motivo di usare il loadmetodo sopra il metodo getById/ get.

Non dico di avere ragione, ma ecco come vedo le cose.

Ok, quindi ecco il getByIdmetodo (il getmetodo è simile ma utilizza lo sku anziché l'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];
}

Come puoi notare il codice che hai incollato:

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

Fa parte di questa funzione.

Tuttavia, la condizione aggiuntiva utilizza istanze memorizzate nella cache per evitare un ulteriore ricaricamento nel caso in cui sia stato precedentemente utilizzato getByIdil getmetodo o per lo stesso ID (o sku nel caso del getmetodo) .

Potresti pensare che un buon motivo per usare loadpotrebbe essere quello di evitare di usare quelle istanze memorizzate nella cache (nel qual caso potrebbe essere un buon motivo? Che non lo so) ma getByIdi getmetodi e hanno un $forceReloadparametro che può essere impostato su true evitare di usare quelle istanze della cache.

Ecco perché, per me, non ci sono buoni motivi per usare il loadmetodo getByIdo i getmetodi.


2

Comprendi la differenza tra repository e raccolte.

Nel tuo esempio, se usi i repository, otterrai una matrice Magento\Catalog\Api\Data\ProductInterfaceche è diversa dall'ottenere una raccolta di Magento\Catalog\Model\Product.

I repository e l'interfaccia dati ti offrono un alto livello di interfaccia che dovrebbe essere garantito come compatibile in futuro rilasci . Questo è il motivo per cui è l'approccio suggerito.

Spero che sia d'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.