WordPress

WP_Query : guide complet des requêtes WordPress personnalisées

Publié le 31 March 2026 — 4 min de lecture
En bref

Maîtrisez WP_Query pour créer des requêtes WordPress personnalisées : paramètres, tax_query, meta_query, pagination et optimisation des performances.

Introduction à WP_Query : la classe centrale de WordPress

WP_Query est la classe PHP qui gère toutes les requêtes de récupération de contenu dans WordPress. Chaque fois qu’une page se charge, une instance de WP_Query est créée pour récupérer les articles, pages ou contenus personnalisés. Comprendre WP_Query vous permet de créer des affichages totalement sur mesure sans plugins tiers.

Ce guide couvre l’instanciation, tous les paramètres essentiels (post_type, tax_query, meta_query, date_query), la gestion de la pagination, les bonnes pratiques de performances et des exemples concrets.

Instancier WP_Query : la syntaxe de base

<?php
$args = array(
    'post_type'      => 'post',
    'posts_per_page' => 10,
    'post_status'    => 'publish',
);

$ma_requete = new WP_Query( $args );

if ( $ma_requete->have_posts() ) {
    while ( $ma_requete->have_posts() ) {
        $ma_requete->the_post();
        echo '<h2>' . get_the_title() . '</h2>';
        echo get_the_excerpt();
    }
    wp_reset_postdata(); // TOUJOURS réinitialiser
} else {
    echo 'Aucun article trouvé.';
}
?>

wp_reset_postdata() est indispensable pour restaurer les données globales de l’article original et éviter des bugs sur les sidebars et widgets.

Paramètres post_type, post_status, orderby

$args = array(
    'post_type'   => array( 'post', 'produit', 'portfolio' ),
    'post_status' => array( 'publish', 'private' ),
    'posts_per_page' => 5,
    'offset'      => 10,
    'orderby'     => 'date',   // date, title, rand, menu_order, meta_value_num
    'order'       => 'DESC',
    'author'      => 3,
    's'           => 'WordPress',
);

tax_query : filtrer par taxonomie

$args = array(
    'post_type' => 'post',
    'tax_query' => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => array( 'wordpress', 'php' ),
            'operator' => 'IN', // IN, NOT IN, AND, EXISTS, NOT EXISTS
        ),
        array(
            'taxonomy' => 'post_tag',
            'field'    => 'slug',
            'terms'    => 'tutoriel',
        ),
    ),
);

meta_query : filtrer par champ personnalisé

$args = array(
    'post_type'  => 'produit',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key'     => '_prix',
            'value'   => array( 10, 100 ),
            'type'    => 'NUMERIC',
            'compare' => 'BETWEEN',
        ),
        array(
            'key'     => '_stock',
            'value'   => 0,
            'type'    => 'NUMERIC',
            'compare' => '>',
        ),
    ),
    'orderby'  => 'meta_value_num',
    'meta_key' => '_prix',
    'order'    => 'ASC',
);

date_query et pagination

// Filtrer par date
$args = array(
    'date_query' => array(
        array(
            'after'     => array( 'year' => 2025, 'month' => 1, 'day' => 1 ),
            'before'    => 'today',
            'inclusive' => true,
        ),
    ),
);

// Pagination correcte
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
    'post_type'      => 'post',
    'posts_per_page' => 6,
    'paged'          => $paged,
);
$requete = new WP_Query( $args );
// Après la boucle :
echo paginate_links( array(
    'base'    => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
    'format'  => '?paged=%#%',
    'current' => max( 1, get_query_var( 'paged' ) ),
    'total'   => $requete->max_num_pages,
) );
wp_reset_postdata();

Optimiser les performances de WP_Query

Paramètre Impact Quand l’utiliser
no_found_rows => true Supprime le COUNT SQL Sans pagination
fields => ‘ids’ Requête minimale Traitement en masse
update_post_meta_cache => false Moins de requêtes Si pas besoin des méta
update_post_term_cache => false Moins de requêtes Si pas besoin des termes
ignore_sticky_posts => true Ignore les sticky Requêtes secondaires
$args = array(
    'post_type'               => 'post',
    'posts_per_page'          => 10,
    'fields'                  => 'ids',
    'no_found_rows'           => true,
    'update_post_meta_cache'  => false,
    'update_post_term_cache'  => false,
    'ignore_sticky_posts'     => true,
);
$ids_query = new WP_Query( $args );
foreach ( $ids_query->posts as $post_id ) {
    echo get_the_title( $post_id );
}

Exemples concrets : afficher des articles par méta et catégorie

// Articles mis en avant d'une catégorie
$args = array(
    'post_type'      => 'post',
    'posts_per_page' => 9,
    'cat'            => 5,
    'meta_query'     => array(
        array( 'key' => 'mise_en_avant', 'value' => '1', 'compare' => '=' ),
    ),
);
$requete = new WP_Query( $args );
if ( $requete->have_posts() ) :
    echo '<div class="grille">';
    while ( $requete->have_posts() ) : $requete->the_post();
        printf(
            '<article><a href="%s"><h3>%s</h3></a><p>%s</p></article>',
            esc_url( get_permalink() ),
            esc_html( get_the_title() ),
            esc_html( get_the_excerpt() )
        );
    endwhile;
    echo '</div>';
    wp_reset_postdata();
endif;

Pour des développements WordPress avancés incluant des requêtes complexes, faites appel à notre développeur WordPress Paris.

Questions fréquentes sur WP_Query

Quelle est la différence entre WP_Query, get_posts() et query_posts() ?

WP_Query est la classe complète recommandée pour les requêtes secondaires. get_posts() est un wrapper simplifié retournant un tableau, pratique pour des listes simples. query_posts() est à éviter absolument car il modifie la requête principale globale et provoque des bugs de pagination. Utilisez le hook pre_get_posts pour modifier la requête principale.

Comment utiliser WP_Query avec un Custom Post Type ?

Remplacez 'post_type' => 'post' par le slug de votre CPT : 'post_type' => 'mon_cpt'. Vérifiez que votre CPT a 'publicly_queryable' => true dans son register_post_type(). Pour plusieurs CPT simultanément : 'post_type' => array('post', 'mon_cpt').

Pourquoi ma pagination WP_Query ne fonctionne pas ?

Causes fréquentes : 1) Oublier le paramètre 'paged'. 2) Confondre get_query_var('page') (page statique) et get_query_var('paged') (blog). 3) Avoir 'no_found_rows' => true qui désactive le calcul du total. 4) Un conflit avec la requête principale.

Comment modifier la requête principale sans WP_Query secondaire ?

Utilisez le hook pre_get_posts pour modifier la requête principale. C’est plus efficace que de créer une requête secondaire car WordPress ne lance qu’une seule requête SQL. Exemple : add_action('pre_get_posts', function($q){ if(!is_admin() && $q->is_main_query() && $q->is_home()){ $q->set('posts_per_page', 12); } });

W
Rédigé par
WebEngine
Développeur web freelance à Paris spécialisé WordPress, WooCommerce et SEO technique depuis 2010. 13 avis vérifiés · Note 5/5. Chaque site livré atteint un score PageSpeed mobile supérieur à 90.

Un projet en tête ?

Devis gratuit sous 48h, sans engagement.

Demander un devis gratuit