Wesentliche Frage
Lassen Sie uns graben sich in das Trio: ::query_posts
, ::get_posts
und class WP_Query
zu verstehen , ::query_posts
besser.
Der Grundstein für das Abrufen der Daten in WordPress ist die WP_Query
Klasse. Beide Methoden ::query_posts
und ::get_posts
verwenden diese Klasse.
Beachten Sie, dass die Klasse WP_Query
auch die Methoden mit demselben Namen enthält: WP_Query::query_posts
und 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_Query
wurde 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_Query
Struktur:
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_posts
Haken
- 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_Query
Objekt 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 can
Entwickelt 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_cache
und update_post_term_cache
zu , false
während die Einstellung WP_Query
Argumente. 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_Query
Felder 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_Query
die Substanz, die Sie iterieren können, vorhanden ist. Die Hilfsmethoden gibt es auch. Sie stellen gerade die while
Schleife ein.
Hinweis. for
und while
Schleifen 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_Rewrite
Class 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_query
oder 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_Query
hat den praktischen pre_get_posts
Haken.
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_Query
Objekte erstellen . Wenn Sie eine primäre und eine sekundäre Abfrage hatten, pre_get_posts
kö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 request
Hook 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_postdata
im 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_Query
hat wp_reset_query
Funktion
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_query
tun:
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_Query
dass kehrt die Abfrageobjekt Beiträge.
Der ignore_sticky_posts
Wert 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_rows
Einstellung auf true bedeutet, dass die WordPress-Datenbank-API keine SQL_CALC_FOUND_ROWS
Paginierung 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_ROWS
vorhanden.
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_ROWS
wird schneller sein.
Bemerkungen zu query_posts
Tipp: Anfangs gab es 2004 nur global $wp_query
. Ab WordPress 2.1 $wp_the_query
kam die Version . Tipp: $GLOBALS['wp_query']
und $GLOBALS['wp_the_query']
sind separate Objekte.
query_posts()
ist WP_Query
Wrapper. Es gibt die Referenz auf das WP_Query
Hauptobjekt 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_posts
war 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_posts
insgesamt 2 MB Arbeitsspeicher und get_posts
3 MB Arbeitsspeicher verbraucht.
Beachten Sie, dass query_posts
wir 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_query
Funktion 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_posts
dass es vom Standpunkt des Gedächtnisses aus vielleicht besser ist. Aber du solltest immer einen wp_reset_query
Trick machen.