Après avoir modélisé vos types de publications avec les Custom Post Types et organisé vos contenus grâce aux Custom Taxonomies, la troisième étape indispensable pour concevoir un site WordPress sur-mesure consiste à enrichir vos fiches avec des Custom Fields (champs personnalisés ou métadonnées).
Par défaut, l’éditeur de WordPress ne propose qu’un nombre restreint de données pour une publication : un titre, un bloc de contenu principal, un extrait et une image mise en avant. Dès que vous développez une application métier comme notre catalogue de streaming Netfloux, ces champs ne suffisent plus : comment renseigner la durée précise d’un film, son réalisateur, sa note critique ou lier directement le fichier vidéo source à visionner ? C’est précisément le rôle des champs personnalisés.
Sommaire
- Le fonctionnement natif : la table wp_postmeta
- Récupérer une métadonnée en PHP : get_post_meta()
- Pourquoi utiliser l’extension Advanced Custom Fields (ACF) ?
- Cas pratique Netfloux : le groupe de champs « Films & Séries »
- Afficher les champs ACF dans son thème : get_field() et the_field()
- Filtrer et trier avec WP_Query et meta_query
- Bonne pratique pro : versionner ses champs ACF (Local JSON et PHP)
- Questions fréquentes
Le fonctionnement natif : la table wp_postmeta
WordPress intègre nativement un système puissant de métadonnées pour enrichir les publications. Toutes ces informations sont enregistrées dans la table SQL wp_postmeta sous forme de paires clé / valeur associées à l’identifiant unique de la publication (post_id) :
| Colonne | Type | Description | Exemple (Netfloux) |
|---|---|---|---|
meta_id | BIGINT | Identifiant unique de la métadonnée. | 4289 |
post_id | BIGINT | Identifiant du post rattaché (film ou série). | 104 (ex. le film Interstellar) |
meta_key | VARCHAR | Nom technique du champ personnalisé. | duree_minutes |
meta_value | LONGTEXT | Contenu stocké (texte, nombre, chaîne JSON). | 169 |
Pour faire apparaître le panneau natif des champs personnalisés dans l’administration, votre CPT doit obligatoirement inclure 'custom-fields' dans son argument supports lors de l’enregistrement avec register_post_type().
Récupérer une métadonnée en PHP : get_post_meta()
Sans aucune extension tierce, vous pouvez lire une métadonnée native dans vos gabarits de thème à l’aide de la fonction WordPress get_post_meta() :
<?php
// Récupération de la durée du film (3e argument à 'true' impératif)
$duree = get_post_meta( get_the_ID(), 'duree_minutes', true );
if ( ! empty( $duree ) ) : ?>
<p class="film-duration">
<strong>Durée :</strong> <?php echo esc_html( $duree ); ?> minutes
</p>
<?php endif; ?>Attention au piège classique du 3e argument : par défaut, le troisième paramètre $single de get_post_meta() vaut false, ce qui renvoie un tableau (array) de valeurs. Si vous souhaitez obtenir directement une chaîne de caractères ou un nombre exploitable, vous devez obligatoirement passer true en troisième argument.
Pourquoi utiliser l’extension Advanced Custom Fields (ACF) ?
Si la métabox native de WordPress fonctionne, elle s’avère vite limitée et risquée en production pour des clients :
- Interface rudimentaire : l’interface native ne propose que de simples champs texte bruts, sans vérification de saisie ni confort visuel.
- Risque d’erreur humaine : le contributeur doit taper manuellement le nom exact de la clé (
meta_key). Une simple faute de frappe rend la donnée introuvable dans le template. - Types de données riches impossibles : impossible de proposer nativement un sélecteur de fichier multimédia, un calendrier avec sélecteur de date, des cases à cocher, des galeries d’images ou des liens de relations entre contenus.
C’est ici qu’intervient Advanced Custom Fields (ACF), l’extension standard de l’écosystème WordPress professionnel. ACF permet de créer des interfaces de saisie sur-mesure (plus de 30 types de champs différents) et de conditionner leur affichage selon des règles précises (ex. afficher le groupe uniquement sur les publications de type film ou serie).
Cas pratique Netfloux : le groupe de champs « Films & Séries »
Sur notre projet Netfloux, nous créons un groupe de champs nommé Films & Séries rattaché conjointement à nos deux Custom Post Types grâce aux règles d’emplacement ACF :
| Intitulé du champ | Nom technique (name) | Type de champ ACF | Format de retour | Rôle sur Netfloux |
|---|---|---|---|---|
| Fichier vidéo | fichier_video | Fichier (File) | Tableau (Array) | Lien vers la vidéo MP4 téléversée dans la médiathèque. |
| Durée en minutes | duree_minutes | Nombre (Number) | Nombre entier | Afficher la durée exacte du film (ex. 124 min). |
| Réalisateur / Créateur | realisateur | Texte (Text) | Texte brut | Nom du cinéaste ou showrunner. |
| Bande-annonce | bande_annonce | oEmbed | Code d’intégration | URL YouTube ou Vimeo intégrée dans un lecteur vidéo. |
Dans les réglages d’emplacement (Location Rules) du groupe ACF, nous définissons : Type de publication est égal à film OU Type de publication est égal à serie. Le groupe apparaît ainsi instantanément sous l’éditeur de blocs de ces deux types de contenus.
Afficher les champs ACF dans son thème : get_field() et the_field()
Pour exploiter les champs ACF dans vos gabarits de thème (index.php, single-film.php ou single-serie.php), ACF met à disposition deux fonctions reines :
the_field( 'nom_du_champ' ): affiche directement la valeur à l’écran (équivalent d’unecho). À réserver aux champs texte simples.get_field( 'nom_du_champ' ): renvoie la valeur sous forme de variable PHP (chaîne, nombre, tableau ou objet). C’est la fonction recommandée pour tester si le champ est rempli et sécuriser l’affichage.
Voici l’implémentation complète pour intégrer le lecteur vidéo HTML5 et les métadonnées d’un film sur Netfloux :
<?php
// 1. Récupération des champs ACF
$video = get_field( 'fichier_video' ); // Tableau contenant 'url', 'mime_type', 'filesize'
$duree = get_field( 'duree_minutes' );
$realisateur = get_field( 'realisateur' );
?>
<section class="netfloux-player">
<?php if ( ! empty( $video ) && isset( $video['url'] ) ) : ?>
<div class="video-wrapper">
<video controls poster="<?php echo esc_url( get_the_post_thumbnail_url( get_the_ID(), 'full' ) ); ?>">
<source src="<?php echo esc_url( $video['url'] ); ?>" type="<?php echo esc_attr( $video['mime_type'] ); ?>">
Votre navigateur ne prend pas en charge la lecture de vidéos HTML5.
</video>
</div>
<?php endif; ?>
<div class="video-meta">
<?php if ( ! empty( $realisateur ) ) : ?>
<p><strong>Réalisation :</strong> <?php echo esc_html( $realisateur ); ?></p>
<?php endif; ?>
<?php if ( ! empty( $duree ) ) : ?>
<p><strong>Durée :</strong> <?php echo esc_html( $duree ); ?> min</p>
<?php endif; ?>
</div>
</section>Règle de sécurité impérative : n’affichez jamais une variable PHP brute provenant de la base de données. Utilisez systématiquement les fonctions d’échappement natives de WordPress : esc_html() pour du texte, esc_url() pour les adresses web et esc_attr() pour les attributs HTML.
Filtrer et trier avec WP_Query et meta_query
Les champs personnalisés ne servent pas seulement à enrichir l’affichage d’un article unique : ils permettent de concevoir des requêtes avancées avec WP_Query via l’argument meta_query. Par exemple, afficher les films durant plus de 2 heures (120 minutes) :
<?php
$args = array(
'post_type' => 'film',
'posts_per_page' => 6,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'duree_minutes',
'value' => 120,
'type' => 'NUMERIC',
'compare' => '>=', // Supérieur ou égal à 120 min
),
),
'meta_key' => 'duree_minutes',
'orderby' => 'meta_value_num', // Tri du plus long au plus court
'order' => 'DESC',
);
$long_films = new WP_Query( $args );
if ( $long_films->have_posts() ) :
echo '<ul class="films-list">';
while ( $long_films->have_posts() ) : $long_films->the_post(); ?>
<li>
<?php the_title(); ?> — <?php the_field( 'duree_minutes' ); ?> min
</li>
<?php endwhile;
echo '</ul>';
wp_reset_postdata();
endif;
?>Bonne pratique pro : versionner ses champs ACF (Local JSON et PHP)
Par défaut, lorsque vous configurez vos groupes de champs dans l’administration d’ACF, ceux-ci sont stockés dans la base de données. En équipe ou lors de déploiements avec Git, vous risquez d’écraser vos configurations entre votre environnement local et le serveur de production. Il existe deux méthodes professionnelles pour versionner vos champs :
1. Le Local JSON d’ACF (Méthode recommandée)
Créez simplement un dossier nommé acf-json à la racine de votre thème ou de votre mu-plugin. Chaque fois que vous enregistrez un groupe de champs dans le tableau de bord, ACF génère automatiquement un fichier JSON synchronisable sous Git.
2. L’enregistrement direct en PHP avec acf_add_local_field_group()
ACF permet également d’exporter vos champs sous forme de code PHP natif via le hook acf/include_fields et la fonction acf_add_local_field_group(). Cette technique permet d’embarquer les champs directement dans le même fichier que vos CPT (dans wp-content/mu-plugins/netfloux-cpt.php) et supprime toute requête SQL de chargement de configuration :
<?php
add_action( 'acf/include_fields', function() {
if ( ! function_exists( 'acf_add_local_field_group' ) ) {
return;
}
acf_add_local_field_group( array(
'key' => 'group_netfloux_media',
'title' => 'Films & Séries',
'fields' => array(
array(
'key' => 'field_fichier_video',
'label' => 'Fichier vidéo',
'name' => 'fichier_video',
'type' => 'file',
'return_format' => 'array',
'library' => 'all',
'mime_types' => 'mp4,mkv,webm',
),
),
'location' => array(
array(
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'film',
),
),
array(
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'serie',
),
),
),
) );
} );Questions fréquentes
the_field(‘nom_champ’) effectue un affichage direct à l’écran (echo), tandis que get_field(‘nom_champ’) renvoie la valeur brute ou formatée sous forme de variable PHP (chaîne, nombre, tableau d’image ou objet). get_field() est indispensable pour vérifier si un champ est rempli avant de générer le balisage HTML.
Par défaut, le troisième paramètre de la fonction native get_post_meta() vaut false, ce qui indique à WordPress de retourner toutes les valeurs associées sous forme de tableau. Pour récupérer une valeur unique sous forme de chaîne de caractères, vous devez obligatoirement passer true en troisième argument : get_post_meta( get_the_ID(), ‘cle’, true ).
Par défaut, get_field() et the_field() utilisent l’ID de la publication en cours dans la boucle. Pour récupérer un champ en dehors de la boucle (par exemple dans le header, le footer ou sur une page d’options), passez l’identifiant de la page en second argument : get_field( ‘mon_champ’, $post_id ) ou get_field( ‘mon_champ’, ‘option’ ).
Même si les données sont saisies par des administrateurs, les bonnes pratiques de sécurité WordPress imposent de neutraliser les injections de scripts malveillants (failles XSS). Échapper systématiquement les données avec esc_html(), esc_attr() ou esc_url() garantit un code propre, robuste et auditable.