Skip to Content
WordPressPartie 5 — Architecture du cœurWP_Query & les requêtes de contenu

Chapitre 5.5 — WP_Query & les requêtes de contenu

⏱️ TL;DRWP_Query est l’objet qui interroge les contenus (wp_posts) via un tableau d’arguments déclaratifs (post_type, posts_per_page, meta_query, tax_query, orderby…), sans écrire de SQL. Trois façons de l’utiliser : la main query (automatique, celle de la page), une requête secondaire (new WP_Query(...)), ou les helpers (get_posts()). Pour modifier la requête de la page, on n’en crée pas une nouvelle : on filtre pre_get_posts. Bien manier WP_Query (et éviter ses pièges de perf) est central en développement.

🎯 Objectifs

  • Construire une requête de contenu avec WP_Query.
  • Filtrer par métadonnées (meta_query) et taxonomies (tax_query).
  • Modifier la main query proprement via pre_get_posts.
  • Éviter les pièges de performance (requêtes coûteuses, posts_per_page => -1).

1. Trois façons d’obtenir des contenus

  • Main query : celle de la page (URL), déjà exécutée ; on la parcourt via la Boucle.
  • new WP_Query( $args ) : une requête que vous formulez (articles liés, carrousel…). Bouclez dessus puis wp_reset_postdata().
  • get_posts( $args ) : un helper qui retourne directement un tableau de posts (pratique hors Boucle).

2. Les arguments essentiels

$args = array( 'post_type' => 'post', // ou 'page', 'livre', array(...) 'post_status' => 'publish', 'posts_per_page' => 10, // -1 = tous (⚠️ voir pièges) 'orderby' => 'date', // 'title', 'menu_order', 'meta_value_num', 'rand'… 'order' => 'DESC', 'paged' => get_query_var( 'paged' ) ?: 1, 'category_name' => 'actus', 's' => 'terme de recherche', ); $q = new WP_Query( $args );

Quelques familles d’arguments : type/statut, pagination (posts_per_page, paged, offset), tri (orderby, order), filtre par auteur, date, taxonomie, métadonnée.

💡 Pour un dev ReactWP_Query est un query builder déclaratif (façon Prisma/ORM) : vous décrivez quoi récupérer via un objet d’arguments, WordPress génère le SQL, gère la pagination et le cache. get_posts()findMany(). La logique « décris ta requête, pas ton SQL » vous est familière — les noms d’arguments diffèrent, l’intuition non.


3. Filtrer par métadonnées et taxonomies

// Livres à moins de 20 €, du genre "roman" $args = array( 'post_type' => 'livre', 'meta_query' => array( array( 'key' => 'prix', 'value' => 20, 'type' => 'NUMERIC', 'compare' => '<=', ), ), 'tax_query' => array( array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => 'roman', ), ), );
  • meta_query : filtre sur wp_postmeta (clé/valeur, opérateurs =, <=, LIKE, IN, BETWEEN…).
  • tax_query : filtre sur les taxonomies (par slug/id/name), combinable en AND/OR.

⚠️ Piège n°1 — les meta_query coûteuses. Filtrer/trier sur des métadonnées implique des jointures sur wp_postmeta (modèle EAV, ch. 4.6), vite lourdes sur de gros volumes. Pour des filtres fréquents et critiques (e-commerce, annuaires), on envisage des tables dédiées, des taxonomies (indexées, plus rapides que meta pour du filtrage), ou un moteur de recherche externe. Ne construisez pas un catalogue de 100 000 produits filtré uniquement par meta_query.


4. Modifier la main query : pre_get_posts

Pour changer ce qu’affiche une page (ex. « 12 articles par page sur les archives », « inclure les CPT dans la recherche »), ne créez pas une nouvelle requête dans le thème : filtrez la main query avant son exécution.

add_action( 'pre_get_posts', 'monprefixe_ajuster_query' ); function monprefixe_ajuster_query( WP_Query $query ) { // uniquement la requête principale, côté front, sur les archives if ( is_admin() || ! $query->is_main_query() ) { return; } if ( $query->is_archive() ) { $query->set( 'posts_per_page', 12 ); } }

⚠️ Piège n°2 — modifier toutes les requêtes. Sans les gardes ! is_admin() et $query->is_main_query(), votre filtre s’applique partout (admin inclus, requêtes secondaires) → effets de bord graves (listes d’admin cassées, widgets faussés). Toujours cibler précisément.


5. Pièges de performance (récap)

  • posts_per_page => -1 : charge tous les contenus en mémoire. Dangereux sur de gros volumes (OOM). Paginez ou limitez.
  • meta_query lourdes : voir §3.
  • Requêtes dans une boucle (N+1) : ne relancez pas une requête par élément affiché — préparez les données en amont.
  • no_found_rows => true : si vous n’avez pas besoin de la pagination totale, cet argument évite un COUNT(*) coûteux.
  • fields => 'ids' : ne récupérer que les IDs quand c’est suffisant, plus léger.
  • Le cache : les résultats sont mis en cache objet (ch. 5.7) ; sur des requêtes lourdes récurrentes, un transient peut aider.

📚 Aller plus loinWP_Query accepte des dizaines d’arguments (dates, post__in, post_parent, meta_key pour tri, fields, update_post_meta_cache…). Consultez la doc du cœur ; mais la règle d’or perf tient en une phrase : ne demandez que ce dont vous avez besoin (bons post_type, posts_per_page, fields, no_found_rows).


✏️ Exercices

  1. Écrivez les arguments d’un WP_Query pour « les 5 derniers articles publiés du type livre, triés par date décroissante ».
  2. Vous voulez afficher 12 éléments par page sur les archives. Pourquoi utiliser pre_get_posts plutôt qu’un new WP_Query dans le template ?
  3. Citez deux raisons pour lesquelles posts_per_page => -1 est risqué.

✅ Solution

$args = array( 'post_type' => 'livre', 'post_status' => 'publish', 'posts_per_page' => 5, 'orderby' => 'date', 'order' => 'DESC', );
  1. Parce que la page a déjà une main query (pagination, contexte, SEO) ; pre_get_posts ajuste cette requête existante (pagination correcte, une seule requête). Un new WP_Query dans le template crée une requête en double, casse la pagination native et le contexte.
  2. Il charge tous les contenus en mémoire (risque de dépassement mémoire / lenteur) et empêche toute pagination ; dangereux dès que le volume grandit.

🧠 Quiz de révision

1. À quoi sert WP_Query ?

À interroger les contenus (wp_posts) via des arguments déclaratifs, sans écrire de SQL.

2. Comment modifier la requête de la page en cours proprement ?

Via le hook pre_get_posts, en ciblant is_main_query() et ! is_admin().

3. Que filtrent meta_query et tax_query ?

meta_query filtre sur les métadonnées (wp_postmeta) ; tax_query sur les taxonomies.

4. Pourquoi les meta_query peuvent-elles être lentes ?

Elles impliquent des jointures sur wp_postmeta (modèle EAV), coûteuses à grande échelle.

5. Quel argument évite un COUNT(*) inutile ?

no_found_rows => true (quand la pagination totale n’est pas nécessaire).


Chapitre suivant : Base de données : $wpdb.