M

Suivez nous

Optimisation des Collections Magento 2

Une collection Magento 2 est un objet qui sert de query builder pour manipuler efficacement des ensembles d’entités (produits, commandes, clients, etc.) en base de données. Elle permet de construire des requêtes SQL complexes tout en restant dans l’architecture Magento, et d’optimiser les performances en évitant les requêtes unitaires répétitives qui surchargeraient MySQL

Instanciation d’une collection

La bonne pratique est de toujours passer par une CollectionFactory injectée en dépendance, puis d’utiliser la méthode create() pour obtenir une nouvelle instance de collection.
On n’utilise jamais $model->getCollection() (héritage Magento 1), car cela ne respecte pas l’architecture moderne et pose des problèmes de testabilité et de réutilisation

public function __construct(
    \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory
) {
    $this->productCollectionFactory = $productCollectionFactory;
}

public function getProducts()
{
    $collection = $this->productCollectionFactory->create();
    // Manipulation de la collection...
}

Pourquoi utiliser les collections ?

Dans Magento 2, tous les objets (models, collections, repositories) sont des abstractions qui reposent sur une vraie base de données relationnelle : chaque manipulation d’objet ou de collection se traduit in fine par une requête SQL optimisée, générée par le framework.

Contrairement à une idée reçue, on ne fait jamais (et on n’a jamais fait) de requêtes unitaires en boucle du type :
SELECT * FROM table WHERE id = 2;
SELECT * FROM table WHERE id = 3;
Ce serait catastrophique pour les performances, car cela multiplie les allers-retours entre PHP et MySQL et surcharge la base inutilement.

L’objectif des collections Magento 2 est justement d’éviter ce schéma : on construit une requête unique, optimisée, qui ramène tout le jeu de résultats d’un coup, avec la possibilité de filtrer, trier, paginer, joindre, etc.

Méthodes principales sur les collections

addFieldToFilter($field, $condition)
Permet de filtrer les résultats (équivalent du WHERE SQL).
Les opérateurs disponibles sont :

  • 'eq' : égal à
  • 'neq' : différent de
  • 'like' : correspondance partielle
  • 'in' : dans un tableau de valeurs
  • 'nin' : pas dans un tableau de valeurs
  • 'gt' : supérieur à
  • 'lt' : inférieur à
  • 'gteq' : supérieur ou égal
  • 'lteq' : inférieur ou égal
  • 'null' : est NULL
  • 'notnull' : n’est pas NULL

Exemple :

$collection->addFieldToFilter('status', ['eq' => 1]);
$collection->addFieldToFilter('name', ['like' => '%promo%']);
$collection->addFieldToFilter('id', ['in' => [1,2,3]]);

addFieldToSelect($field) : définit quelles colonnes inclure dans la requête. Par défaut, toutes les colonnes sont incluses[3].

setPageSize($size) : nombre d’éléments par page (LIMIT SQL).

setCurPage($page) : numéro de la page courante (OFFSET SQL).

setOrder($field, $direction) : tri sur un champ, direction 'ASC' ou 'DESC'

Manipulation avancée : l’objet Select

Quand les méthodes natives ne suffisent plus, on accède à l’objet Select sous-jacent :

Attention à l’objet retourné :
Les méthodes de la collection (ex : addFieldToFilter) retournent toujours la collection, ce qui permet le chaînage.
Mais les méthodes de l’objet Select (getSelect()->group(), getSelect()->columns(), etc.) retournent un objet Zend_Db_Select et non une collection.
Il ne faut donc jamais réaffecter le résultat à ta variable collection, sinon tu perds toutes les méthodes de la collection et casses le process.

// Correct
$collection->getSelect()->group('customer_id');
// Incorrect
$collection = $collection->getSelect()->group('customer_id'); // $collection n'est plus une collection !

group :

$collection->getSelect()->group('customer_id');

columns:

Attention, columns([]) remplace la liste des colonnes sélectionnées. Il faut donc inclure tous les champs nécessaires, sinon la collection ne pourra plus hydrater correctement les objets.

Utilise toujours Zend_Db_Expr pour les fonctions SQL (COUNT, SUM, etc.), sinon Zend va échapper les caractères et la requête sera incorrecte.

$collection->getSelect()->columns([
    'nb_reviews' => new \Zend_Db_Expr('COUNT(review_id)')
]);

join :
Pour faire une jointure sur une autre table, la syntaxe recommandée est :

$collection->getSelect()->join(
    ['alias' => 'table_name'], // alias et nom de la table
    'main_table.id = alias.foreign_id', // condition ON
    ['field1' => 'alias.field1', 'field2' => 'alias.field2'] // champs sélectionnés et renommés
);

Utiliser un tableau clé/valeur pour le 3e paramètre permet de renommer les champs et d’éviter les conflits de noms.

En résumé, maîtriser les collections Magento 2 est indispensable pour optimiser la performance de votre site e-commerce et garantir une gestion efficace des données produits, clients ou commandes. En exploitant les collections, vous évitez les requêtes SQL unitaires coûteuses et bénéficiez d’une requête unique, filtrée, triée et paginée, générée par le framework Magento 2.
Pourquoi est-ce crucial ? Parce qu’une bonne utilisation des collections Magento 2 améliore la rapidité du site, la satisfaction client et le taux de conversion, tout en assurant la scalabilité de votre boutique en ligne.

Vous souhaitez aller plus loin dans l’optimisation Magento 2 ?
Découvrez nos autres guides dédiés à la performance Magento 2, à l’utilisation de thèmes front-end alternatifs comme Breeze, ainsi qu’à l’optimisation des modèles (models) Magento 2 : apprenez quand privilégier un plugin, un observer ou l’injection de dépendances pour étendre ou modifier le comportement natif de Magento, tout en garantissant la maintenabilité et la performance de votre boutique.