Comment enregistrer des entités de modèles nouvelles ou mises à jour?

10

Dans Magento 2, nous avons des classes de référentiels. La méthode classique save()largement utilisée dans Magento 1.9 est déconseillée, si je ne me trompe, de 2.04 ou 2.05. J'utilisais des usines pour créer un nouvel objet et après avoir défini les propriétés du nouveau, par exemple le produit que j'ai appelé save():

$productFactory->create()->setName()...->save()

D'un autre côté, nous avons des référentiels contenant également la méthode save. Je l'utilise en quelques mots comme ceci:

$product = $productFactory->create()->setName()... $productRepository->save($product)

Dans mon code, j'ai des classes qui fonctionnent dans les deux sens. J'ai également remarqué que parfois des manières différentes signifient un comportement différent. Le chemin avec les référentiels at-il fourni une validation supplémentaire des données?

De quelle façon dois-je le faire?

Bartosz Kubicki
la source

Réponses:

10

Voyons d'abord ce qui se passe si vous utilisez la save()méthode directement sur un productmodèle comme

/**
 * @var Magento\Catalog\Model\Product $product
 */
$product->save();

La classe de modèle elle-même est

Magento\Catalog\Model\Product

Dans cette classe, recherchez la définition de la méthode save ().

Aucun trouvé non? Eh bien, il y a beforeSave () et afterSave (), mais pas save () lui-même. Intéressant, non?

Ensuite, nous devons examiner les classes parentes de Magento\Catalog\Model\Product.

Nous devons passer Magento\Catalog\Model\AbstractModelet Magento\Framework\Model\AbstractExtensibleModel, juste pour arriver enfin à Magento\Framework\Model\AbstractModel.

Effectivement, il y a une méthode save () ici et elle ressemble à quelque chose

public function save()
{
    $this->_getResource()->save($this);
    return $this;
}

Nous voyons maintenant, chaque fois que save () est appelée sur n'importe quel modèle, la méthode save () de celle-ci AbstractModelest appelée, et l'implémentation est que le MODÈLE DE RESSOURCES effectue réellement la sauvegarde.

Ce dernier n'est pas surprenant étant donné que nous sommes toujours, comme depuis le début du temps dans Magento 1.0, créant à la fois un modèle et un modèle de ressource pour à peu près n'importe quelle entité.


Voyons maintenant comment cela ProductRepositoryfonctionne.

Permet d'ouvrir le fichier

/vendor/magento/module-catalog/Api/ProductRepositoryInterface.php

Cette interface exige qu'il existe entre autres une méthode save ().

Qui implémente réellement cette interface?

Permet d'ouvrir le fichier

/etc/di.xml

et vérifiez la ligne 10

<preference for="Magento\Catalog\Api\ProductRepositoryInterface" type="Magento\Catalog\Model\ProductRepository" />

Donc, naturellement, nous trouvons l'implication de la méthode save () à l'intérieur

/vendor/magento/module-catalog/Model/ProductRepository

et cela commence à la ligne 444, ressemblant à quelque chose comme

public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
{
    $tierPrices = $product->getData('tier_price');

    try {
    .... other code here ....

Cette méthode attend un objet $ product de type \Magento\Catalog\Api\Data\ProductInterfacepassé, mais par défaut, cela se résout en Magento\Catalog\Model\Product.

En regardant ci-dessous à la ligne 500, dans une trydéclaration, nous voyons quelque chose comme

$this->resourceModel->save($product);

Tu as bien deviné! $this->resourceModelest de type \Magento\Catalog\Model\ResourceModel\Product, déclaré comme protectedpropriété à la ligne 77.

Donc, encore une fois, le ResourceModelfait l'économie.

Mais, entre les lignes 444 et 500, c'est en fait la réponse à votre question. Tout le code exécuté ici, en effet, peut éventuellement conduire à des différences de comportement entre la sauvegarde directe du modèle et cette méthode de sauvegarde du référentiel.

Par exemple, le référentiel de produits obtiendra et traitera les liens de produits si le ignore_links_flagest défini sur 0, vérifiez s'il s'agit d'un produit existant en premier lieu, etc.

Nous devons probablement conclure que s'il est nécessaire à l'avenir de modifier la façon dont le produit est enregistré, la meilleure façon de le faire est peut-être de remplacer le référentiel de produit au lieu du modèle de produit.

Il en va de même pour la sauvegarde et la mise à jour des produits. Je préfère utiliser l'objet de référentiel de produit.

Je vous remercie également de bien vouloir /vendor/magento/module-cms/Model/PageRepository.php

C'est ainsi qu'une page CMS serait enregistrée via le référentiel. Ici, les choses sont plus simples. L'identifiant de magasin est défini et le modèle de ressource est appelé pour enregistrer immédiatement.

Avec ce dernier avis, vous conclurez que dans certains cas, il peut ne pas y avoir autant de différences entre le référentiel et la sauvegarde du modèle, mais de toute façon j'espère que vous êtes maintenant équipé pour les repérer chaque fois que vous en avez besoin.

Marjan
la source
1

Il est encouragé à utiliser des interfaces de données (par exemple \Magento\Catalog\Api\Data\ProductInterface) au lieu du modèle directement et à utiliser les référentiels pour charger et enregistrer les modèles.

Voir la documentation du développeur Magento

ochnygosch
la source
1
ok - c'est la bonne façon pour l'entité entière - mais seulement pour mettre à jour la valeur de certains attributs - je pense que charger / enregistrer l'entité entière n'est pas recommandé.
Bartosz Kubicki