[ Article ]
DevOps Experience Conf' 2026 : 6 enseignements clés sur la maîtrise des infrastructures

Marie-Pierre Goetz

Baptiste Leulliette
Publié le 11 avril 2024
Dans le contexte de refonte d’un site web avec Strapi, nous avons été confrontés à la problématique de la création de relations multi-contenus avec ce CMS. En effet, celui-ci n’autorise que des relations vers un unique type de contenu.
En opposition avec d’autres CMS, Strapi ne permet pas de relier plusieurs types de contenus pour une seule propriété d’un content-type :

Fig 1. Comparaison avec le marché

Fig 2. Création d’une relation mono contenu dans Strapi
Comparons rapidement les possibilités des deux CMS :
| Autres CMS | Strapi | |
| Champ requis | X | – |
| Gestion du min/max | X | – |
| Relation multi-contenu | X | – |
| Relation one-to-one | X | X |
| Relation one-to-many | X | X |
| Relation many-to-one | ~ (à créer dans le CT cible) | X |
| Relation many-to-many | ~ (à créer dans le CT cible) | X |
On se rend compte ici qu’il manque 3 features critiques qui sont nécessaires pour la refonte.
Pour pallier ces manques cruciaux, nous avons attaqué le développement d’un plugin Strapi de relation multi content-type, que je nommerai MRCT par la suite (Multi Relation Content Type).
Nous sommes donc partis sur un plugin qui permet d’ajouter un champ custom dans les content types ce qui nous donnera la possibilité, à terme de configurer, par champ, les content types associés pour le champ du content-type.
La première étape du développement a été le proof-of-concept (Preuve de conception), le CMS étant derrière un backend développé avec GraphQL, nous avons mis en place un client Strapi qui permet la récupération des différents contenus. L’approche était de stocker dans un format JSON du contenu, les différents contenus associés, en exploitant leur UID et leur ID et les exploiter dans le client du BFF.

À noter qu’ici, nous avons volontairement mis le type « richText” afin de profiter d’une table qui accepte un gros payload JSON dans le but de ne pas être limité dans la sauvegarde de celui-ci.
S’est ensuivi le développement de la partie backoffice qui permet la contribution de ce champ de relation. Pour cela, nous nous sommes appuyés sur le design system que Strapi nous met à disposition.
Une fois la définition du champ custom établie, passons à la configuration de celui-ci. On souhaite avoir la possibilité de configurer tous les content-types pour lesquels le champ aura une relation, ainsi que les features de bases que Strapi ne propose pas : champ requis (Oui/non), minimum, maximum.
À l’initialisation du backoffice, le plugin appelle une première route d’API custom “listContentTypes” qui permet de récupérer l’intégralité des content-types disponibles pour une relation.
On y ajoute la configuration de base, nous offrant une bien meilleure latitude sur l’exploitation des champs de relation.


Maintenant que la configuration du custom field est terminée, attaquons nous à l’affichage et la contribution du champ custom. Après quelques itérations de développements sur la partie Backoffice, on arrive à quelque chose qui s’intègre aisément dans le masque de saisie natif de Strapi :

On retrouve sur l’illustration présentée ci-dessus plusieurs choses :
Il a ensuite fallu développer des endpoints customs qui permettent de récupérer les différentes données.

Pour le détail de ces deux endpoints d’API :
L’interface du plugin custom stocke un JSON représente la relation vers ces différents contenus.

À savoir que la présence du champ “MRCT”: true permet d’identifier la présence d’un champ de relation custom dans la réponse d’API de strapi et nous servira dans la seconde partie de cet article.
Nous avons implémenté un client custom Strapi qui vient automatiquement hydrater les contenus dans la mesure du possible. Celui-ci passe par différentes étapes afin d’identifier et d’hydrater les contenus avant de retourner le contenu finalisé :
Nous pouvons distinguer plusieurs choses dans cette fonction :
Après tout ce développement, on arrive à un contenu qui est correctement hydraté de ses relations.
Ce plugin a été développé sur deux sprints de deux semaines et permet aujourd’hui d’exploiter des composants qui ont plusieurs relations possibles afin d’avoir une vraie dynamique dans la contribution pour le client.
Gardons à l’esprit qu’il reste une amélioration majeure à apporter, qui consiste à la création de hooks de lifecycle autour des contenus qui portent un champ custom MRCT. De cette façon, Strapi portera l’intégralité de la charge de l’hydratation des contenus dans l’API avant de servir la donnée afin qu’elle soit proprement servie dans celle-ci.
Le plugin a été publié sur NPMJS pour le moment, il est en cours de publication sur la marketplace de Strapi, en espérant qu’il soit réintégré par défaut dans les futures versions, pour combler un besoin fonctionnel qui semble indispensable à un CMS. Vous pouvez y contribuer sur github.
[ Article ]

Marie-Pierre Goetz