15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer
21.10.2024

Qu’est-ce qu’une Tax Query dans WordPress ? Un guide complet pour les développeurs

Une requête tax dans WordPress est un filtre structuré transmis à WP_Query qui récupère les articles correspondant à des termes de taxonomie spécifiques. Au lieu d’extraire chaque article de la base de données, une requête tax réduit l’ensemble de résultats aux seuls enregistrements dont les relations de termes satisfont vos conditions définies — qu’il s’agisse d’un seul slug de catégorie, d’une combinaison de termes de taxonomie personnalisée, ou d’un modèle d’exclusion multi-taxonomie complexe.

En termes pratiques : si vous devez afficher uniquement les articles étiquetés « web-development » qui appartiennent également à une taxonomie personnalisée appelée « project-type » avec le terme « client-work », une requête tax est l’outil correct et performant pour ce travail. Elle opère au niveau SQL via la classe WP_Tax_Query de WordPress, générant des clauses JOIN et WHERE optimisées contre les tables wp_term_relationships et wp_term_taxonomy.

Comment les taxonomies et les termes WordPress sont structurés

Avant d’écrire une seule ligne de code de requête, vous avez besoin d’un modèle mental clair de l’architecture de données sous-jacente.

Les taxonomies sont des systèmes de classification. WordPress est livré avec deux taxonomies globales — category et post_tag — mais la fonction register_taxonomy() vous permet d’en définir un nombre illimité. Une taxonomie est essentiellement un mécanisme de regroupement nommé.

Les termes sont les étiquettes individuelles au sein d’une taxonomie. Dans la taxonomie category, « Technology », « Lifestyle » et « Business » sont des termes. Chaque terme possède trois identifiants adressables :

  • term_id — la clé primaire entière dans wp_terms
  • slug — l’identifiant de chaîne compatible URL (ex. : web-development)
  • name — le libellé d’affichage lisible par l’humain

Les relations de termes sont les enregistrements pivot dans wp_term_relationships qui relient l’ID objet d’un article à un ID de taxonomie de terme. Chaque requête tax se résout finalement en une recherche dans cette table.

Comprendre cette structure à trois niveaux — taxonomie > terme > relation de terme — est essentiel pour écrire des requêtes efficaces et diagnostiquer des ensembles de résultats inattendus.

Arguments principaux du paramètre tax_query

La clé tax_query accepte un tableau d’un ou plusieurs tableaux de clauses de requête, plus une clé relation optionnelle au niveau supérieur. Chaque clause prend en charge les arguments suivants :

ArgumentTypeDescriptionValeurs courantes
`taxonomy`stringLa taxonomie à interroger`category`, `post_tag`, slug personnalisé
`field`stringQuel champ de terme faire correspondre`slug`, `name`, `term_id`, `term_taxonomy_id`
`terms`string / int / arrayLa ou les valeurs de terme à faire correspondre`'technology'`, `[4, 7]`, `'web-dev'`
`operator`stringComment appliquer la correspondance de terme`IN`, `NOT IN`, `AND`, `EXISTS`, `NOT EXISTS`
`include_children`boolInclure ou non les termes enfants (taxonomies hiérarchiques uniquement)`true` (par défaut), `false`
`relation`stringConnecteur logique de niveau supérieur entre plusieurs clauses`AND`, `OR`

L’argument operator en détail

C’est là que la plupart des développeurs font des erreurs. Les opérateurs se comportent comme suit :

  • IN (par défaut) — retourne les articles assignés à *n’importe lequel* des termes spécifiés. Il s’agit d’une correspondance OR au sein d’une seule clause.
  • NOT IN — exclut les articles assignés à l’un des termes spécifiés.
  • AND — retourne les articles assignés à *tous* les termes spécifiés simultanément. Utilisez ceci lorsqu’un article doit porter plusieurs étiquettes à la fois.
  • EXISTS — retourne les articles qui ont *n’importe quel* terme dans la taxonomie spécifiée, quel qu’il soit. L’argument terms est ignoré.
  • NOT EXISTS — retourne les articles sans aucun terme assigné dans la taxonomie spécifiée. Utile pour trouver du contenu non catégorisé ou sans étiquette.

Une nuance critique : operator => 'AND' au sein d’une seule clause vérifie qu’un article est assigné à chaque terme du tableau terms. C’est différent d’utiliser relation => 'AND' au niveau supérieur, qui combine des clauses séparées. Confondre ces deux éléments est l’un des bugs de requête tax les plus courants dans le code WordPress en production.

Requête tax de base : filtre de taxonomie unique

Le cas d’utilisation le plus simple — récupérer tous les articles dans la catégorie « Technology » :

$args = array(
    'post_type'  => 'post',
    'tax_query'  => array(
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => 'technology',
        ),
    ),
);

$query = new WP_Query( $args );

if ( $query->have_posts() ) {
    while ( $query->have_posts() ) {
        $query->the_post();
        // Render post content here
    }
    wp_reset_postdata();
}

Appelez toujours wp_reset_postdata() après une boucle WP_Query personnalisée. Ne pas le faire corrompt l’objet global $post, ce qui casse les balises de template comme the_title() et get_the_ID() pour toutes les requêtes suivantes sur la même page.

Combiner plusieurs requêtes tax avec relation

La clé relation au niveau supérieur du tableau tax_query contrôle la façon dont plusieurs clauses sont jointes :

$args = array(
    'post_type'  => 'post',
    'tax_query'  => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => 'technology',
        ),
        array(
            'taxonomy' => 'post_tag',
            'field'    => 'slug',
            'terms'    => 'web-development',
        ),
    ),
);

Cela retourne uniquement les articles qui sont *simultanément* dans la catégorie « Technology » et étiquetés « web-development ». Remplacez relation par 'OR' et vous obtenez les articles correspondant à l’une ou l’autre condition.

Requêtes tax imbriquées (WordPress 4.1+)

Pour une logique de filtrage avancée, WordPress prend en charge les tableaux tax_query imbriqués, vous permettant de construire des expressions booléennes composées :

$args = array(
    'post_type'  => 'product',
    'tax_query'  => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'product_cat',
            'field'    => 'slug',
            'terms'    => array( 'laptops', 'desktops' ),
            'operator' => 'IN',
        ),
        array(
            'relation' => 'OR',
            array(
                'taxonomy' => 'product_tag',
                'field'    => 'slug',
                'terms'    => 'sale',
            ),
            array(
                'taxonomy' => 'availability',
                'field'    => 'slug',
                'terms'    => 'in-stock',
            ),
        ),
    ),
);

Cela récupère les produits dans « Laptops » ou « Desktops » qui sont *également* soit en promotion soit en stock. Ce type de logique imbriquée est impossible à reproduire proprement avec une clé relation plate — les tableaux imbriqués sont la seule approche correcte.

Types de publications personnalisés et taxonomies personnalisées

Les requêtes tax deviennent particulièrement puissantes lorsqu’elles sont combinées avec des types de publications personnalisés enregistrés via register_post_type() et des taxonomies personnalisées via register_taxonomy(). Considérez un site portfolio où vous enregistrez un type de publication portfolio et une taxonomie portfolio_type :

// Register custom taxonomy (typically in functions.php or a plugin)
register_taxonomy(
    'portfolio_type',
    'portfolio',
    array(
        'label'        => 'Portfolio Types',
        'hierarchical' => true,
    )
);

// Query portfolio items of type "branding"
$args = array(
    'post_type'  => 'portfolio',
    'tax_query'  => array(
        array(
            'taxonomy' => 'portfolio_type',
            'field'    => 'slug',
            'terms'    => 'branding',
        ),
    ),
);

$query = new WP_Query( $args );

Lorsque hierarchical est true et que include_children n’est pas explicitement défini sur false, la requête inclut automatiquement tous les termes enfants de « branding ». C’est le comportement correct pour les hiérarchies de style catégorie, mais cela peut produire des résultats inattendus si vous avez des arborescences de termes profondément imbriquées. Définissez 'include_children' => false lorsque vous avez besoin d’une correspondance de terme exacte uniquement.

Utiliser term_id vs. slug vs. name comme valeur field

Valeur du champUtiliser quandMise en garde
`slug`Requêtes codées en dur dans le code du thème/pluginLes slugs peuvent être modifiés par les éditeurs dans l’administration
`term_id`Requêtes critiques en termes de performance ou programmatiquesLes IDs diffèrent entre les environnements (dev vs. production)
`name`Logique de couche d’affichage lisible par l’humainSensible à la casse ; fragile si les noms sont modifiés
`term_taxonomy_id`Désambiguïsation multi-taxonomieRarement nécessaire ; à utiliser uniquement lorsque les IDs de termes entrent en collision entre les taxonomies

Pour le code en production, slug est généralement le choix le plus sûr pour la lisibilité. Cependant, si vous migrez des bases de données entre un environnement de staging et un environnement live, sachez que les valeurs term_id seront différentes. Utilisez toujours slug pour un code portable.

Considérations de performance et pièges courants

Impact sur la base de données

Chaque requête tax génère au minimum une JOIN supplémentaire contre wp_term_relationships. Avec plusieurs clauses, cela se cumule. Sur des sites avec des dizaines de milliers d’articles, les requêtes tax mal construites sont une cause majeure de chargements de pages lents et de timeouts de base de données.

Optimisations clés :

  • Utilisez fields => 'ids' lorsque vous n’avez besoin que des IDs d’articles, pas des objets d’articles complets. Cela évite de charger les métadonnées d’articles et les données sérialisées.
  • Mettez en cache les résultats avec l’API Transients. Les requêtes tax sur les pages d’archives qui changent rarement doivent être mises en cache avec set_transient() et get_transient().
  • Évitez operator => 'AND' avec de grands tableaux de termes. Chaque terme supplémentaire dans une clause AND ajoute une sous-requête. Effectuez des benchmarks avec EXPLAIN dans MySQL avant le déploiement.
  • Définissez no_found_rows => true lorsque vous n’avez pas besoin de pagination. Cela évite la surcharge de SQL_CALC_FOUND_ROWS.
$args = array(
    'post_type'      => 'post',
    'fields'         => 'ids',
    'no_found_rows'  => true,
    'tax_query'      => array(
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => 'technology',
        ),
    ),
);

Le piège wp_reset_postdata()

Si vous exécutez un WP_Query secondaire à l’intérieur d’une boucle principale sans réinitialiser les données d’article, la variable globale $post pointera vers le mauvais article pour le reste du rendu de la page. Cela provoque des bugs subtils : mauvais titres d’articles dans les fils d’Ariane, URLs canoniques incorrectes et balises Open Graph cassées. Réinitialisez toujours.

Interroger des termes qui n’existent pas

Si vous transmettez une valeur terms qui n’existe pas dans la base de données, WP_Query retourne zéro résultat silencieusement. Il n’y a aucune erreur ni avertissement. Validez toujours l’existence du terme avec term_exists() avant de construire des requêtes tax dynamiques basées sur des entrées utilisateur ou des données externes.

$term = term_exists( 'technology', 'category' );
if ( $term !== 0 && $term !== null ) {
    // Safe to build the tax query
}

Cas d’utilisation réels

Pages d’archives personnalisées

Remplacez archive.php ou utilisez pre_get_posts pour injecter une requête tax dans la requête principale, filtrant une archive pour afficher uniquement des termes spécifiques sans créer un objet de requête séparé :

add_action( 'pre_get_posts', function( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'portfolio' ) ) {
        $query->set( 'tax_query', array(
            array(
                'taxonomy' => 'portfolio_type',
                'field'    => 'slug',
                'terms'    => array( 'branding', 'web-design' ),
                'operator' => 'IN',
            ),
        ) );
    }
} );

Utiliser pre_get_posts est plus efficace qu’instancier un WP_Query secondaire car cela modifie la requête principale avant qu’elle n’atteigne la base de données.

Filtrage de produits e-commerce

WooCommerce enregistre product_cat et product_tag comme taxonomies WordPress standard, plus des taxonomies d’attributs comme pa_color et pa_size. Les requêtes tax alimentent la barre latérale de filtre de navigation à facettes. Un filtre personnalisé pour « ordinateurs portables rouges d’une marque spécifique » combinerait trois clauses de taxonomie séparées avec relation => 'AND'.

Exclure du contenu éditorialement

Utilisez operator => 'NOT IN' pour supprimer le contenu sponsorisé ou promotionnel des flux éditoriaux :

$args = array(
    'post_type'  => 'post',
    'tax_query'  => array(
        array(
            'taxonomy' => 'post_tag',
            'field'    => 'slug',
            'terms'    => array( 'sponsored', 'promoted' ),
            'operator' => 'NOT IN',
        ),
    ),
);

Trouver du contenu non classifié

Utilisez operator => 'NOT EXISTS' pour auditer votre bibliothèque de contenu à la recherche d’articles manquant d’assignations de taxonomie requises :

$args = array(
    'post_type'  => 'post',
    'tax_query'  => array(
        array(
            'taxonomy' => 'category',
            'operator' => 'NOT EXISTS',
        ),
    ),
);

Cela est inestimable pour les audits de contenu sur les grands sites éditoriaux où les articles peuvent avoir été importés sans assignation de taxonomie appropriée.

Requête tax vs. requête meta : choisir le bon outil

Une décision architecturale courante dans le développement WordPress est de savoir si les données de filtrage doivent être stockées comme terme de taxonomie ou comme métadonnée d’article. Ce choix a des implications significatives en termes de performance.

CritèresRequête tax (`tax_query`)Requête meta (`meta_query`)
Table de base de données`wp_term_relationships` (indexée)`wp_postmeta` (moins optimisée pour le filtrage)
Performance des requêtesRapide — conçue pour les recherches basées sur des ensemblesPlus lente à grande échelle — structure EAV
Filtrage à facettesNatif, efficaceNécessite des solutions de contournement
Type de donnéesVocabulaire contrôlé (termes)Paires clé-valeur arbitraires
Cas d’utilisationCatégorisation, classificationAttributs, mesures, indicateurs
IndexationAutomatique via les IDs de taxonomie de termeNécessite un réglage manuel des index

Règle générale : si les données sont utilisées pour le filtrage ou la navigation (couleur, catégorie, type, statut), utilisez une taxonomie. S’il s’agit d’un attribut unique par article (prix, poids, horodatage de publication), utilisez les métadonnées d’article. Confondre ces deux éléments est l’une des causes les plus courantes de sites WordPress lents à grande échelle.

Considérations d’hébergement pour les sites WordPress utilisant des requêtes complexes

Les requêtes tax avec plusieurs clauses, une logique imbriquée ou de grands ensembles de termes génèrent du SQL complexe. La performance de ces requêtes dépend fortement de votre environnement serveur.

Sur un plan d’Hébergement VPS, vous avez un contrôle direct sur la configuration MySQL — vous pouvez régler innodb_buffer_pool_size, activer le cache de requêtes (MySQL 5.7 et antérieur), et ajouter des index personnalisés à wp_term_relationships si nécessaire. Les environnements partagés ne permettent généralement pas ce niveau de réglage de base de données.

Si vous exploitez une boutique WooCommerce à fort trafic avec une navigation à facettes alimentée par des requêtes tax, un Serveur Dédié vous offre des E/S de base de données isolées, ce qui élimine le problème de voisin bruyant qui dégrade les temps de réponse des requêtes sur une infrastructure partagée.

Pour les développeurs qui souhaitent la commodité d’un panneau de contrôle tout en maintenant un accès au niveau serveur pour l’optimisation de la base de données, un VPS avec cPanel offre un juste milieu pratique — accès MySQL complet via phpMyAdmin aux côtés d’une interface de gestion familière.

Les sites qui s’appuient fortement sur les endpoints de l’API REST WordPress alimentés par des requêtes tax devraient également envisager la mise en cache d’objets (Redis ou Memcached) au niveau serveur, configurable sur les Panneaux de contrôle VPS qui prennent en charge les couches de mise en cache PHP personnalisées et côté serveur.

Matrice de décision et liste de contrôle technique

Avant de déployer une requête tax en production, vérifiez les points suivants :

  • Existence du terme validée — utilisez term_exists() pour toutes les valeurs de terme construites dynamiquement
  • wp_reset_postdata() appelé — après chaque boucle WP_Query personnalisée, sans exception
  • include_children explicitement défini — ne vous fiez pas à la valeur par défaut pour les taxonomies hiérarchiques sauf si l’inclusion des enfants est intentionnelle
  • fields => 'ids' utilisé — partout où les objets d’articles complets ne sont pas requis
  • no_found_rows => true défini — sur toute requête qui ne nécessite pas de pagination
  • Résultats mis en cache — utilisez l’API Transients pour les requêtes sur les pages d’archives ou de destination à fort trafic
  • pre_get_posts préféré — aux instances WP_Query secondaires pour les modifications de la requête principale
  • Choix de operator confirmé — distinguez entre IN (n’importe quel terme), AND (tous les termes) et NOT IN (exclusion) avant d’écrire la clause
  • Distinction relation vs. operator clairerelation connecte les clauses ; operator contrôle la correspondance au sein d’une clause
  • Tableaux imbriqués utilisés pour la logique composée — n’essayez pas d’exprimer des combinaisons AND/OR avec une seule clé relation plate
  • Requête de base de données journalisée et examinée — utilisez le plugin Query Monitor ou SAVEQUERIES pour inspecter le SQL généré avant le lancement

FAQ

Quelle est la différence entre relation => 'AND' et operator => 'AND' dans une requête tax ?

relation est une clé de niveau supérieur qui connecte plusieurs clauses de requête tax entre elles — elle détermine si un article doit satisfaire toutes les clauses (AND) ou au moins une (OR). operator est une clé par clause qui détermine comment le tableau terms est mis en correspondance au sein d’une seule clause — AND exige que l’article ait chaque terme listé assigné simultanément.

Pourquoi ma requête tax ne retourne-t-elle aucun résultat même si les articles et les termes existent ?

Les causes les plus courantes sont : transmettre une valeur terms qui ne correspond pas au type field spécifié (ex. : transmettre un nom lorsque field est défini sur slug), interroger une taxonomie non enregistrée pour le type de publication, ou utiliser operator => 'AND' avec des termes qu’aucun article ne détient simultanément. Activez SAVEQUERIES et inspectez le SQL brut pour diagnostiquer.

Puis-je utiliser une requête tax dans l’API REST WordPress ?

Oui. Le WP_REST_Posts_Controller de l’API REST accepte tax_query indirectement via des paramètres de requête enregistrés. Pour les taxonomies personnalisées, vous devez définir 'show_in_rest' => true lors de l’enregistrement de la taxonomie. Pour les requêtes complexes à plusieurs clauses, utilisez un endpoint REST personnalisé qui construit les arguments WP_Query côté serveur.

include_children => true affecte-t-il les performances ?

Oui. Lorsque include_children est activé (la valeur par défaut pour les taxonomies hiérarchiques), WordPress exécute une requête supplémentaire pour récupérer tous les IDs de termes descendants avant de construire la requête principale. Sur les taxonomies avec des hiérarchies profondes et de nombreux termes, cette pré-requête ajoute une surcharge mesurable. Définissez 'include_children' => false lorsque vous avez besoin d’une correspondance de terme exacte et ne nécessitez pas l’héritage des termes enfants.

Y a-t-il une limite au nombre de clauses qu’une requête tax peut avoir ?

Il n’y a pas de limite codée en dur dans le cœur de WordPress, mais des limites pratiques sont imposées par la profondeur maximale de jointure de MySQL et les seuils de complexité des requêtes. Plus de quatre ou cinq clauses dans une seule requête tax est un signal que le modèle de données nécessite peut-être une reconsidération — soit par dénormalisation, un index de recherche dédié (Elasticsearch, Typesense), ou une restructuration de la hiérarchie de taxonomie pour réduire le nombre de clauses.

15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer