Tout savoir sur WordPress

Le Champ Relationnel d’Advanced Custom Fields : 2 exemples concrets

ACF propose un champ relationnel. A première vue on en comprend mal l’utilité, mais c’est en réalité l’un des champs les plus puissants du plugin !  Il peut vous servir lorsque vous avez par exemple besoin de sélectionner des articles similaires, mais pas que ! Dans ce tutoriel je vous explique tout avec des exemples concrets.

Cet article fait partie d’une suite de tutoriels autour d’ACF, découvrez également :

Pourquoi un champ relationnel ?

Le champ relationnel permet  de sélectionner un ou des articles  à afficher sur une page.

WordPress vous permet d’afficher du contenu : pages, articles, custom types. Mais les méthodes de rangement sont assez limitées : généralement on trie par ordre chronologie ou inverse. Par exemple on affiche la liste des derniers produits sur la page d’accueil. Mais comment faire lorsque votre client souhaite choisir les produits à afficher, car il souhaite mettre en avant ses meilleurs produits, et pas ses plus récents ? Le champ relationnel répond justement à cette problématique !

Dans quel cas de figure utiliser le champ relation d’ACF ?

Globalement dans tous les cas où vous souhaitez que l’utilisateur mette en avant le contenu de son choix. Voici quelques exemples où ce champ se révèle très utile :

  • Blog : A la fin d’un article, vous souhaitez afficher une liste d’articles susceptibles d’intéresser le lecteur
  • E-commerce : sur une page produit, afficher des produits liés / complémentaires pour augmenter le panier moyen
  • Immobilier : sur la page d’accueil, donner le contrôle à votre client pour qu’il affiche ses 4 biens phares, au lieu d’afficher les 4 plus récents
  • Application : permettre de lier entre eux des articles de différents types de publication. Par exemple lier des entreprises et des salariés facilement (le champ permettra dans la fiche entreprise de choisir quels sont ses salariés)
  • Et bien plus… On peut imaginer des centaines de cas où le champ peut être utile

De manière générale il servira à tout cas de figure où le rédacteur souhaite choisir ce qu’il affiche plutôt que de laisser WordPress l’afficher en ordre chronologique.

Comment fonctionne-t’il ?

En ajoutant un champ relationnel dans un groupe de champ ACF, vous obtiendrez ce widget :

champ-acf-relationnel

A gauche : la liste des articles disponibles.
A droite : la liste du ou des articles sélectionnés

On retrouve également un moteur de recherche en haut à gauche pour trouver rapidement un article et des filtres permettant de trouver un article dans une taxonomie ou un type de publication en particulier.

Il vous suffit de cliquer sur un article de la colonne de gauche pour qu’il s’insère à droite. Vous pouvez également choisir l’ordre d’apparition par un simple glisser-déposer.

Des options pour contraindre les choix

Vous pourrez choisir le nombre maximum d’éléments que votre client pourra choisir (par exemple 3 produits à afficher maximum) et également limiter les choix à certaines catégories / taxonomies (par exemple seulement les produits de la catégorie promotion) et types de publications (par exemple que les article du custom type portfolio).

Exemple 1 : des articles mis en avant en fin d’article

Commençons simplement : on souhaite ici pouvoir afficher une sélection d’articles similaires à la fin d’un article. Pour cela on va aller créer notre groupe de champs.

Créer le groupe de champs ACF

Rendez-vous désormais dans le menu ACF > Ajouter.

Indiquez comme nom du groupe Articles par exemple, et créez un champ relationnel appelé Articles similaires.

relationnel-article

Notez bien pour plus tard le nom du champ articles_similaires, que l’on appelle aussi le slug (nom informatique sans caractères spéciaux).

Pour faire bien on va limiter le choix aux articles seulement. De cette manière on évite d’avoir dans la liste des pages ou autres types de publication. Je désactive également le filtre Type de publication.

options-relationnel

Si on laisse le type de publication, il y aura un select au dessus du champ qui proposera une seule entrée : les articles.

type-filtre

C’est intéressant de conserver cette option dans le cas où vous faites un relationnel qui permet de piocher sur plusieurs types de publication (mais on ne rencontrera que très rarement le cas).

Côté options, on peut aussi faire afficher l’image à la Une (c’est plus cool) et éventuellement limiter le nombre de résultats :

relationnel-options

Voilà ! Notre groupe est prêt, vous noterez que par défaut les nouveaux groupes de champs sont automatiquement assignés au type de publication Articles, c’est à dire que l’on verra bien notre champ quand on créera un article. Vous n’avez donc pour le coup rien besoin de changer ici.

assigner-groupe-article-defaut

Créer des articles

On va maintenant rédiger quelques articles histoire d’avoir de la matière, puis assigner des articles similaires à l’un d’entre eux :

champ-acf-relationnel

Dans mon article 1, j’ai assigné Article 2, 3 et 4 en temps qu’articles similaires. Publiez votre article !

Le code dans le template

Si vous lancez maintenant l’aperçu, il ne se passe rien. Bien entendu, comme je l’expliquais dans le premier tutoriel ACF pour débutants, il va falloir retoucher le code PHP du template pour faire afficher la valeur du champ sur votre site !

Et pour cela on va s’aider de la documentation officielle ACF à propos des champs relationnels.

Les articles sont rendus via la page single.php de votre thème. Là encore, un passage par le template hierarchy vous permettra de savoir quel fichier est appelé selon le cas. Pour trouver le bon endroit dans le template, référez-vous à la fin du tutoriel ACF débutant.

<?php
	$posts = get_field('articles_similaires');

	if($posts): 
?>
<h3>Articles Similaires</h3>
<ul>
	<?php 
		foreach( $posts as $post): // ne pas changer $post IMPORTANT
			setup_postdata($post); 
	?>

	<li>
		<?php the_post_thumbnail(); ?>
		<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</li>

	<?php endforeach; ?>
</ul>

<?php 
		wp_reset_postdata(); // IMPORTANT - réinitialiser l'objet $post sur la requête principale
	endif; 
?>

A l’intérieur de la boucle foreach, le setup_postdata permet le même fonctionnement que la boucle WordPress. Il ne vous reste plus qu’à afficher les informations avec les fonctions habituelles the_title, the_permalink, et éventullement the_field.

En résumé, le temps de la boucle foreach, on n’est plus dans les données de la page en cours (article 1), mais on a accès aux données de l’article similaire (article 2, puis 3, puis 4), comme si on était dans sa propre page. Donc si vous avez crée des champs ACF pour vos articles, vous pouvez les appeler de manière classique avec <?php the_field(); ?>

C’est pour cela que l’on fait appel à wp_reset_postdata() à la fin de la boucle, afin de revenir sur les données de la page en cours (notre article 1) . Génial non ?

Bon, ça nécessite un peu de CSS pour être joli mais voilà à quoi ça peut ressembler :

affichage-champ-relationnel-template

Voilà pour l’exemple le plus commun. On va maintenant aller un peu loin, et vous serez des experts !

Exemple 2 : entreprises et projets

Imaginons cette fois un site où sont listées des entreprises, et des projets.

  • Chaque projet peut être mené par plusieurs entreprises différentes (imaginons des projets du bâtiment qui impliquent des entreprises de maçonnerie, peinture, électricité…)
  • Chaque entreprise peut avoir participé à plusieurs projets

Dans les fiches projets, on veut pouvoir assigner les entreprises qui ont participé. Plus tard, on va vouloir également que dans une fiche entreprise, on ai la liste des projets sur lesquels elle a travaillé.

Schématisé ça donne ceci :

projet-entreprise

Prérequis : créer les types de publication Entreprises et Projets

Dans WordPress par défaut on a seulement Articles et Pages. On va donc créer un type de publication Projets et un Entreprise.

Vous pouvez récupérer le code de base d’un custom post type sur GenerateWP ou récupérer le mien, simplifié :

function geekpress_create_post_type() {

	$labels = array(
		'name' => 'Entreprises',
		'all_items' => 'Entreprises',  // affiché dans le sous menu
		'singular_name' => 'Entreprise',
		'add_new_item' => 'Ajouter une entreprise',
		'edit_item' => 'Modifier',
		'menu_name' => 'Entreprises'
	);

	$args = array(
		'labels' => $labels,
		'public' => true,
		'has_archive' => true,
		'supports' => array('title', 'editor','thumbnail'),
		'menu_position' => 5,
		'menu_icon' => 'dashicons-store',
	);

	register_post_type('entreprises',$args);


	$labels = array(
		'name' => 'Projets',
		'all_items' => 'Projets',  // affiché dans le sous menu
		'singular_name' => 'Projet',
		'add_new_item' => 'Ajouter un projet',
		'edit_item' => 'Modifier',
		'menu_name' => 'Projets'
	);

	$args = array(
		'labels' => $labels,
		'public' => true,
		'has_archive' => true,
		'supports' => array('title', 'editor','thumbnail'),
		'menu_position' => 5,
		'menu_icon' => 'dashicons-star-empty',
	);

	register_post_type('projets',$args);

}
add_action( 'init', 'geekpress_create_post_type' );

Ce code est à placer dans le fichier functions.php de votre thème actif. Pensez à aller ensuite dans Réglages > Permaliens et enregistrez pour mettre à jour la structure des permaliens et prendre en compte les urls

Créer le groupe de champs ACF

Rendez-vous désormais dans le menu ACF > Ajouter.

On va créer un groupe qui s’appelle Projets, qui contient un champ relationnel appelé Entreprises.

groupe-de-champs

Dans les options du champ ACF, on va limiter la sélection aux projets seulement :

filtre-cpt

Enfin, on va assigner ce groupe au type de publication Projets : notre champ relationnel n’apparaitra donc que lors de l’édition de projets dans l’administration de WordPress.

assigner

Notez qu’on aurait très bien pu faire l’inverse : avoir un relationnel dans entreprises qui pointe vers projets.

Créer des entreprises et des projets

Maintenant, on va créer quelques entreprises et quelques projets. Lors de l’édition de ces derniers, vous devriez voir apparaitre votre champ relationnel ACF :

champ-relationnel-acf

Créez plusieurs entreprises et au moins un projet. Assignez ensuite des entreprises à votre projet.

Le code dans le template

Le code sera identique que dans le premier exemple, excepté le le nom du champ qui est cette fois-ci entreprises.  Et contrairement à précédemment, nous allons placer ce code cette fois-ci dans single-{nom-du-CPT}.php : single-projets.php. Ce template n’existe pas par défaut mais vous pouvez dupliquer single.php.

<?php
	$posts = get_field('entreprises');

	if($posts): 
?>
<h3>Contributeurs</h3>
<ul>
	<?php 
		foreach( $posts as $post): // ne pas changer $post IMPORTANT
			setup_postdata($post); 
	?>

	<li>
		<?php the_post_thumbnail(); ?>
		<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</li>

	<?php endforeach; ?>
</ul>

<?php 
		wp_reset_postdata(); // IMPORTANT - réinitialiser l'objet $post sur la requête principale
	endif; 
?>

Et voici le résultat quand on affiche le projet :

projets

Dans l’autre sens : lister les projets auquel une entreprise a participé

Et si on veut le contraire :  afficher les projets dans la fiche entreprise ?

Votre insatiable soif de connaissances va vous pousser à me poser désormais la question suivante : Et si maintenant je souhaite, dans la fiche de l’entreprise, afficher les projets dont elle a participé ? 

Le problème actuel est que c’est la fiche projet qui sait quelles entreprises ont participé. La fiche entreprise n’a aucune information directement enregistrée sur les projets. Et on ne va pas faire un autre champ relationnel, car les données ne seraient pas synchronisées.

Mais il existe une solution : faire une requête personnalisée WP_Query qui va aller trouver les mentions de l’entreprise dans les fiches projets. On appelle cela aussi une reverse Query (= requête inversée).

La solution est donnée par la documentation ACF : Reverse Query.

On va cette fois dupliquer single.php pour créer single-entreprises.php, et utiliser ce code :

<?php 
	$projects = get_posts(array(
		'post_type' => 'projets',
		'meta_query' => array(
			array(
				'key' => 'entreprises', // nom du champ
				'value' => '"' . get_the_ID() . '"', // bien conserver les apostrophes
				'compare' => 'LIKE'
			)
		)
	));

	if($projects):
?>
	<h3>Projets auxquels on a participé : </h3>
	<ul>

	<?php	foreach($projects as $project): ?>
		<li>
			<a href="<?php echo get_permalink($project->ID); ?>" >
				<?php echo get_the_title($project->ID); ?>		
			</a>
		</li>

	<?php
		endforeach;
	endif; 
?>

Sur la ligne 3 : il faut indiquer le nom de l’autre Custom Post Type : projets. Et sur la ligne 6, le nom du champ relationnel dans projets : entreprises.

La requête personnalisée va chercher des projets (paramètre post_type) et va regarder, dans le champ ACF entreprises (notre relationnel donc) si cette entreprise y est listée.

Ce code va donc afficher la liste de tous les projets dans lesquels cette entreprise est attachée ! Cool non ? Voici le résultat :

entreprise

Et voilà ! Il suffit donc pour chaque projet, de rattacher les entreprises concernées, et vous aurez automatiquement, pour chaque entreprise, la liste des projets. On a bien un fonctionnement dans les deux sens.

Comme je le disais plus haut, on aurait pu totalement faire l’inverse : mettre un relationnel dans l’entreprise pour lier les projets. Et ça fonctionnerait tout aussi bien !

Conclusion

Le champ relationnel n’a plus de secrets pour vous ! Je l’utilise quasiment dans tous mes projets pour donner plus de contrôle à mon client. De plus il fait partie des champs de base d’ACF, ce n’est donc pas un add-on payant !

Et vous, vous l’utilisez déjà ? Dans quels cas ?

Cet article a été mis à jour il y a 206 jours

Article écrit par Maxime BJ

Développeur, bloggeur et formateur Web spécialisé WordPress. 31 ans. Grenoblois. Co-fondateur de WPChef, l’organisme de formation WordPress.

Organisateur de WPInAlps, le meetup WordPress Grenoblois. Vous pouvez me rencontrer lors d’événements tels que WordCamp Paris et Europe. Traducteur Français de l’extension Advanced Custom Fields. Également développeur d’applications web avec MeteorJs. Je m’occupe un site pour apprendre l’informatique aux débutants gratuitement.

J’aime les jeux vidéo, la rando, la bouffe bien grasse et les voyages.

11 Commentaires

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

  1. Bonjour Maxime,
    Merci et bravo pour cette brillante démonstration. Je suis tombé sur l’équivalent de cet article en anglais et pensais résoudre ma question en lisant votre version.

    J’ai un custom post type nommé « formations ».

    Sur ces posts j’ai une set de champs ACF dont « formation_lieu » qui est un relationnel vers un autre custom post type : une liste de 36000 villes.
    Tout est parfaitement stocké dans l’admin mais je n’arrive pas à extraire le nom du champ avec mon query post !!!


    $args_formation = array(
    ‘post_type’ => ‘formations ‘,
    ‘post_status’ => ‘publish,future’,
    ‘showposts’ => 6,
    ‘orderby’ => ‘date’,
    ‘order’ => ‘ASC’
    );

    J’ai essayé votre script mais il ne me permet pas de choisir mon CPT « formations », pas d’erreur mais rien ne sort de la boucle …

    D’avance un grand merci si vous avez une idée, je n’ai pas l’impression de cherche à faire un truc délirant…
    Merci,
    jd

  2. Bonjour Maxime,

    De passage sur ton blog, j’en profite pour informer de la sortie d’un add-on qui se marie parfaitement avec les champs de type Relation évoqués ici : https://wordpress.org/plugins/quick-and-easy-post-creation-for-acf-relationship-fields/

    Le but de ce plugin est de simplifier le workflow lorsqu’on souhaite lier à ce type de champ un contenu qui n’existe pas encore. En temps normal, la procédure est assez rébarbative, puisqu’il faut tout d’abord enregistrer le contenu sur lequel on travaille, avant d’aller créer le nouveau contenu, puis revenir sur le premier contenu pour enfin pouvoir le lier au nouveau contenu nouvellement créé.

    J’espère que ce plugin fera le bonheur de ceux qui passent par ici.

  3. Bonjour,

    Je veux préciser 2 choses mais qui vont un peu plus loin que l’article.

    Premièrement je crois qu’il n’existe pas de solution proposée par ACF pour avoir un champ relationnel « double » dans l’administration. Comme tu le dis si bien dans l’article, le champ relationnel est affiché dans l’édition des projets. Mais ça oblige le client à aller dans l’édition du projet pour modifier les assignation. Et j’ai trouvé dommage de ne pas pouvoir rajouter de base le champ relationnel aux 2 endroits (cpt projets et cpt clients) et qu’ils se synchronise tout seul.

    Deuxième difficulté : l’utilisation de ce champ relationnel dans les scripts (en plugin ou fonction). Il y a déjà un manque énorme de documentation sur ce champ. Et il y a quelques bugs pour ajouter une relation.

    Si tu as déjà mis les.mains dedans ça m’intéresse de savoir ce que tu en as pensé. Je ne cherche pas de solutions, je les avais trouvé à l’époque.

    • Je trouve que pour ACF c’est plutôt pas mal documenté au niveau des champs et des fonctions.
      Après le code ne l’est pas en effet, donc si tu veux créer toi même ton champ pour faire ce que tu dis (ce qui serait super) je pense que ce serait pas forcément très évident.

      Je n’ai jamais eu besoin de faire ce que tu proposes mais je pense que j’entrevois comment faire. Faudrait que je teste un jour !

    • Désolé je ne peux pas modifier mon commentaire. Mon premier était sur mobile c’était donc difficile d’inclure des ressources. Tu peux supprimer ou fusionner ces commentaires si tu le souhaites.

      Dans tous les cas ACF est d’une grande aide c’est certain ! Voilà quand même ce que ACF donne comme exemple de champ relationnel « bidirectionnel » : https://www.advancedcustomfields.com/resources/bidirectional-relationships/

      Et voici la doc sur update_field : https://www.advancedcustomfields.com/resources/update_field/

      Je ne peux par contre plus te dire sur quoi je m’étais cassé les dents exactement car ça va dater d’un an et je n’ai pas le code sous la main. Quoi qu’il en soit ça aurait été bien plus difficile sans ACF !

    • Oh super tu vois pour le bidirectional je ne connaissais pas ! C’est top cool :) ça va pouvoir servir à beaucoup je pense, j’en ferais surement un tuto FR ! Merci ;)

  4. Hello Maxime,
    Super article sur ce champs bien qu’utile ! Je rajouterais néanmoins qu’il est cependant possible de faire mumuse avec ce dernier en BO pour ne filtrer que les contenu qui nous intéresse.

    Quand de base l’ UI nous propose un filtrage par type de contenu et par taxinomies, sans pouvoir les mêler et en avoir plusieurs, je pense que dans ce contexte on arrive vite à la limitation imposée. C’est pourquoi je voulais mettre en avant le fait qu’il est possible de se hooker sur ces champs relationship pour ajouter des arguments de type WP_Query :
    – faire de multiples tax_query
    – faire de multiples meta_query
    – requêter plusieurs type de contenu avec des tax_query, date_query, meta_query bien spécifiques
    – limiter conditionnellement le nombres d’éléments à afficher
    – ajouter les hide empty pour les taxinomies
    – faire tout ce qui vous passe par la tête quoi ^^

    Les hooks sont les suivants :
    – acf/fields/relationship/result
    – acf/fields/relationship/result/name={$field_name}
    – acf/fields/relationship/result/key={$field_key}
    La documentation se trouve ici : https://www.advancedcustomfields.com/resources/acf-fields-relationship-result/

    Un sample de code, pour faciliter la compréhension : https://gist.github.com/MaximeCulea/afdd68e67b7ff2f8efb4d51e636c689c

  5. Super artcile,
    j’utilise ACF pro depuis un moment et je viens de découvrir les relationship qui m’a permis de filtrer une relation (choix_realisation : choix des résidences vendus) sur une page d’accueil, en fonction d’un input radio (etat_projet) que j’ai mis sur une post_type residence

    function my_relationship_query( $args, $field, $post_id ) {
    $meta_query = array(
    ‘key’ => ‘etat_projet’,
    ‘value’ => ‘vendu’,
    ‘compare’ => ‘IN’,
    );
    $args = array(
    ‘post_type’ => ‘residences’,
    ‘meta_query’ => $meta_query,
    );
    return $args;

    }
    add_filter(‘acf/fields/relationship/query/name=choix_realisation’, ‘my_relationship_query’, 10, 3);

1cb26a3261e3a0728911f2f57164ef3bMMMMMMMMMMMMMMMMMMMMMMMMM