L'origine du conflit
Lorsque l'on développe un site, on a tendance à se retrouver avec une multitude
de templates Twig avec probablement des blocs dupliqués ici et là.
En tant que développeur, on ressent vite le besoin de factoriser nos layouts,
découper nos templates, utiliser des macros avec des variables non typées et des
includes pour contenir au maximum notre base de code qui grossit au fur et à
mesure des évolutions ou autres features mises en place.
Puis vient le grand jour où il faut faire une refonte graphique et tu te retrouves à crouler sous les bugs parce que tu n'as pas eu le temps de factoriser des pans entiers de ton site et que la refonte va finalement te prendre un temps interminable.
C'est à ce moment-là, qu'en tant que développeur Backend, tu te réveilles de ce cauchemar pour finalement te rappeler que tu ne fais pas de frontend pour toutes ces raisons.
Rassure-toi, Twig Component arrive à la rescousse et tu vas pouvoir te réconcilier avec le frontend.
Un exemple vaut mieux qu'une longue explication
Imaginons que tu aies besoin de développer une fonctionnalité pour afficher une image personnalisée lorsque cette page est partagée, par exemple, sur un réseau social tel que LinkedIn.
Pour cela, nous allons utiliser "The Open Graph protocol" et plus particulièrement la balise meta "og:image".
<meta property="og:image" content="...url..."/>
En partant du principe que tu es développeur Backend, tu vas probablement
commencer par développer un service qui va te permettre de générer cette image.
Tu vas donc développer ton service, certainement installer quelques packages via
composer pour la génération de l'image, le stockage, etc.
Idéalement, ici la génération de l'image sera faite de manière asynchrone et une image par défaut sera rendu temporairement dans l'url de prévisualisation de l'article.
On va donc créer un Twig Component qui nous permettra de rendre cette balise.
Chose intéressante, nous allons même pouvoir nous permettre de pouvoir contrôler les paramètres à envoyer à notre service depuis les propriétés du component. Pour des raisons de simplicité, seul un titre est passé dans notre exemple, mais rien ne vous empêche d'ajouter des propriétés supplémentaires comme une image ou une couleur de fond, etc. Pour utiliser ce composant, il faut tout d'abord l'installer !
composer require symfony/ux-twig-component
Ensuite, passons au code : le composant nous permet d'exploiter les namespaces pour
organiser nos composants de manière logique.
Nous allons nommer notre composant OpenGraphImage
dans un namespace Meta
.
<?php
namespace App\Twig\Components\Meta;
use App\Service\OpenGraphImageManager;
use App\ValueObject\OpenGraph\Image;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent]
final class OpenGraphImage
{
public string $title = 'Développeur Symfony - Devops';
public function __construct(
private readonly OpenGraphImageManager $imageManager,
) {
}
public function getPreviewUrl(): string
{
$openGraphImage = $this->generateOpenGraphImage();
return $openGraphImage->getPreviewUrl();
}
private function generateOpenGraphImage(): Image
{
return $this->imageManager->generate($this->title);
}
}
L'avantage d'avoir une classe PHP pour définir les propriétés de notre composant
est que l'on peut en profiter pour utiliser l'injection de dépendance et ainsi
injecter notre service OpenGraphImageManager
directement dans notre composant.
La méthode getPreviewUrl
est accessible via twig par un this.previewUrl
.
Une fois le component créé, il est temps de créer le template Twig lui appartenant :
## templates/components/Meta/OpenGraphImage.html.twig
<meta property="og:image" content="{{ this.previewUrl }}"/>
Et enfin, nous appelons le component dans notre template avec notre propriété title
:
{{ component('Meta:OpenGraphImage', {title: 'Mon titre ou ma variable de titre'}) }}
Et "voilà", la meta est ajoutée sur notre site et le partage des pages du site aura à présent une image de prévisualisation basée sur le contenu de la page.
Pour des raisons de simplicité, le code du service OpenGraphImageManager
n'est
pas partagé sur cet article. Il fera l'objet d'un article dédié par la suite.
Voici un exemple pour cette page, par exemple.
Crédit photo: Robin Glauser