Wesentliche Frage
Lassen Sie uns graben sich in das Trio: ::query_posts, ::get_postsund class WP_Queryzu verstehen , ::query_postsbesser.
Der Grundstein für das Abrufen der Daten in WordPress ist die WP_QueryKlasse. Beide Methoden ::query_postsund ::get_postsverwenden diese Klasse.
Beachten Sie, dass die Klasse WP_Queryauch die Methoden mit demselben Namen enthält: WP_Query::query_postsund WP_Query::get_posts, aber wir berücksichtigen eigentlich nur die globalen Methoden, damit Sie nicht verwirrt werden.

Das verstehen WP_Query
Die Klasse mit dem Namen WP_Querywurde bereits 2004 eingeführt. Alle Felder mit der Markierung ☂ (Regenschirm) waren bereits 2004 vorhanden. Die zusätzlichen Felder wurden später hinzugefügt.
Hier ist die WP_QueryStruktur:
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 ist das Schweizer Taschenmesser.
Einige Dinge über WP_Query:
- Dies können Sie über Argumente steuern, die Sie übergeben
- es ist standardmäßig gierig
- es enthält die Substanz zum Schleifen
- es wird im globalen Raum x2 gespeichert
- es kann primär oder sekundär sein
- Es werden Hilfsklassen verwendet
- Es hat einen praktischen
pre_get_postsHaken
- Es unterstützt sogar verschachtelte Schleifen
- Es enthält die SQL-Abfragezeichenfolge
- Es enthält die Anzahl der Ergebnisse
- es hält die Ergebnisse
- Es enthält die Liste aller möglichen Abfrageargumente
- Es enthält die Vorlagenflags
- ...
Ich kann das alles nicht erklären, aber einige davon sind schwierig, also geben wir kurze Tipps.
WP_Query können Sie über Argumente steuern, die Sie übergeben
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
Diese Liste von WordPress Version 4.7 wird sich in Zukunft sicherlich ändern.
Dies wäre das minimale Beispiel, bei dem das WP_QueryObjekt aus den Argumenten erstellt wird:
// 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 ist gierig
get all you canEntwickelt auf der Idee, WordPress-Entwickler beschlossen, alle möglichen Daten frühzeitig zu erhalten, da dies gut für die Leistung ist . Wenn die Abfrage 10 Posts aus der Datenbank entnimmt, werden daher standardmäßig auch die Begriffe und die Metadaten für diese Posts über separate Abfragen abgerufen. Begriffe und Metadaten werden zwischengespeichert (Prefetch).
Beachten Sie, dass das Zwischenspeichern nur für die Lebensdauer einer einzelnen Anforderung gilt.
Sie können die Caching deaktivieren , wenn Sie festgelegt update_post_meta_cacheund update_post_term_cachezu , falsewährend die Einstellung WP_QueryArgumente. Wenn die Zwischenspeicherung deaktiviert ist, werden die Daten nur bei Bedarf aus der Datenbank angefordert.
Bei den meisten WordPress-Blogs funktioniert das Zwischenspeichern gut, aber es kann vorkommen, dass Sie das Zwischenspeichern deaktivieren.
WP_Query verwendet Hilfsklassen
Wenn Sie dort WP_QueryFelder markiert haben, haben Sie diese drei:
public $tax_query;
public $meta_query;
public $date_query;
Sie können sich vorstellen, in Zukunft neue hinzuzufügen.

WP_Query Enthält die Substanz zum Looping
In diesem Code:
$query = new WP_Query( $args )
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
Möglicherweise stellen Sie fest, dass WP_Querydie Substanz, die Sie iterieren können, vorhanden ist. Die Hilfsmethoden gibt es auch. Sie stellen gerade die whileSchleife ein.
Hinweis. forund whileSchleifen sind semantisch äquivalent.
WP_Query primär und sekundär
In WordPress haben Sie eine primäre und keine oder mehrere sekundäre Abfragen.
Es ist möglich, dass die primäre Abfrage nicht vorhanden ist, dies würde jedoch den Rahmen dieses Artikels sprengen.
Primäre Abfrage, die als Hauptabfrage oder reguläre Abfrage bezeichnet wird . Sekundäre Abfrage wird auch als benutzerdefinierte Abfrage bezeichnet .
WordPress verwendet WP_RewriteClass Early, um die Abfrageargumente basierend auf der URL zu erstellen. Basierend auf diesen Argumenten speichert es die zwei identischen Objekte im globalen Raum. Beide enthalten die Hauptabfrage.
global $wp_query @since WordPress 1.5
global $wp_the_query @since WordPress 2.1
Wenn wir main query sagen , denken wir an diese Variablen. Andere Abfragen können als sekundär oder benutzerdefiniert bezeichnet werden.
Es ist völlig legal, entweder global $wp_queryoder zu verwenden $GLOBALS['wp_query'], aber die Verwendung der zweiten Notation ist viel bemerkenswerter und erspart das Eingeben einer zusätzlichen Zeile innerhalb des Funktionsumfangs.
$GLOBALS['wp_query']und $GLOBALS['wp_the_query']sind separate Objekte. $GLOBALS['wp_the_query']sollte eingefroren bleiben.
WP_Queryhat den praktischen pre_get_postsHaken.
Dies ist der Aktionshaken. Es gilt für jede WP_Query Instanz. Du nennst es so:
add_action( 'pre_get_posts', function($query){
if ( is_category() && $query->is_main_query() ) {
// set your improved arguments
$query->set( ... );
...
}
return $query;
});
Dieser Hook ist großartig und kann beliebige Abfrageargumente ändern.
Folgendes können Sie lesen :
Wird ausgelöst, nachdem das Abfragevariablenobjekt erstellt wurde, aber bevor die eigentliche Abfrage ausgeführt wird.
Dieser Hook ist also Argument-Manager, kann jedoch keine neuen WP_QueryObjekte erstellen . Wenn Sie eine primäre und eine sekundäre Abfrage hatten, pre_get_postskönnen Sie die dritte nicht erstellen. Oder wenn Sie nur eine primäre hatten, kann sie die sekundäre nicht erstellen.
Beachten Sie, dass Sie den requestHook auch verwenden können, falls Sie nur die Hauptabfrage ändern müssen .
WP_Query unterstützt verschachtelte Schleifen
Dieses Szenario kann auftreten, wenn Sie Plugins verwenden und Plugin-Funktionen aus der Vorlage aufrufen.
Hier ist das Vorzeigebeispiel, in dem WordPress auch für verschachtelte Schleifen Hilfsfunktionen bietet:
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;
Die Ausgabe sieht folgendermaßen aus, da ich die Testdaten für die Themeneinheit installiert habe :
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!
Obwohl ich 5 Posts in der benutzerdefinierten $ query angefordert habe, werden mir sechs zurückgegeben, da der klebrige Post mitgeht. Wenn es wp_reset_postdataim vorherigen Beispiel keine gibt, ist die Ausgabe wie folgt, da $GLOBALS['post']sie ungültig ist.
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_Queryhat wp_reset_queryFunktion
Dies ist wie eine Reset-Taste. $GLOBALS['wp_the_query']sollte die ganze Zeit eingefroren sein und Plugins oder Themes sollten es niemals ändern.
Hier ist was zu wp_reset_querytun:
function wp_reset_query() {
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
wp_reset_postdata();
}
Bemerkungen zu get_posts
get_posts sieht aus wie
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);
Die Zeilennummern können sich in Zukunft ändern.
Es ist nur ein Wrapper um , WP_Querydass kehrt die Abfrageobjekt Beiträge.
Der ignore_sticky_postsWert true bedeutet, dass die klebrigen Pfosten möglicherweise nur in einer natürlichen Position angezeigt werden. Es gibt keine klebrigen Pfosten in der Front. Die andere no_found_rowsEinstellung auf true bedeutet, dass die WordPress-Datenbank-API keine SQL_CALC_FOUND_ROWSPaginierung implementiert und die Datenbank weniger belastet, um die Anzahl der gefundenen Zeilen auszuführen .
Dies ist praktisch, wenn Sie keine Paginierung benötigen. Wir verstehen jetzt, dass wir diese Funktion mit dieser Abfrage nachahmen können:
$args = array ( 'ignore_sticky_posts' => true, 'no_found_rows' => true);
$query = new WP_Query( $args );
print( $query->request );
Hier ist die entsprechende SQL-Anfrage:
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
Vergleichen Sie das, was wir jetzt haben, mit der vorherigen SQL-Anforderung, sofern SQL_CALC_FOUND_ROWSvorhanden.
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
Die Anfrage ohne SQL_CALC_FOUND_ROWSwird schneller sein.
Bemerkungen zu query_posts
Tipp: Anfangs gab es 2004 nur global $wp_query. Ab WordPress 2.1 $wp_the_querykam die Version . Tipp: $GLOBALS['wp_query']und $GLOBALS['wp_the_query']sind separate Objekte.
query_posts()ist WP_QueryWrapper. Es gibt die Referenz auf das WP_QueryHauptobjekt zurück und setzt gleichzeitig die global $wp_query.
File: /wp-includes/query.php
function query_posts($args) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
In PHP4 wurde alles, einschließlich der Objekte, als Wert übergeben. query_postswar wie folgt:
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);
}
Bitte beachten Sie, dass in einem typischen Szenario mit einer primären und einer sekundären Abfrage diese drei Variablen vorliegen:
$GLOBALS['wp_the_query']
$GLOBALS['wp_query'] // should be the copy of first one
$custom_query // secondary
Angenommen, jeder dieser drei Speicher benötigt 1 MB Speicher. Insgesamt wären 3M Speicher. Wenn wir verwenden query_posts, $GLOBALS['wp_query']wird nicht gesetzt und neu erstellt.
PHP5 + sollte intelligent sein, um das $GLOBALS['wp_query']Objekt zu leeren, genau wie in PHP4, in dem wir es gemacht habenunset($GLOBALS['wp_query']);
function query_posts($args) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
Infolgedessen werden query_postsinsgesamt 2 MB Arbeitsspeicher und get_posts3 MB Arbeitsspeicher verbraucht.
Beachten Sie, dass query_postswir nicht das eigentliche Objekt zurücksenden, sondern einen Verweis auf das Objekt.
Von php.net : Eine PHP-Referenz ist ein Alias, mit dem zwei verschiedene Variablen auf denselben Wert schreiben können. Ab PHP 5 enthält eine Objektvariable das Objekt selbst nicht mehr als Wert. Es enthält nur eine Objektkennung, mit der Objektzugriffsberechtigte das tatsächliche Objekt finden können. Wenn ein Objekt als Argument gesendet, zurückgegeben oder einer anderen Variablen zugewiesen wird, sind die verschiedenen Variablen keine Aliase: Sie enthalten eine Kopie des Bezeichners, der auf dasselbe Objekt verweist.
Auch in PHP5 + ist der Assign (=) - Operator klug. Es werden flache Kopien und keine Ausdrucke verwendet. Wenn wir so schreiben, werden $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];nur die Daten kopiert, nicht das gesamte Objekt, da diese den gleichen Objekttyp haben.
Hier ist ein Beispiel
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'] ) ) );
Wird ergeben:
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
d6db1c6bfddac328442e91b6059210b5
Versuchen Sie die Abfrage zurückzusetzen:
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'] ) ) );
Wird ergeben:
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
Sie können Probleme erstellen, auch wenn Sie verwenden 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'] ) ) );
Die Lösung wäre natürlich, die wp_reset_queryFunktion wieder zu verwenden.
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'] ) ) );
Dies ist der Grund, warum ich denke, query_postsdass es vom Standpunkt des Gedächtnisses aus vielleicht besser ist. Aber du solltest immer einen wp_reset_queryTrick machen.