Aller au contenu
🛠 Comment ajouter un champ personnalisé à de nombreux articles dans WordPress

🛠 Comment ajouter un champ personnalisé à de nombreux articles dans WordPress

Un site sous WordPress a grossi jusqu’à atteindre des centaines d’articles, et chacun doit recevoir un nouveau champ personnalisé. Ouvrir chaque article à la main et cliquer sur «Mettre à jour» prend au minimum une demi-journée.

C’est particulièrement vrai quand vous peaufinez un thème ou que vous connectez un plugin SEO qui a besoin du même meta_key sur l’ensemble du flux d’articles. Le panneau d’administration de WordPress ne propose pas de bouton «Appliquer à tous», mais il vous donne deux façons de résoudre ce problème avec du code.

Voici les deux méthodes, avec des extraits prêts à l’emploi: rapide (une requête SQL pour tout le lot) et simple (une boucle sur les IDs avec la fonction native add_post_meta). Choisissez en fonction de la tâche.

Deux moniteurs affichent divers blocs de code source et fichiers de développement sur l'espace de travail d'un développeur

💡 Aperçu rapide:

  • Vous pouvez attribuer en masse le même champ personnalisé à tous les articles avec add_post_meta dans une boucle, 4 lignes de code.
  • Si vous avez des centaines d’articles et que la vitesse compte, une insertion directe dans la table wp_postmeta via une fonction personnalisée.
  • Les deux méthodes fonctionnent via le fichier functions.php du thème ou le plugin Code Snippets. Sauvegardez la base de données avant d’exécuter du SQL.

Pourquoi ajouter un champ à de nombreux articles en une fois

Les champs personnalisés (aussi appelés post meta) stockent des informations supplémentaires sur un enregistrement: compteur de vues, étiquettes pour le filtrage interne, un drapeau «favori», un ID de produit lié. Tout ce qui ne rentre pas dans les champs standards post_title et post_content.

D’habitude, un champ est ajouté au cas par cas: ouvrez un article, trouvez le bloc «Champs personnalisés» dans l’éditeur, saisissez une paire clé-valeur. Mais quand le champ doit apparaître sur les 200 articles d’un coup, la méthode manuelle est exclue.

Scénarios typiques où une action de masse est nécessaire:

  • Vous avez activé un thème enfant qui utilise get_post_meta($post_id, 'featured_post', true) pour marquer les articles populaires. Sans remplissage en masse, les anciens articles n’apparaîtront pas dans le rendu.
  • Un audit SEO a exigé de définir noindex pour un type de contenu spécifique via un champ meta, plutôt que par le robots.txt.
  • Migration depuis une autre plateforme: les données de l’ancien CMS sont arrivées dans un CSV, et il faut les charger dans wp_postmeta pour des milliers d’enregistrements.

WordPress n’a pas de fonction native add_multiple_posts_meta. Mais il existe deux chemins éprouvés, à choisir selon la situation.

Méthode 1. Une requête SQL pour tous les articles

La méthode la plus rapide, une insertion directe dans la table wp_postmeta en une seule transaction. Au lieu de 200 requêtes individuelles vers la base, vous en faites une, et elle s’exécute en millisecondes.

Voici la fonction add_multiple_posts_meta, qui accepte un tableau d’IDs d’articles et reproduit la signature de la fonction native add_post_meta: mêmes paramètres, même ordre.

Ajoutez le code au fichier functions.php du thème enfant ou via le plugin Code Snippets. La fonction vérifie elle-même si un tel champ existe déjà pour l’article (si $unique = true est passé) et filtre les IDs invalides.

1if( !function_exists( 'add_multiple_posts_meta' ) ){
2 function add_multiple_posts_meta( $post_ids, $meta_key, $meta_value, $unique = false ){
3
4 // If key or ID is not set — exit
5 if( !$meta_key || empty( $post_ids ) ){
6 return false;
7 }
8
9 // One post — pass to native add_post_meta
10 if( is_numeric( $post_ids ) || ( is_array( $post_ids ) && count( $post_ids ) === 1 ) ){
11 return add_post_meta(
12 is_array( $post_ids ) ? $post_ids[0] : $post_ids,
13 $meta_key,
14 $meta_value,
15 $unique
16 );
17 }
18
19 global $wpdb;
20
21 // Filter out invalid IDs and duplicates
22 $valid_post_ids = array_unique(
23 array_filter( $post_ids, function( $post_id ) use ( $wpdb, $meta_key, $unique ){
24 return $post_id
25 && is_numeric( $post_id )
26 && get_post_status( $post_id )
27 && (
28 ! $unique
29 || ! $wpdb->get_var( $wpdb->prepare(
30 "SELECT COUNT(*) FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s",
31 $post_id,
32 $meta_key
33 ) )
34 );
35 } )
36 );
37
38 if( ! count( $valid_post_ids ) ){
39 return false;
40 }
41
42 // Sanitization
43 $meta_key = wp_unslash( $meta_key );
44 $meta_value = sanitize_meta( $meta_key, wp_unslash( $meta_value ), 'post' );
45
46 // Collect data and format strings for a single INSERT
47 $insert_data = [];
48 $insert_formats = [];
49
50 foreach( $valid_post_ids as $post_id ){
51 array_push( $insert_data, $post_id, $meta_key, $meta_value );
52 $insert_formats[] = '(%d, %s, %s)';
53 }
54
55 $sql_string = "INSERT INTO $wpdb->postmeta (`post_id`, `meta_key`, `meta_value`) VALUES "
56 . implode( ', ', $insert_formats );
57
58 // ... unpacks the array into separate arguments for prepare
59 $sql_query = $wpdb->prepare( $sql_string, ...$insert_data );
60
61 return $wpdb->query( $sql_query );
62 }
63}

Ce qui se passe ici, ligne par ligne. La vérification !function_exists est une protection contre les conflits: si un autre plugin a déjà déclaré une fonction avec ce nom, il n’y aura pas d’erreur fatale. Le bloc is_numeric($post_ids) transmet un ID unique à la fonction native add_post_meta, de sorte que la même fonction marche aussi bien avec un seul article qu’avec un tableau. Le filtre array_filter écarte les IDs des brouillons, des enregistrements supprimés et de ceux pour lesquels le champ unique existe déjà. La sanitization via wp_unslash et sanitize_meta est obligatoire: sans elle, les données sérialisées et les caractères spéciaux casseraient la requête.

*Remarque importante à propos de ...$insert_data.* L’opérateur ... (splat) décompose le tableau en une liste plate d’arguments. Sans lui, $wpdb->prepare recevrait un seul argument de type tableau au lieu d’un ensemble de (%d, %s, %s), et la requête échouerait avec une erreur de comptage de paramètres. PHP 5.6+ (WordPress exige au minimum la version 7.0, vous êtes donc tranquille).

Comment l’utiliser

Passez un tableau d’IDs d’articles, la clé et la valeur comme un appel classique. Le quatrième paramètre, le drapeau d’unicité: true empêchera d’ajouter le champ s’il existe déjà pour l’article.

1$post_ids = [ 1, 2, 3, 42, 108 ];
2$meta_key = 'featured_priority';
3$meta_value = 'high';
4$unique = false; // will set for all, even if the field already existed
5
6add_multiple_posts_meta( $post_ids, $meta_key, $meta_value, $unique );

Il est pratique d’exécuter un tel appel via le hook init (une seule fois, puis on le retire) ou via WP-CLI avec la commande wp eval-file. Après exécution, pensez à retirer le code de functions.php, sinon la fonction se déclenchera à chaque chargement de page.

Méthode 2. Boucle sur les IDs avec add_post_meta

Si vous ne voulez pas toucher au SQL directement, utilisez la fonction native add_post_meta dans une boucle. Le code est quatre fois plus court et s’appuie entièrement sur le cœur de WordPress.

1$post_ids = [ 1, 2, 3, 42, 108 ];
2$meta_key = 'featured_priority';
3$meta_value = 'high';
4$unique = false;
5
6foreach( $post_ids as $post_id ){
7 add_post_meta( $post_id, $meta_key, $meta_value, $unique );
8}

La boucle parcourt le tableau et appelle add_post_meta pour chaque ID. La fonction vérifie elle-même l’existence de l’enregistrement, l’unicité de la clé (si $unique = true est défini) et la correction des données; aucune validation supplémentaire n’est nécessaire.

Performance. Avec une centaine d’articles, la différence avec la requête SQL est imperceptible. Mais si vous avez 5 000 enregistrements, chaque appel à add_post_meta génère une insertion séparée, plus les hooks internes (added_post_meta, update_post_meta_cache). À de tels volumes, la première méthode avec une requête unique s’exécutera 10 à 20 fois plus vite.

Pour des opérations ponctuelles sur quelques dizaines d’articles, utilisez la boucle, ne compliquez pas les choses.

Comparaison des approches

Critère

Méthode 1 (SQL unique)

Méthode 2 (boucle add_post_meta)

Vitesse sur 5 000 articles

~0,2 s (1 requête)

~3-6 s (5 000 requêtes)

Complexité du code

~50 lignes avec validation

4 lignes

Sécurité

Sanitization manuelle nécessaire

add_post_meta gère tout

Hooks WordPress

Non appelés

added_post_meta, update_post_meta_cache

Quand choisir

Migration en masse, import CSV

Éditions ponctuelles, jusqu’à cent articles

Une règle universelle: s’il y a moins d’une centaine d’articles et que l’opération est ponctuelle, utilisez la boucle. S’il s’agit d’une synchronisation régulière ou d’une migration de milliers d’enregistrements, seule la requête directe avec la fonction préparée convient.

⁉️🤔 Questions fréquentes

Puis-je attribuer un champ de manière sélective, uniquement aux articles d’une catégorie spécifique?

Oui. Récupérez les IDs d’articles via get_posts avec le paramètre 'category' => ID_рубрики, puis passez le tableau à l’une des deux méthodes ci-dessus. Pour des milliers d’articles, ajoutez 'numberposts' => -1 et 'fields' => 'ids'; la requête renverra uniquement un tableau d’IDs, sans charger les objets.

Voici un exemple prêt à l’emploi: $post_ids = get_posts( [ 'category' => 5, 'numberposts' => -1, 'fields' => 'ids', 'post_type' => 'post' ] );. Ensuite, appelez add_multiple_posts_meta($post_ids, ...) ou une boucle avec add_post_meta.

Et si j’ai besoin d’une valeur de champ différente selon les articles?

L’insertion en masse ne fonctionnera pas ici. Construisez un tableau associatif [ ID_поста => значение ] et parcourez-le dans une boucle avec add_post_meta ou update_post_meta. Une valeur pour tous, SQL; des valeurs différentes selon les articles, uniquement une boucle.

Pour plus de 50 articles avec des valeurs uniques, utilisez update_post_meta au lieu de add_post_meta: cela ne crée pas de doublons si le champ existe déjà.

Est-il sûr d’écrire des requêtes SQL directement dans wp_postmeta?

C’est sûr à deux conditions. Premièrement: passez toujours les données par $wpdb->prepare; cela échappe les caractères spéciaux et bloque les injections SQL. Deuxièmement: faites une sauvegarde complète de la base avant d’exécuter quoi que ce soit. Un seul UPDATE incorrect sans WHERE, et wp_postmeta est vidé pour tous les enregistrements.

Commande de sauvegarde via WP-CLI: wp db export backup-before-meta.sql. Restauration: wp db import backup-before-meta.sql.

Quelle est la différence entre add_post_meta et update_post_meta?

add_post_meta ajoute une nouvelle ligne dans wp_postmeta, même si la clé existe déjà pour l’article, ce qui crée un doublon. update_post_meta vérifie l’existence de la clé: si elle existe, il met à jour la valeur; sinon, il la crée. Pour un remplissage en masse où il y a une clé par article, add_post_meta avec $unique = true produit le même effet.

En pratique: add_post_meta($id, 'views', 0, true) créera le champ une fois et n’y touchera plus jamais. update_post_meta($id, 'views', $count) écrasera la valeur à chaque appel.

Où placer le code, dans le thème ou un plugin?

Pour des opérations ponctuelles, dans le fichier functions.php du thème enfant, avec retrait immédiat après exécution. Pour des tâches récurrentes, empaquetez-le dans un plugin Must-Use (dossier wp-content/mu-plugins/) ou ajoutez-le à Code Snippets avec le drapeau «Exécuter une seule fois». Du code dans un thème actif sans retrait interrogera la base à chaque chargement de page; c’est une charge inutile.

Que choisir pour votre tâche

La pratique montre que 9 cas sur 10 sont couverts par la boucle avec add_post_meta. C’est quatre lignes de code, une fonction native et aucune surprise.

Une requête SQL directe se justifie dans deux situations: une migration en masse (des milliers d’articles, le temps est précieux) et une synchronisation périodique où vous maîtrisez la sanitization en entrée. Sinon, ne compliquez pas les choses.

Ce qu’il faut faire tout de suite:

  • Si vous devez attribuer un champ à ≤100 articles, copiez la boucle de la deuxième méthode, insérez vos IDs et exécutez-la.
  • S’il y a plusieurs milliers d’articles, prenez la fonction de la première méthode, mais testez-la d’abord sur une copie du site.
  • Dans tous les cas, sauvegardez la base de données avant d’exécuter. Ce n’est pas une précaution, c’est une règle.

Et vous, quelle méthode utilisez-vous habituellement pour ajouter des champs personnalisés: via le panneau d’administration, du code ou un plugin comme ACF? Écrivez dans les commentaires, c’est intéressant de comparer les approches.