Retour d’expérience suite à un PoC Sylius

Retour d’expérience suite à un PoC Sylius

Par Olivier A. le 27 mars 2019

 Lecture 7 minutes

En quelques mots, Sylius se présente comme un « framework » E-commerce, basé sur Symfony et permettant la création de sites marchands facilement personnalisables. Pour cela, la solution embarque les fonctions classiques d’un site e-commerce mais offre en plus la possibilité d'intégrer de nombreux modules et une surcharge facile de tous les composants déjà présents.

Quel est le cadre de ce PoC ?

Un prospect Synolia ayant un projet E-commerce spécifique nous a sollicité pour sa mise en oeuvre. Ce projet, bien qu'il soit e-commerce, a des particularités fortes, auxquelles il aurait été compliqué de répondre avec les solutions E-commerce classiques utilisées par Synolia. Il a été décidé conjointement avec le prospect de se tourner vers la solution Sylius 😊

Le PoC (Proof of Concept) a pour but de valider des points clés du projet afin de confirmer que Sylius est bien LA solution la plus adaptée aux besoins.

En quelques mots, vous avez fait quoi ?

Nous n'allons pas dévoiler l'intégralité du PoC, mais nous allons plutôt nous concentrer sur une fonctionnalité clé qui nous a permis de toucher à plusieurs composants de Sylius.

La but de cette fonctionnalité est que l'utilisateur sélectionne des produits liés à un abonnement qu'il a choisi. Cette sélection doit se faire durant la phase panier, selon le schéma suivant :

  • L'utilisateur navigue sur les types d'abonnements sur le site
  • L'utilisateur ajoute un abonnement à son panier et est redirigé vers le récapitulatif de son panier
  • L'utilisateur saisit son adresse (le comportement classique de Sylius)
  • Une nouvelle étape est ajoutée pour la sélection des produits disponibles selon son abonnement
  • La suite du tunnel de commande reprend le natif de Sylius

Pour faire cela, qu'avez-vous altéré sur Sylius ?

Afin de réaliser cette fonctionnalité, nous avons altéré les éléments suivants :

  • Form (Création d'un nouveau type de formulaire)
  • Controller (Modification de la méthode addAction du OrderItemController)
  • Routing (Ajout de routes personnalisées)
  • Event (Ajouts d'un évènement afin de rediriger l'utilisateur vers le récapitulatif panier)
  • Templating (Ajout de données à afficher)
  • State Machine (Ajout d'une étape dans le tunnel d'achat pour la sélection des plats)
  • Fixtures (Génération de données de test)
  • Migrations (Modification de la structure de la base de données)
  • Translation (Ajout des traductions des nouveaux contenus)
  • Service (Création de services utilisés par le nouveau Controller)

Ce qui représente un éventail assez large

Pouvez-vous m'en dire plus sur la modification du Controller ?

Le Controller que nous devions modifier est le OrderItemController. Pour faire cela il y a uniquement deux étapes à effectuer :

Créer notre class OrderItemController

Informer Sylius qu'il doit utiliser notre classe

Quelques explications

Les Controllers qui servent à gérer les ressources (Order, Product, ...) de notre application héritent de leur Controller de base (donc notre exemple Sylius\Bundle\OrderBundle\Controller\OrderItemController) qui eux-mêmes héritent tous du Sylius\Bundle\ResourceBundle\Controller\ResourceController, lequel permet de gérer les opérations de CRUD sur les ressources grâce aux fonctions :

  • showAction : affiche une ressource identifiée
  • indexAction : affiche une liste de ressources
  • createAction : affiche le formulaire de création de la ressource et créé la ressource si le formulaire est valide
  • updateAction : affiche le formulaire de mise à jour d'une ressource et modifie la ressource si le formulaire est valide
  • deleteAction : supprime une ressource
  • bulkDeleteAction : supprime une liste de ressources
  • applyStateMachineTransitionAction : applique une transition de la machine à état sur une ressource

 

Toutes ces fonctions disposent de :

  • Une vérification des droits de l'utilisateur avant de faire l'action demandée
  • Une vérification que la ressource existe (une erreur 404 est levée dans le cas contraire)
  • Un événement propagé avant chaque réalisation de l'action (par exemple "sylius.order_item.pre_create", "sylius.order_item.pre_delete" et "sylius.order_item.pre_update") qui nous permet d'ajouter un comportement métier très facilement.
  • Les appels sur l'API REST passent par les Controller. Une modification faite est donc appliquée au Front mais aussi à l'API sans aucune action manuelle, ce qui est très pratique ! Ceci est possible grâce au retour de manière agnostique de toutes les actions des Controllers.

Et en ce qui concerne la machine à état ?

Sylius utilise le bundle StateMachineBundle afin de gérer les états et les transitions entre ces états sur diverses ressources. Nous avons :

  • sylius_order_checkout : pour le déroulement de l'acte d'achat (du panier à la création de la commande)
  • sylius_order : pour les états généraux de la commande (du panier à la finalisation)
  • sylius_order_payment : pour le déroulement de l'acte de paiement (de la création du paiement à la validation par le plugin de paiement)
  • sylius_product_review : pour le déroulement de la vie d'un commentaire sur une fiche produit (de la saisie à l'affichage en passant par la validation de celui-ci)
  • sylius_order_shipping : pour le déroulement de la livraison d'une commande (de la demande d'expédition à la validation de la livraison)

Celle dont nous allons parler est sylius_order_checkout. Voici ce que nous pouvons imaginer comme modifications :

  • Retirer une étape (nous n'avons pas besoin de Livraison dans le cas où nous ne vendons que des produits dématérialisés)
  • Changer l'ordre des étapes
  • Fusionner des étapes (par exemple la saisie de l'adresse et le choix du mode de livraison)
  • Ajouter une étape (afin d'obtenir plus d'informations de l'utilisateur). C'est cette fonctionnalité qui nous intéresse !

Voici donc comment nous avons procédé pour ajouter une étape de sélection de produits liés à notre abonnement :

Au niveau de notre machine à état, ce sont les seules modifications que nous avons apporté et celles-ci suffisent à ajouter notre étape.
Pour notre besoin nous avons également modifié les templates et créé un formulaire...

Y-a-t-il d'autres concepts intéressants ?

Oui, Sylius s'appuie sur la plupart des concepts de Symfony ! Et il y en a de très intéressants et souvent utilisés avec Sylius. Nous allons nous pencher sur deux d'entres-eux uniquement.

La décoration :

Dans le cas, par exemple, où nous voudrions modifier la formule de calcul de prix d'une variation de produit définie dans Sylius\Component\Core\Calculator\ProductVariantPriceCalculator, les solutions qui s'offrent à nous sont les suivantes :

  • Étendre la classe et surcharger la fonction calculate(). C'est impossible : Sylius a défini la classe comme finale.
  • Copier/Coller la classe entière pour en faire un nouveau service. Dans ce cas, nous dupliquons du code et perdons les potentiels correctifs faits par Sylius.
  • Décorer la classe originale, c'est la meilleure solution !

Le "decorator pattern" permet de garder le comportement d'une fonction, mais d'ajouter notre propre code métier avant ou après l'exécution de la fonction décorée. Nous pouvons appliquer ce pattern sur beaucoup de services, comme par exemple les Factory.

Les plugins :

Sylius dispose d’un grand nombre de moyens de personnalisation et d’extensions. L'objectif d'un plugin est de compartimenter nos développements en "briques" simples et réutilisables.
Tout ce que l'on peut faire dans notre application (surcharge, création, ...), peut être fait dans un (des) plugin(s). Nous vous conseillons donc de les utiliser. Sylius dispose d'une bibliothèque de plugins que vous pouvez retrouver sur le site officiel.

Pour finir, qu'en est-il de la QA et des tests ?

L'analyse statique de code ainsi que les tests sont très fournis. Le cœur de l'application ainsi que les plugins proposés sont de très bonne qualité. Et les tests ont une très bonne couverture de code.

Voici un petit tour des vérifications faites par la CI (Travis sur le repository officiel) pour les PRs de Sylius :

  • validate-composer : validation du composer.json et composer.lock
  • validate-composer-security : vérification de la sécurité des composants installés via SensioLabs Security Checker
  • validate-doctrine-schema : validation des fichiers de mapping Doctrine
  • validate-twig : validation de la syntaxe des fichiers Twig
  • validate-yaml-files : validation de la syntaxe des fichiers Yaml
  • validate-yarn-packages : validation du package.json et yarn.lock
  • test-phpstan : analyse statique du code PHP avec PHPStan
  • test-phpspec : analyse du code PHP (définie par des spécifications) avec PHPSpec
  • test-phpunit : tests unitaires en PHP avec PHPUnit
  • test-behat: tests fonctionnels (via la simulation d'un navigateur) avec Behat

De ce fait, la CI est un peu longue, mais elle nous garantie une qualité de code et une non-régression sur nos projets 😊

 

 

 

 

 

 

 

GIF