Question essentielle
La fouille Let dans le trio: ::query_posts
, ::get_posts
et class WP_Query
de comprendre ::query_posts
mieux.
La pierre angulaire pour obtenir les données dans WordPress est la WP_Query
classe. Les deux méthodes ::query_posts
et ::get_posts
utilisent cette classe.
Notez que la classe WP_Query
contient également les méthodes du même nom: WP_Query::query_posts
et 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_Query
a é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_Query
structure:
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_posts
crochet 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_Query
objet à 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 can
dé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_cache
et update_post_term_cache
sur false
lors de la définition des WP_Query
arguments. 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_Query
champs, 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_Query
substance que vous pouvez parcourir. Les méthodes d'assistance existent également. Vous venez de définir la while
boucle.
Remarque. for
et les while
boucles 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_Rewrite
classe 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_query
ou $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_Query
a le pre_get_posts
crochet 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_Query
objets. Si vous aviez une requête principale et une requête secondaire, pre_get_posts
vous 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 request
hook.
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_postdata
dans 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_Query
a une wp_reset_query
fonction
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_query
font:
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_Query
que le rendement des messages de l' objet de la requête.
La valeur ignore_sticky_posts
true 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_rows
true signifie que l'API de base de données WordPress ne sera pas utilisée SQL_CALC_FOUND_ROWS
pour 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_ROWS
existe.
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_ROWS
sera 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_query
arrivée. Astuce: $GLOBALS['wp_query']
et $GLOBALS['wp_the_query']
sont des objets séparés.
query_posts()
est WP_Query
wrapper. Il renvoie la référence à l' WP_Query
objet 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_posts
consomme 2M de mémoire au total, tandis que get_posts
consomme 3 M de mémoire.
Notez que query_posts
nous 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_query
fonction.
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_posts
peut être mieux du point de vue de la mémoire. Mais vous devriez toujours faire des wp_reset_query
tours.