L'histoire des collections dans Magento 2?


25

Je sais que beaucoup de code qui est actuellement dans Magento 2 (2.1.2) est plus ou moins porté depuis Magento 1 et que beaucoup de code sera remplacé par un équivalent à l'avenir. Dans cet aspect, je me demande quel est l'avenir des collections dans Magento 2.

Laissez-moi expliquer:

Magento 1:

Dans Magento 1, nous avons l'habitude d'obtenir une collection comme celle-ci:

$products = Mage::getModel('catalog/product')->getCollection();

Nous pourrions alors appliquer des filtres et d'autres opérations à la collection:

$products->addAttributeToFilter('price', ['gteq' => 10]);
$products->addFieldToFilter('created_at', ['lt' => '2016-10-10']);
$products->setPageSize(10);
// ... etc ...

Et enfin et surtout, notre collection retournerait les modèles:

foreach ($products as $product) {
    echo get_class($product); // Mage_Catalog_Model_Product
}

Magento 2:

Magento ajoute de nombreuses nouvelles couches d'abstraction, mettant en œuvre une manière de travailler plus SOLIDE. Cela signifie que lorsque nous voulons une liste d'entités, nous la demandons à partir d'un référentiel:

$productResults = $this->productRepository->getList($searchCriteria);

Si nous voulons appliquer des filtres, nous utilisons une combinaison du SearchCriteriaBuilder, du FilterGroupBuilder, du FilterBuilderet du SortOrderBuilder:

$this->searchCriteriaBuilder->addSortOrder(
    $this->sortOrderBuilder
        ->setField('created_at')
        ->setAscendingDirection()
        ->create()
);
$priceFilter = $this->filterBuilder
    ->setField('price')
    ->setValue(10)
    ->setConditionType('gteq')
    ->create();
$createdAtFilter = $this->filterBuilder
    ->setField('created_at')
    ->setValue('2016-10-10')
    ->setConditionType('lt')
    ->create();
$filterGroups = [
    $this->filterGroupBuilder->addFilter($priceFilter)->create(),
    $this->filterGroupBuilder->addFilter($createdAtFilter)->create()
];

Et si nous voulons parcourir nos résultats, nous obtenons des modèles de données, pas des modèles réels (hérités):

foreach ($productResults->getItems() as $product) {
    echo get_class($product); // \Magento\Catalog\Model\Data\Product
}

Ce type d'abstraction suit le principe SOLIDE et embrasse le principe de «composition sur héritage» . Toutes les opérations «exotiques» qui seraient autrement effectuées sur la collection (comme les jointures par exemple) sont effectuées en interne dans le référentiel, ce qui facilite également l'utilisation en dehors du module.

La question:

Tout cela me fait me demander: avec toute l'approche référentiel / modèle de données, y a-t-il une place dans l'avenir de Magento 2 pour les collections? Les collections doivent-elles uniquement être utilisées en interne par le module lui-même et non en dehors de celui-ci? Ou vont-ils être dépréciés au profit d'Entity Manager?

Actuellement, si vous souhaitez adopter les modèles de données, vous devez toujours créer un modèle hérité (hérité de \Magento\Framework\Model\AbstractModel) juste pour faire fonctionner la collection (car Magento\Framework\Data\Collection::setItemObjectClassle modèle doit s'étendre depuis Magento\Framework\DataObject). Et vous devez collecter pour pouvoir filtrer dans votre référentiel. Mais là encore, dans le référentiel, vous devez «convertir» votre modèle (normal) en modèle de données.

Ou devons-nous l'implémenter comme le référentiel de commandes, où le getList()retourne une instance de Magento\Sales\Api\Data\OrderSearchResultInterface, mais sous l'eau, les résultats de la recherche ne sont rien de plus qu'une collection régulière qui implémente cette interface. Fait amusant: les résultats de la recherche indiquent qu'il renverra un tableau de modèles de données ( Magento\Sales\Api\Data\OrderInterface[]), mais si vous analysez le code, getItems()s'exécutera Magento\Framework\Data\Collection::getItems()qui, en retour, ne renvoie pas les modèles de données, mais les modèles de commande (tels que définis par Magento\Sales\Model\ResourceModel\Order\Collection::_construct()). Voilà pour la «composition plutôt que l'héritage».

Beaucoup de questions sur quelle est la bonne façon dans Magento 2. Encore une fois, il y a 100 façons de faire la même chose, mais qu'est-ce que 'The Magento Way'? Ou suis-je tout simplement sur la mauvaise voie ici?


2
Poser les vraies questions ici +1. J'aimerais vraiment une réponse du développeur principal ici
Marius

Je crois que le plan consiste à éliminer progressivement les collections. Cependant, comme vous l'avez remarqué, cela n'est presque pas encore accompli et il existe de nombreux domaines qui semblent être dans différents états de refactorisation (avoir l'API stable comme Magento \ Sales \ Api \ Data \ OrderSearchResultInterface, permet à Magento de remplacer ce se passe plus facilement sous le capot plus tard). Cela n'aide pas que les différentes implémentations de getList ne soient pas encore aussi capables que ce que nous pouvons actuellement faire avec les collections. L'incohérence que vous avez notée autour du retour déclaré pourrait être digne d'un problème sur github.
Kristof à Fooman

Réponses:


16

Les collections ne sont plus obsolètes maintenant. Alors que certains modules exposent déjà les API de contrat de service, d'autres n'exposent toujours que les API de modèle / collection.

Le plan est le suivant:

  1. Refléter l'état actuel avec une meilleure couverture @api: annoter des collections abstraites et des collections spécifiques dans certains modules avec @api
  2. Améliorer le cadre de persistance pour permettre la création facile de contrats de service sans dépendre des API basées sur l'héritage: collections, modèles, modèles de ressources
  3. Obsolète la collection d'abrégés pour ne pas promouvoir les implémentations basées sur la collection des contrats de service
  4. Libérez progressivement les nouvelles versions des modules avec les API de contrat de service

Les collections seront donc obsolètes à un moment donné, mais elles font désormais partie des API Magento 2.

En ce qui concerne la mise en œuvre des contrats de service, - les modèles et les collections sont le seul moyen pratique de les mettre en œuvre dans Magento <= 2.1. Les contrats de service ne sont que des interfaces. Leur implémentation ne fait pas partie de l'API publique et peut être modifiée ultérieurement.


1
Merci pour votre réponse. Alors, quel conseil donneriez-vous aux développeurs qui créent de nouveaux modules? Ma stratégie actuelle est de créer des contrats de service qui (sous l'eau) utilisent toujours des collections car a) cela rend le filtrage facile, et b) le gestionnaire d'entités est encore trop expérimental / non documenté. À un moment donné, le fonctionnement interne peut être remplacé par autre chose, mais l'interface reste la même. Mais si je comprends bien votre réponse, c'est la bonne façon pour l'instant non?
Giel Berkers

Correct. J'ai modifié ma réponse pour refléter cela.
Anton Kril

1
Compte tenu de ce qui précède, quelle serait la bonne façon de mettre en œuvre une fonctionnalité qui nécessite des données qui ne peuvent pas être récupérées via des contrats de service? Par exemple, si le module A nécessite toutes les commandes filtrées par mode de paiement.
Stjepan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.