Y a-t-il jamais une raison de préférer $ model-> load () aux contrats de service?

24

Je comprends que la façon préférée de travailler entre les modules dans Magento 2 est d'utiliser les contrats de service.

Donc, si je veux charger un produit, j'utilise le référentiel produit:

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

qui est par contrat renvoyant une instance de Magento\Catalog\Api\Data\ProductInterface.

Mais je pourrais également utiliser l'ancienne méthode à la place, en appelant directement la couche de domaine:

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

Y a-t-il des cas où cela serait nécessaire ou utile?

Les devdocs disent (surlignage ajouté):

Un module peut appeler directement un autre module. Cette solution étroitement couplée n'est pas recommandée dans la plupart des situations, mais est parfois inévitable .

[...]

Votre stratégie pour appeler le code de couche de domaine d'un autre module dépend fortement de la configuration et des besoins uniques de votre système.

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

Et un commentaire sur une question connexe a déclaré:

l'utilisation du référentiel vous donnera un modèle de données produit ( Api/Data/Product), qui est un modèle produit converti en DTO simplifié. Quelque chose à considérer, car ils sont très différents

Mais pour autant que je puisse voir, les objets sont les mêmes dans des conditions normales, seuls les types de retour par phpDoc diffèrent ( Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product)

Fabian Schmengler
la source

Réponses:

23

La raison d'utiliser ProductRepository's get/ getByIdau lieu d'une load()méthode ProductFatory , est parce que la première est d'un niveau plus élevé que la seconde.

Un ProductRepository- tout comme un ProductFactory- peut renvoyer un Product modèle , mais ce n'est pas ce que M2 veut que vous considériez. Ce n'est pas ce que \Magento\Catalog\Api\ProductRepositoryInterface::getById()dit le bloc doc. Il dit @return \Magento\Catalog\Api\Data\ProductInterface, qui est une interface qu'un modèle de produit met en œuvre.

Donc, vous devez utiliser la couche API autant que possible, car:

  • Api/Data La couche est également utilisée dans l'API Web
  • les modèles peuvent - et seront probablement - refactorisés à un moment donné; Api/Data/Productne le fera pas.
  • Pour obtenir un produit dans vos classes, vous devez injecter soit une usine de béton ( ProductFactory) soit une interface ( ProductRepository). Je ne pense pas que vous souhaitiez que votre module repose sur autre chose qu'une interface. Je ne suis donc pas d'accord avec ce type d'injection .

Je considère que ce n'est qu'une autre minuscule couche d'abstraction au- dessus des modèles, pour répondre à l'API Web (REST, SOAP, etc.).

Citant cette réponse:

Espérons que vous aimerez les contrats de service lorsque votre module personnalisé ne sera pas rompu après les prochaines versions de Magento 2 (bien sûr, si vous ne contournez pas les contrats de service et utilisez directement les modèles / collections / modèles de ressources). Et lorsque vous commencez à consommer / exposer l'API Web Magento 2, qui est désormais basée sur les mêmes contrats de service. Vous devez donc apporter des modifications à un seul endroit (par exemple via un plugin) et elles seront appliquées partout. C'était impossible dans Magento 1.

Nevermind
la source
Pas exactement ce que je demandais mais c'est ce que je pensais aussi, merci pour la confirmation!
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?. Oui: lorsque vous devez appeler la méthode d' un modèle et non celle d' un modèleApi/Data/Product . Est-ce mieux? :)
nevvermind
Oui, cela a du sens :)
Fabian Schmengler
14

Pour moi, il n'y a aucune raison d'utiliser la loadméthode sur la méthode getById/ get.

Je ne dis pas que j'ai raison mais voici comment je vois les choses.

Ok alors voici la getByIdméthode (la getméthode est similaire mais utilise le sku au lieu de 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];
}

Comme vous pouvez remarquer le code que vous avez collé:

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

Fait partie de cette fonction.

Cependant, la condition supplémentaire utilise des instances mises en cache pour éviter un rechargement supplémentaire au cas où vous auriez précédemment utilisé la getByIdou la getméthode pour le même id (ou sku dans le cas de la getméthode) .

Vous pouvez penser qu'une bonne raison d'utiliser loadpourrait être d'éviter d'utiliser ces instances mises en cache (dans quel cas cela pourrait-il être une bonne raison? Que je ne sais pas) mais getByIdles getméthodes et ont un $forceReloadparamètre qui peut être défini sur true pour évitez d'utiliser ces instances de cache.

C'est pourquoi pour moi, il n'y a aucune bonne raison d'utiliser la loadméthode getByIdou les getméthodes.

Raphael chez Digital Pianism
la source
2

Veuillez comprendre la différence entre les référentiels et les collections.

Dans votre exemple, si vous utilisez des référentiels, vous obtiendrez un tableau Magento\Catalog\Api\Data\ProductInterfacedifférent de celui d'une collection de Magento\Catalog\Model\Product.

Les référentiels et l'interface de données vous offrent un niveau d'interface élevé qui devrait être garanti comme compatible dans les futures versions . C'est pourquoi c'est l'approche suggérée.

J'espère que ça aide.

Phoenix128_RiccardoT
la source