Ludovic Frank - Développeur indépendant

Changer les couleurs du thème de manière dynamique avec du CSS et Symfony ? C'est possible

ionicons-v5-k Ludovic Frank 25 mars 2024
562 lectures Niveau :

Coucou par ici 🙂,

Merci beaucoup d'avoir cliqué sur cet article 😁.

Sur le dernier article, je vous disais que ça sentait le printemps, mais là, ça s'est rafraîchi sévèrement 😅.
Ah oui, c'est vrai qu’on est toujours pas là pour parler météo... je suis désolé (enfin, je crois.).

Cette semaine, on va jouer avec du CSS et on va complètement casser Twig, vous allez voir c'est marrant, enfin, c'est un peu "pas très propre" comme méthode, mais bon, sur ce blog, je vous raconte tout.

Bref, cette semaine, on fait de l'art (c'est pour ça l'image de peinture pour cet article 😛)

Mais pourquoi ai-je besoin de faire ça ?

Ah bah, toujours un "side project", vous vous souvenez de l'application de réservation avec Symfony UX Turbo ?

En même temps, je vous ai tellement spam avec que vous ne devriez pas l'avoir oublié 😛.

Cette application a de base été désignée pour un seul restaurant, car n'ayons pas peur des mots, moi je ne voyais pas la valeur à l'époque. Je l'ai fait, car on m’a dit que ça pouvait résoudre un gros problème...

Et, je suis forcé de constater que bon, c'est le cas, cette application, qui de base était juste un autre "side project”, tourne à plein régime...

Et, d'après vous, un truc qui marche bien, qu'est ce qui se passe avec ? Bah on n’arrête pas de me demander "comment l'avoir" et ma réponse à ça toujours était :

Vous ne pouvez pas, elle n'est pas conçue pour être déployée à grande échelle, elle est conçue pour un seul restaurant.

Et c'était vrai... jusqu'à maintenant.

Le truc, c'est que je peux luter comme je veux, quand ta coiffeuse (Salut Alex), tes amis, tes contacts pros... te disent que cette app et trop bien et qu'il faut la rendre accessible a d'autres restaurateurs... bah, à force, ça rentre dans ton crâne, donc tu te mets au travail.

Et que pour chaque restaurant et "son espace de réservation", il est nécessaire de permettre de créer des thèmes de couleurs totalement différents par établissement.

Quel stack CSS dans le projet ?

Pour le coup, ce projet, c'est du Bootstrap pour le CSS (C'est le moment où je prends cher là ? 😛), avec la blinde de classe utilitaire, toute "transpilé" du SASS au CSS.

Et si on utilisait des thèmes (SASS) différents pour chaque restaurant ?

Cette solution ne me convient pas, en effet ça voudrait dire qu'à chaque fois que je redéploie, le CSS se “transpille” et qu'il devrait créer autant de fichiers CSS qu'il y a de restaurants. Ce n’est pas viable même si pour quelques restaurants, c’est possible, je ne sais pas combien de restaurants vont utiliser cette application, et surtout il faut qu'en un clic on puisse changer une couleur 😁.

Du CSS, du Twig, un contrôleur et une entité

Et voilà comment on va faire, on pourrait mettre du CSS directement dans le HTML, mais je n’aime pas cette idée, en effet, on n’exploite pas le cache du navigateur en faisant ça, donc on va faire un peu plus propre.

Le Twig

Ici, c'est la partie ou je me suis bien marré, en effet PHPStorm, ne comprenait pas ce que je faisais, car avec Twig on utilise "{{ }}" pour afficher des variables, le problème c'est qu'en CSS on utilise aussi des "{ }", donc PHPStorm ne savait pas trop quoi faire et ça donnait des situations un peu cocasses.

Sans plus attendre, voici la tête du code Twig :

Intéressant, même l'interpréteur Twig de Gitlab n'aime pas trop ce code 😅.

Pourquoi avoir défini les variables au début du fichier ?
Pour être très francs, c'était un travail assez désagréable, je devais aller regarder dans les classes de Bootstrap ou quelle classe définissait quelle couleur ? Et donc pour faciliter la visualisation de mon avancé, j'ai défini les variables en début de fichier.

Ici, vous voyez le fichier final, mais pendant le dev, je définissais les couleurs directement dans le fichier pour tout de suite détecter s'il reste des couleurs du test de base, d'ailleurs pour votre plus grand plaisir, voici le magnifique thème que j'ai désigné pendant la création de ce fichier css.twig (je ne pensais jamais dire ça un jour)

C'est beau, hein ? C'est absolument horrible, on est d'accord... mais au moins là je vois tout de suite si il y a des résidus du CSS d'origine dans les couleurs.

D'ailleurs, sur cette capture, on voit que je n'avais pas encore travaillé les "alerts" de Bootstrap.

Il faut noter ici, que j'utilise le filtre Twig "raw", c'est dangereux, car il y n'y a aucun filtre et donc, on pourrait injecter du CSS dans mon fichier Twig, pour palier ça, je ferais un filtre plus tard 🙂, avant la sortie de la release.

Également, vous pouvez voir que j'utilise des filtres Twig "custom" dans ce code, c'est tout simplement un code récupéré sur "StackOverflow” (les vrais savent) , qui recalcul le dégradé automatiquement :

Ce fichier il y a des choses qui ne vont pas, notamment le nom des fonctions, je verrai pour corriger ça plus tard.

Le contrôleur

Il faut que pour notre navigateur, ce fichier soit un fichier CSS et surtout un fichier "cacheable” par le navigateur, sinon, à chaque fois qu'un utilisateur revient dans le process de réservation de son établissement préféré, alors il devra recharger ce fichier, et ça, ce n’est pas dans mes valeurs, j'ai les poils qui s'hérissent rien qu'a l'idée de ne pas exploiter le cache du navigateur. 🤣

Voici donc notre contrôleur :

La partie intéressante ici, c'est la réponse, en effet, on va dire à Symfony que c'est un fichier CSS, et qu'il doit renvoyer dans les "header" que ce fichier est public (donc "cacheable” par les CDN), et que le navigateur peut le garder en cache.

Si vous êtes attentif, vous allez vous rendre compte que la mise en cache, c'est bien, mais, si le thème change, ça ne changera pas dans le navigateur des utilisateurs qui sont déjà venus (ou ceux qui passent par le même serveur du CDN).
Ne vous n’inquiétez pas, on voit ça juste après.

Comme vous le voyer dans le code on envoie à notre “.css.twig”, la variable "theme" qui est "$restaurant->getTheme();" et ce “getTheme()”, renvoie une entité Doctrine.

L'entité

Dernier point, mais non des moindres, l'entité, c'est elle qui va stocker notre thème en base, mais pas que ça...

Le problème du cache, c'est qu'il faut le rafraîchir quand le thème change, et pour ça, on a utilisé une version du fichier tout simplement pour changer l'URL du fichier quand on modifie le thème.

Voici mon entité :

Vous y retrouvez toutes les couleurs du thème ainsi que "$version", qui sera une simple "int” que l'on mettra à jour quand on change le thème.

Il y a des valeurs par défaut à chaque couleur ça permet d'avoir un thème "clef en main" et modifiable dès la création du restaurant en base, pour les petits curieux voici le thème de base :

Un petit fond bleu foncé et des boutons dorés, c'est pas mal non ?

Charger notre CSS

Pour ça, rien de plus simple, il faudra quand même que l'entité qui contient le thème soit accessible depuis votre" "Layout” de base (ou si vous le souhaitez vous pouvez créer un "block" et l’étendre à votre vue Twig fille.
Dans mon cas le projet étant un peu spécial (rappelez-vous, c'était le premier a utiliser Symfony UX Turbo), j'ai accès au restaurant depuis la "base_customer.html.twig".

Pensez bien à inclure votre version dans votre URL dans mon cas c'est le "v" qui prend comme valeur restaurant.thème.version.
Ce numéro de version sera mis à jour à chaque fois que le formulaire de modification sera enregistré.

Le formulaire pour éditer le thème

Alors pour être francs, je ne l'ai pas encore écrit, tout simplement, car ça va se résumer à une commande à savoir : "php bin/console make:form".
Ensuite, il suffira de l'intégré dans le "back office” pour les restaurants et le tour est joué.

D'ailleurs si vous avez envie de voir, un autre CRUD que j'ai fait en "back office”, ici la possibilité d'ajouter des messages sur l'écran d'accueil :

Oui, ça n'a rien à voir, mais bon il fallait que je vous montre un truc quand même 😁.

Conclusion

Nous voilà à la fin de cet article, j'espère que ça vous a plu et que ça vous sera utile dans vos propres projets.
On se retrouve prochainement dans un autre article 🙂 même si je ne sais pas encore de quoi on parlera (et en écrivant ça, je viens d'avoir une idée...).

Passez une très bonne semaine 🙂.