Question essentielle
La fouille Let dans le trio: ::query_posts, ::get_postset class WP_Queryde comprendre ::query_postsmieux.
La pierre angulaire pour obtenir les données dans WordPress est la WP_Queryclasse. Les deux méthodes ::query_postset ::get_postsutilisent cette classe.
Notez que la classe WP_Querycontient également les méthodes du même nom: WP_Query::query_postset WP_Query::get_posts, mais nous ne considérons en fait que les méthodes globales, alors ne vous trompez pas.

Comprendre le WP_Query
La classe appelée WP_Querya été introduite en 2004. Tous les champs portant la marque ☂ (parapluie) étaient présents en 2004. Les champs supplémentaires ont été ajoutés ultérieurement.
Voici la WP_Querystructure:
class WP_Query (as in WordPress v4.7)
public $query; ☂
public $query_vars = array(); ☂
public $tax_query;
public $meta_query = false;
public $date_query = false;
public $queried_object; ☂
public $queried_object_id; ☂
public $request;
public $posts; ☂
public $post_count = 0; ☂
public $current_post = -1; ☂
public $in_the_loop = false;
public $post; ☂
public $comments;
public $comment_count = 0;
public $current_comment = -1;
public $comment;
public $found_posts = 0;
public $max_num_pages = 0;
public $max_num_comment_pages = 0;
public $is_single = false; ☂
public $is_preview = false; ☂
public $is_page = false; ☂
public $is_archive = false; ☂
public $is_date = false; ☂
public $is_year = false; ☂
public $is_month = false; ☂
public $is_day = false; ☂
public $is_time = false; ☂
public $is_author = false; ☂
public $is_category = false; ☂
public $is_tag = false;
public $is_tax = false;
public $is_search = false; ☂
public $is_feed = false; ☂
public $is_comment_feed = false;
public $is_trackback = false; ☂
public $is_home = false; ☂
public $is_404 = false; ☂
public $is_embed = false;
public $is_paged = false;
public $is_admin = false; ☂
public $is_attachment = false;
public $is_singular = false;
public $is_robots = false;
public $is_posts_page = false;
public $is_post_type_archive = false;
private $query_vars_hash = false;
private $query_vars_changed = true;
public $thumbnails_cached = false;
private $stopwords;
private $compat_fields = array('query_vars_hash', 'query_vars_changed');
private $compat_methods = array('init_query_flags', 'parse_tax_query');
private function init_query_flags()
WP_Query est le couteau suisse.
Quelques points sur WP_Query:
- c'est quelque chose que vous pouvez contrôler via les arguments que vous passez
- c'est gourmand par défaut
- il contient la substance pour boucler
- il est enregistré dans l'espace global x2
- il peut être primaire ou secondaire
- il utilise des classes d'assistance
- il a un
pre_get_postscrochet pratique
- il prend même en charge les boucles imbriquées
- il contient la chaîne de requête SQL
- il contient le nombre de résultats
- il détient les résultats
- il contient la liste de tous les arguments de requête possibles
- il contient les drapeaux de modèle
- ...
Je ne peux pas expliquer tout cela, mais certains d'entre eux sont délicats, alors fournissons de courts conseils.
WP_Query est quelque chose que vous pouvez contrôler via les arguments que vous passez
The list of the arguments
---
attachment
attachment_id
author
author__in
author__not_in
author_name
cache_results
cat
category__and
category__in
category__not_in
category_name
comments_per_page
day
embed
error
feed
fields
hour
ignore_sticky_posts
lazy_load_term_meta
m
menu_order
meta_key
meta_value
minute
monthnum
name
no_found_rows
nopaging
order
p
page_id
paged
pagename
post__in
post__not_in
post_name__in
post_parent
post_parent__in
post_parent__not_in
post_type
posts_per_page
preview
s
second
sentence
static
subpost
subpost_id
suppress_filters
tag
tag__and
tag__in
tag__not_in
tag_id
tag_slug__and
tag_slug__in
tb
title
update_post_meta_cache
update_post_term_cache
w
year
Cette liste de WordPress version 4.7 va certainement changer à l'avenir.
Ce serait l'exemple minimal de création de l' WP_Queryobjet à partir des arguments:
// WP_Query arguments
$args = array ( /* arguments*/ );
// creating the WP_Query object
$query = new WP_Query( $args );
// print full list of arguments WP_Query can take
print ( $query->query_vars );
WP_Query est gourmand
Créés sur l'idée, les get all you candéveloppeurs WordPress ont décidé d'obtenir toutes les données possibles le plus tôt possible, car cela est bon pour les performances . C'est pourquoi par défaut, lorsque la requête prend 10 articles de la base de données, elle obtiendra également les termes et les métadonnées de ces articles via des requêtes distinctes. Les termes et métadonnées seront mis en cache (prélecture).
Notez que la mise en cache est juste pour la durée de vie d'une seule demande.
Vous pouvez désactiver la mise en cache si vous définissez update_post_meta_cacheet update_post_term_cachesur falselors de la définition des WP_Queryarguments. Lorsque la mise en cache est désactivée, les données ne seront demandées à la base de données que sur demande.
Pour la majorité des blogs WordPress, la mise en cache fonctionne bien, mais il peut arriver que vous désactiviez la mise en cache.
WP_Query utilise des classes d'assistance
Si vous avez coché les WP_Querychamps, vous avez les trois suivants:
public $tax_query;
public $meta_query;
public $date_query;
Vous pouvez imaginer en ajouter de nouveaux à l'avenir.

WP_Query détient la substance pour boucler
Dans ce code:
$query = new WP_Query( $args )
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
vous remarquerez peut-être la WP_Querysubstance que vous pouvez parcourir. Les méthodes d'assistance existent également. Vous venez de définir la whileboucle.
Remarque. foret les whileboucles sont sémantiquement équivalentes.
WP_Query primaire et secondaire
Dans WordPress, vous avez une requête principale et zéro ou plusieurs requêtes secondaires .
Il est possible de ne pas avoir la requête principale, mais cela dépasse le cadre de cet article.
Requête principale connue sous le nom de requête principale ou requête régulière . La requête secondaire est également appelée requête personnalisée .
WordPress utilise la WP_Rewriteclasse tôt pour créer les arguments de requête basés sur l'URL. Sur la base de ces arguments, il stocke les deux objets identiques dans l'espace global. Les deux contiendront la requête principale.
global $wp_query @since WordPress 1.5
global $wp_the_query @since WordPress 2.1
Lorsque nous disons requête principale, nous pensons à ces variables. D'autres requêtes peuvent être appelées secondaires ou personnalisées.
Il est tout à fait légal d'utiliser soit global $wp_queryou $GLOBALS['wp_query'], mais l'utilisation de la deuxième notation est beaucoup plus notable et évite de taper une ligne supplémentaire à l'intérieur de la portée des fonctions.
$GLOBALS['wp_query']et $GLOBALS['wp_the_query']sont des objets séparés. $GLOBALS['wp_the_query']devrait rester gelé.
WP_Querya le pre_get_postscrochet pratique .
Ceci est le crochet d'action. Il s'appliquera à toute WP_Query instance. Vous l'appelez comme:
add_action( 'pre_get_posts', function($query){
if ( is_category() && $query->is_main_query() ) {
// set your improved arguments
$query->set( ... );
...
}
return $query;
});
Ce crochet est génial et il peut modifier tous les arguments de requête.
Voici ce que vous pouvez lire :
Se déclenche après la création de l'objet variable de requête, mais avant l'exécution de la requête réelle.
Ce crochet est donc le gestionnaire d'arguments mais ne peut pas créer de nouveaux WP_Queryobjets. Si vous aviez une requête principale et une requête secondaire, pre_get_postsvous ne pouvez pas créer la troisième. Ou si vous venez d'avoir un primaire, il ne peut pas créer le secondaire.
Notez que si vous devez modifier la requête principale, vous pouvez également utiliser le requesthook.
WP_Query prend en charge les boucles imbriquées
Ce scénario peut se produire si vous utilisez des plugins et que vous appelez des fonctions de plugin à partir du modèle.
Voici l'exemple de vitrine WordPress a des fonctions d'assistance même pour les boucles imbriquées:
global $id;
while ( have_posts() ) : the_post();
// the custom $query
$query = new WP_Query( array( 'posts_per_page' => 5 ) );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) : $query->the_post();
echo '<li>Custom ' . $id . '. ' . get_the_title() . '</li>';
endwhile;
}
wp_reset_postdata();
echo '<li>Main Query ' . $id . '. ' . get_the_title() . '</li>';
endwhile;
La sortie sera comme ceci depuis que j'ai installé les données de test d'unité de thème :
Custom 100. Template: Sticky
Custom 1. Hello world!
Custom 10. Markup: HTML Tags and Formatting
Custom 11. Markup: Image Alignment
Custom 12. Markup: Text Alignment
Custom 13. Markup: Title With Special Characters
Main Query 1. Hello world!
Même si j'ai demandé 5 messages dans la requête $ personnalisée, il m'en retournera six, car le message collant ira de pair. S'il n'y en a pas wp_reset_postdatadans l'exemple précédent, la sortie sera comme ceci, car elle $GLOBALS['post']ne sera pas valide.
Custom 1001. Template: Sticky
Custom 1. Hello world!
Custom 10. Markup: HTML Tags and Formatting
Custom 11. Markup: Image Alignment
Custom 12. Markup: Text Alignment
Custom 13. Markup: Title With Special Characters
Main Query 13. Markup: Title With Special Characters
WP_Querya une wp_reset_queryfonction
C'est comme un bouton de réinitialisation. $GLOBALS['wp_the_query']devrait être gelé tout le temps, et les plugins ou les thèmes ne devraient jamais le modifier.
Voici ce que wp_reset_queryfont:
function wp_reset_query() {
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
wp_reset_postdata();
}
Remarques sur get_posts
get_posts ressemble à
File: /wp-includes/post.php
1661: function get_posts( $args = null ) {
1662: $defaults = array(
1663: 'numberposts' => 5,
1664: 'category' => 0, 'orderby' => 'date',
1665: 'order' => 'DESC', 'include' => array(),
1666: 'exclude' => array(), 'meta_key' => '',
1667: 'meta_value' =>'', 'post_type' => 'post',
1668: 'suppress_filters' => true
1669: );
... // do some argument parsing
1685: $r['ignore_sticky_posts'] = true;
1686: $r['no_found_rows'] = true;
1687:
1688: $get_posts = new WP_Query;
1689: return $get_posts->query($r);
Les numéros de ligne peuvent changer à l'avenir.
Il est juste un wrapper autour WP_Queryque le rendement des messages de l' objet de la requête.
La valeur ignore_sticky_poststrue signifie que les poteaux collants peuvent apparaître uniquement dans une position naturelle. Il n'y aura pas de poteaux collants à l'avant. L'autre valeur no_found_rowstrue signifie que l'API de base de données WordPress ne sera pas utilisée SQL_CALC_FOUND_ROWSpour implémenter la pagination, réduisant ainsi la charge sur la base de données pour exécuter le nombre de lignes trouvées .
C'est pratique lorsque vous n'avez pas besoin de pagination. Nous comprenons maintenant que nous pouvons imiter cette fonction avec cette requête:
$args = array ( 'ignore_sticky_posts' => true, 'no_found_rows' => true);
$query = new WP_Query( $args );
print( $query->request );
Voici la requête SQL correspondante:
SELECT wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10
Comparez ce que nous avons maintenant avec la requête SQL précédente où elle SQL_CALC_FOUND_ROWSexiste.
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10
La demande sans SQL_CALC_FOUND_ROWSsera plus rapide.
Remarques sur query_posts
Astuce: au début en 2004, il y en avait seulement global $wp_query. À partir de la version WordPress 2.1 est $wp_the_queryarrivée. Astuce: $GLOBALS['wp_query']et $GLOBALS['wp_the_query']sont des objets séparés.
query_posts()est WP_Querywrapper. Il renvoie la référence à l' WP_Queryobjet principal et en même temps, il définit le global $wp_query.
File: /wp-includes/query.php
function query_posts($args) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
En PHP4, tout, y compris les objets, était passé par valeur. query_postsétait comme ça:
File: /wp-includes/query.php (WordPress 3.1)
function &query_posts($args) {
unset($GLOBALS['wp_query']);
$GLOBALS['wp_query'] =& new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
Veuillez noter que dans un scénario typique avec une requête principale et une requête secondaire, nous avons ces trois variables:
$GLOBALS['wp_the_query']
$GLOBALS['wp_query'] // should be the copy of first one
$custom_query // secondary
Disons que chacun de ces trois prend 1M de mémoire. Le total serait de 3 m de mémoire. Si nous utilisons query_posts, $GLOBALS['wp_query']sera non défini et créé à nouveau.
PHP5 + devrait être intelligent en vidant l' $GLOBALS['wp_query']objet, tout comme en PHP4 nous l'avons fait avec leunset($GLOBALS['wp_query']);
function query_posts($args) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
Par conséquent, query_postsconsomme 2M de mémoire au total, tandis que get_postsconsomme 3 M de mémoire.
Notez que query_postsnous ne retournons pas l'objet réel, mais une référence à l'objet.
De php.net : Une référence PHP est un alias, qui permet à deux variables différentes d'écrire sur la même valeur. Depuis PHP 5, une variable objet ne contient plus l'objet lui-même comme valeur. Il contient uniquement un identifiant d'objet qui permet aux accesseurs d'objet de trouver l'objet réel. Lorsqu'un objet est envoyé par argument, retourné ou affecté à une autre variable, les différentes variables ne sont pas des alias: elles contiennent une copie de l'identifiant, qui pointe vers le même objet.
Également en PHP5 +, l'opérateur assign (=) est intelligent. Il utilisera une copie superficielle et non une copie d'objet dur. Lorsque nous écrivons comme ceci, $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];seules les données seront copiées, pas l'objet entier car ceux-ci partagent le même type d'objet.
Voici un exemple
print( md5(serialize($GLOBALS['wp_the_query']) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
query_posts( '' );
print( md5(serialize($GLOBALS['wp_the_query']) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
Résultera:
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
d6db1c6bfddac328442e91b6059210b5
Essayez de réinitialiser la requête:
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
query_posts( '' );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
Résultera:
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
Vous pouvez créer des problèmes même si vous utilisez WP_Query
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
global $wp_query;
$wp_query = new WP_Query( array( 'post_type' => 'post' ) );
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
Bien sûr, la solution serait de réutiliser la wp_reset_queryfonction.
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
global $wp_query;
$wp_query = new WP_Query( array( 'post_type' => 'post' ) );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
C'est pourquoi je pense que cela query_postspeut être mieux du point de vue de la mémoire. Mais vous devriez toujours faire des wp_reset_querytours.