Changer la suite de fixtures par défaut sous Sylius

Par Jibé B. le 1 avril 2020
Lecture 5 minutes

Lorsqu’on développe un site e-commerce sur la solution Sylius, les développeurs peuvent être amenés à utiliser les fixtures pour initialiser rapidement une boutique. Ces dernières permettent, via un fichier de configuration, de customiser entièrement une boutique, son nom, ses administrateurs, les taxes à utiliser, de créer les produits et catégories, etc. Il est même possible de créer des chargeurs de fixtures custom pour ses propres entités.

Voyons comment créer notre propre suite de fixtures et indiquer à Sylius qu’il doit l’utiliser par défaut.

Pour utiliser les fixtures, selon la documentation officielle, plusieurs choix : créer sa propre suite ou bien altérer la suite par défaut. Ces méthodes ont leurs avantages et inconvénients.

Création de sa propre suite de fixtures

Dans le fichier config/packages/sylius_fixtures.yaml, créer sa suite de fixtures ainsi :

 

sylius_fixtures:
    suites:
        my_awesome_project:
            listeners:
                orm_purger: ~
                logger: ~
            fixtures:
                currency:
                    options:
                        currencies: ['EUR']
                channel:
                    options:
                        custom:
                            main_web_store: # creating new channel
                                name: "My awesome store"
                                code: "AWESOME_WEBSTORE"
                                locales: "%locales%"
                                default_locale: "%locale%"
                                currencies:
                                    - "EUR"
                                enabled: true
                                hostname: "%env(resolve:SYLIUS_FIXTURES_HOSTNAME)%"
                                shop_billing_data: 
                                    company: My Awesome Company
                                    country_code: FR
                                    street: '55 Rue du Faubourg Saint-Honoré'
                                    city: 'Paris'
                                    postcode: '75008'
                 # ... others fixtures<

 

sylius_fixtures:
    suites:
        my_awesome_project:
            listeners:
                orm_purger: ~
                logger: ~
            fixtures:
                currency:
                    options:
                        currencies: ['EUR']
                channel:
                    options:
                        custom:
                            main_web_store: # creating new channel
                                name: "My awesome store"
                                code: "AWESOME_WEBSTORE"
                                locales: "%locales%"
                                default_locale: "%locale%"
                                currencies:
                                    - "EUR"
                                enabled: true
                                hostname: "%env(resolve:SYLIUS_FIXTURES_HOSTNAME)%"
                                shop_billing_data: 
                                    company: My Awesome Company
                                    country_code: FR
                                    street: '55 Rue du Faubourg Saint-Honoré'
                                    city: 'Paris'
                                    postcode: '75008'
                 # ... others fixtures

Puis, pour l’utiliser, il faut passer le nom de la suite (ici : my_awesome_project) en paramètre des commandes `sylius:install` et/ou `sylius:fixtures:load` ainsi :


$ php bin/console sylius:install --fixture-suite=my_awesome_project
$ php bin/console sylius:fixtures:load my_awesome_project

L’avantage de cette solution : la suite contiendra uniquement les fixtures que l’on a définies.
S’il n’y pas besoin de fixtures de taxons ou de produits, il suffit de ne pas en mettre.

Par contre, cela nécessite de connaître le nom de la suite et d’ajouter l’argument lorsque les commandes ci-dessus sont jouées. Tout doit être bien précisé dans une documentation pour que chaque développeur intervenant sur le projet utilise la bonne suite de fixtures.

Altérer la suite par défaut

La suite de fixtures par défaut dans Sylius se nomme … `default`.
C’est ce nom qui est utilisé quand les arguments des commandes indiquées précédemment ne sont pas renseignés.

Pour altérer cette suite, il faut la renseigner également dans le fichier config/packages/sylius_fixtures.yaml :



sylius_fixtures:
    suites:
        my_awesome_project:
            # ... 
        default:
            fixtures:
                currency:
                    options:
                        currencies: ['EUR']
                channel:
                    options:
                        custom:
                            main_web_store: # creating new channel
                                name: "My awesome store"
                                code: "AWESOME_WEBSTORE"
                                locales: "%locales%"
                                default_locale: "%locale%"
                                currencies:
                                    - "EUR"
                                enabled: true
                                # ...

Lorsque cette suite de fixtures sera jouée, la configuration personnalisée sera « fusionnée » avec la configuration de la suite `default`.

L’avantage de modifier cette suite : la possibilité de redéfinir une petite partie des fixtures et d’utiliser toujours ces fixtures lors du sylius:install ou lors du sylius:fixtures:load.

Néanmoins, impossible d’en retirer. Par exemple, si la suite en l’état, avec la configuration ci-dessus, est jouée, 2 channels se trouveront en base de données : celui qui est déjà défini dans la suite default et celui qu’on rajoute.

Par ailleurs, il est impossible de désactiver les fixtures de produits, juste les altérer.

Logiquement, en créant sa propre suite de fixtures, on veut qu’elle qui soit utilisée par défaut.
Voyons comment procéder.

Notre propre suite par défaut

En inspectant le code du SyliusFixturesBundle, il est une interface nommée SuiteRegistryInterface.

Cette interface et son implémentation sont chargées de récupérer la configuration d’une suite de fixtures.

Pour appliquer notre remplacement, il faut donc décorer l’implémentation de cette interface.

Pour cela, une classe AwesomeProjectSuiteRegistryDecorator.php doit être créée. Elle doit ensuite décorer la SuiteRegistry.

<?php

declare(strict_types=1);

namespace App\Fixtures\Suite;

use Sylius\Bundle\FixturesBundle\Suite\SuiteInterface;
use Sylius\Bundle\FixturesBundle\Suite\SuiteRegistryInterface;

final class AwesomeProjectSuiteRegistryDecorator implements SuiteRegistryInterface
{
    /**
     * @var SuiteRegistryInterface
     */
    private $decorated;

    public function __construct(SuiteRegistryInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function getSuite(string $name): SuiteInterface
    {
        return $this->decorated->getSuite($name);
    }

    public function getSuites(): array
    {
        return $this->decorated->getSuites();
    }
}

Puis, enregistrer le décorateur dans le fichier config/services.yaml :

# config/services.yaml
services:
    # Others services...
    App\Fixtures\Suite\AwesomeProjectSuiteRegistryDecorator:
        decorates: 'sylius_fixtures.suite_registry'
        arguments:
            $decorated: '@App\Fixtures\Suite\AwesomeProjectSuiteRegistryDecorator.inner'

Pour en savoir plus sur le décorateur et son utilisation, rendez vous sur la documentation de Symfony.

On peut maintenant implémenter notre logique dans le décorateur :

<?php
// ...
final class AwesomeProjectSuiteRegistryDecorator implements SuiteRegistryInterface
{
    private const PROJECT_SUITE_NAME = 'my_awesome_project';
    private const DEFAULT_SUITE_NAME = 'default';
    
    // ...
    
    public function getSuite(string $name): SuiteInterface
    {
        if (self::DEFAULT_SUITE_NAME === $name) {
            // We don't use anymore default fixture suite.
            return $this->decorated->getSuite(self::PROJECT_SUITE_NAME);
        }

        return $this->decorated->getSuite($name);
    }

Ici, la demande de récupération d’une suite est interceptée.

En demandant le nom `default`, on renvoie la suite de notre projet, my_awesome_project.

Notre suite est maintenant la suite par défaut.

Lancez un sylius:install ou sylius:fixtures:load sans argument spécifique et votre boutique sera peuplée uniquement de vos propres données.

Il serait par la suite intéressant de proposer une Pull Request à Sylius pour pouvoir définir le nom par de la suite par défaut dans un paramètre.

GIF