Formation « Créer des blocs avec Gutenberg »

Bloc dynamique via l’API REST et rendu en PHP

Lecture : 4 minutes • 0

Dans ce cours on va voir comment réaliser un bloc dynamique qui va afficher la liste toujours à jour des 3 derniers articles publiés. Cela nous permettra de voir comment récupérer des informations dans la base un peu à la manière de la WP Query, mais en JS.

On va maintenant monter le niveau d’un cran avec la création d’un bloc qui affiche les 3 derniers articles en date. On parle alors de blocs dynamiques.

On emploie ce terme car le contenu n’est pas écrit directement en dur dans le HTML, comme il est susceptible de changer avec le temps.

Le bloc que l’on va voir est en apparence tout simple :

Bloc dynamique Gutenberg

Lorsqu’on l’ajoute, on observe brièvement un écran de chargement le temps pour lui de récupérer les informations via l’API :

Chargement d'un bloc dynamique

On va prendre pour cet exemple le fichier src/15-dynamic dans le plugin qui accompagne cette formation et disponible sur Github.

Utiliser useSelect pour contacter l’API REST

On va commencer par charger une nouvelle fonction appelée useSelect que l’on va utiliser dans edit.js :

JSX
src/15-dynamic/edit.js

Cette fonction, issue de la librairie Data est d’ailleurs très utile pour aller récupérer des d’informations dans le coeur de WordPress. C’est une peu une sorte de WP Query pour JavaScript.

La fonction useSelect est un hook React, on en reparlera un peu plus tard dans la formation. Pour l’instant, tout ce que vous avez besoin de savoir, c’est qu’elle va permettre d’aller récupérer dynamiquement des informations dans la base de données.

Ici on indique dans les paramètres qu’on veut récupérer 3 articles dans le type de publication post. Pour en savoir plus, n’hésitez pas à consulter la documentation.

Gérer les résultats de manière asynchrone

Du coup désormais on se confronte à 3 cas de figure différents :

  1. L’API n’a encore rien renvoyé ;
  2. L’API a renvoyé aucun résultat ;
  3. L’API a renvoyé une liste d’articles.

Comme dans le cas d’une requête AJAX asynchrone, les résultats n’arrivent pas tout de suite, d’où l’utilité de mettre un écran de chargement même si c’est pour un bref instant (moins d’une seconde en général).

Et comme je vous ai dit c’est React qui gère le cycle de vie du composant. Du coup quand l’API aura répondu, React raffraichira l’affichage automatiquement en prenant en compte les nouvelles données. On n’aura rien besoin de faire de plus de notre côté donc !

Au niveau du code, au lieu d’utiliser les ternaires dans le return(), je vais cette fois faire 3 returns différents, en fonction des cas :

JSX
src/15-dynamic/edit.js

Je me permet cette approche car dans chaque cas le rendu sera complètement différent (et donc pas de répétition en vue).

Dans le cas où je n’ai pas encore eu de réponse de l’API, j’affiche le <Spinner /> qui est une roue animée pour faire patienter, et un texte « chargement » dans un bloc gris avec un petit peu de CSS.

Si je n’ai pas de résultat, j’affiche le même bloc gris avec la mention « Aucun article trouvé ». Et enfin si tout va bien j’affiche ma liste d’articles.

D’ailleurs j’en profite pour utiliser la fonction map() en JS, qui, comme on a déjà pu le voir, est une sorte de forEach qui affiche le résultat dans le template.

Enfin, vous remarquez que j’ai un code simple, qui ne nécessite pas de if/else ou de tests à rallonge : si une condition est vraie, le « return » renvoie le HTML et la fonction arrête à ce moment son exécution. Elle ne va donc pas plus loin.

Une fonction save minimaliste

Le plus gros lifting est la méthode save, qui ne renvoie plus rien du tout ! C’est logique puisque notre composant est dynamique : on ne peut donc pas enregistrer un HTML. Sinon côté front on n’aurait pas réellement les 3 derniers articles, mais les 3 articles les plus récents au moment où l’article a été publié.

JSX
src/15-dynamic/save.js

Du coup c’est en PHP que l’on va s’occuper d’afficher ce bloc !

La seule chose enregistrée par l’éditeur sera le commentaire HTML :

HTML

A l’avenir on pourra toujours y passer des attributs, notamment dans le cas où par exemple l’utilisateur peut sélectionner les articles qu’il souhaite afficher (et pas forcément les 3 derniers). Les identifiants de ces articles seraient donc stockés dans un attribut affiché dans ce commentaire.

Le rendu en PHP

On va donc aller faire un tour du côté de PHP. J’ai mis mon code dans capitainewp-gut-bases.php.

PHP
capitainewp-gut-bases.php

Lorsque l’on déclare nos blocs en PHP via la fonction register_block_type(), on peut ajouter un second paramètre, qui est un tableau, dans lequel on indique le nom de la fonction de callback.

Dans cette fonction, arbitrairement nommée capitainewp_dynamic_render() je n’ai plus qu’à récupérer mon contenu via la fonction get_posts() et générer le markup correspondant.

Information

Comprenez bien que côté front-end, il n’y a pas de React, d’appel API, ou quoi que ce soit d’asynchrone en JS, on fait un simple get_posts() en PHP qui récupère les articles voulus, à la manière d’une WP_Query.

Petite astuce : au lieu d’utiliser une variable $markup et de concatener du HTML, vous pouvez utiliser les fonctions ob (ob_start, ob_end_flush, ob_get_contents…) pour écrire le rendu.

Pourquoi donc ? Car ici vous ne pouvez pas directement afficher du HTML (en mode echo), il faut le retourner via un return().

Attention

Le code PHP pour récupérer des articles fait doublon avec ce que l’on a déjà fait en JS. Malheureusement on n’a pas d’autres alternatives que d’écrire 2 fois la même logique dans deux languages différents.

Un peu plus tard dans la formation, on verra d’autres blocs dynamiques un peu plus poussés. On en profitera pour améliorer la façon dont on affiche le markup en PHP, et on ajoutera des options pour nous permettre de choisir les articles à afficher.


Voilà ! Vous savez désormais faire un composant qui est capable de récupérer des données dynamiquement. Cela vous ouvrira pas mal de portes pour la suite !

Dans le prochain cours, on va voir comment on peut permettre d’insérer des blocs enfants à l’intérieur de notre bloc grâce au composant InnerBlocks.

0

Questions, réponses et commentaires

Laisser un commentaire