回答:
トリオを掘り下げましょう:::query_posts
、::get_posts
そしてよりよくclass WP_Query
理解する::query_posts
ために。
WordPressでデータを取得するための基礎はWP_Query
クラスです。両方のメソッド::query_posts
と::get_posts
そのクラスを使用します。
クラスに
WP_Query
は同じ名前のメソッドも含まれていることに注意してください:WP_Query::query_posts
とWP_Query::get_posts
ですが、実際にはグローバルメソッドのみを考慮しているため、混同しないでください。
WP_Query
呼び出されたクラス
WP_Query
は2004年に導入されました。2004年に存在するすべてのフィールドにmark(傘)マークが付いています。追加のフィールドは後で追加されました。
ここにあるWP_Query
構造は:
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
スイスアーミーナイフです。いくつかのこと WP_Query
:
pre_get_posts
フックがありますこれらすべてを説明することはできませんが、これらのいくつかは扱いにくいので、短いヒントを提供しましょう。
WP_Query
渡す引数を介して制御できるものです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
WordPressバージョン4.7のこのリストは、将来的に変更されることは確かです。
これはWP_Query
、引数からオブジェクトを作成する最小限の例です。
// 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
貪欲ですget all you can
WordPress開発者はアイデアに基づいて作成されたため、パフォーマンスに優れているため、可能な限りすべてのデータを早期に取得することにしました。これが、デフォルトでクエリがデータベースから10個の投稿を取得するときに、別のクエリを介してこれらの投稿の用語とメタデータも取得する理由です。用語とメタデータはキャッシュされます(プリフェッチされます)。
キャッシングは、単一のリクエストライフタイムのためのものです。
あなたが設定されている場合は、キャッシュを無効にすることができますupdate_post_meta_cache
し、update_post_term_cache
にfalse
設定しながら、WP_Query
議論を。キャッシュが無効になっている場合、データはオンデマンドでのみデータベースから要求されます。
大部分のWordPressブログではキャッシュがうまく機能しますが、キャッシュを無効にできる場合があります。
WP_Query
ヘルパークラスを使用しますWP_Query
そこでフィールドをチェックした場合、次の3つがあります。
public $tax_query;
public $meta_query;
public $date_query;
将来的に新しいものを追加することを想像できます。
WP_Query
ループするための物質を保持しますこのコードでは:
$query = new WP_Query( $args )
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
あなたはWP_Query
反復することができる物質を持っていることに気付くかもしれません。ヘルパーメソッドもあります。while
ループを設定するだけです。
注意。
for
そしてwhile
ループは意味的に等価です。
WP_Query
一次および二次WordPressには、1つのプライマリクエリと0個以上のセカンダリクエリがあります。
プライマリクエリを持たないことも可能ですが、これはこの記事の範囲外です。
メインクエリまたは通常のクエリと呼ばれるプライマリクエリ。セカンダリクエリは、カスタムクエリとも呼ばれます。
WordPressはWP_Rewrite
クラスを早期に使用して、URLに基づいてクエリ引数を作成します。これらの引数に基づいて、2つの同一のオブジェクトをグローバルスペースに保存します。これらは両方ともメインクエリを保持します。
global $wp_query @since WordPress 1.5
global $wp_the_query @since WordPress 2.1
メインクエリを言うとき、これらの変数を考えます。他のクエリは、セカンダリまたはカスタムと呼ばれます。
global $wp_query
またはの いずれかを使用することは完全に合法です$GLOBALS['wp_query']
が、2番目の表記を使用する方がはるかに注目に値し、関数のスコープ内に余分な行を入力する手間が省けます。
$GLOBALS['wp_query']
と$GLOBALS['wp_the_query']
は別のオブジェクトです。$GLOBALS['wp_the_query']
凍結したままにしてください。
WP_Query
便利なpre_get_posts
フックがあります。これがアクションフックです。すべての WP_Query
インスタンスに適用されます。次のように呼び出します:
add_action( 'pre_get_posts', function($query){
if ( is_category() && $query->is_main_query() ) {
// set your improved arguments
$query->set( ... );
...
}
return $query;
});
このフックは優れており、クエリ引数を変更できます。
クエリ変数オブジェクトが作成された後、実際のクエリが実行される前に発生します。
したがって、このフックは引数マネージャーですが、新しいWP_Query
オブジェクトを作成できません。1つのプライマリクエリと1つのセカンダリクエリpre_get_posts
がある場合、3番目のクエリを作成できません。または、プライマリが1つだけの場合は、セカンダリを作成できません。
メインクエリを変更する必要がある場合のみ、
request
フックも使用できることに注意してください。
WP_Query
ネストされたループをサポートこのシナリオは、プラグインを使用し、テンプレートからプラグイン関数を呼び出す場合に発生する可能性があります。
以下は、WordPressがネストされたループに対してもヘルパー関数を持っているショーケースの例です。
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;
テーマユニットテストデータをインストールしたため、出力は次のようになります。
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!
カスタムの$ queryで5つの投稿をリクエストしましたが、スティッキーな投稿が続くため、6つの投稿が返されます。wp_reset_postdata
前の例にない場合、出力は$GLOBALS['post']
無効になりますので、このようになります。
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
持っているwp_reset_query
機能をこれはリセットボタンのようなものです。$GLOBALS['wp_the_query']
常にフリーズする必要があり、プラグインまたはテーマはそれを決して変更しないでください。
ここに何がありwp_reset_query
ます:
function wp_reset_query() {
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
wp_reset_postdata();
}
get_posts
get_posts
のように見える
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);
行番号は将来変更される可能性があります。
それだけであるラッパーの周りのWP_Query
ことを返すクエリオブジェクトの記事。
ignore_sticky_posts
真の意味スティッキーポストへのセットが唯一の自然な位置に表示される場合があります。前面にスティッキーな投稿はありません。もう1 no_found_rows
つはtrueに設定すると、WordPressデータベースAPIがSQL_CALC_FOUND_ROWS
ページネーションを実装するために使用しないことを意味し、データベースの負荷を減らして、見つかった行を実行します数。
これは、ページネーションを必要としないときに便利です。このクエリでこの機能を模倣できることがわかりました。
$args = array ( 'ignore_sticky_posts' => true, 'no_found_rows' => true);
$query = new WP_Query( $args );
print( $query->request );
対応するSQL要求は次のとおりです。
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
現在の内容を、SQL_CALC_FOUND_ROWS
存在する以前のSQL要求と比較します。
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
なしのリクエストSQL_CALC_FOUND_ROWS
はより高速になります。
query_posts
ヒント:2004年の最初はのみでした
global $wp_query
。WordPress 2.1のバージョン$wp_the_query
が来ました。ヒント:$GLOBALS['wp_query']
と$GLOBALS['wp_the_query']
は別個のオブジェクトです。
query_posts()
あるWP_Query
ラッパー。メインWP_Query
オブジェクトへの参照を返し、同時にを設定しglobal $wp_query
ます。
File: /wp-includes/query.php
function query_posts($args) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
PHP4では、オブジェクトを含むすべてのものが値渡しされました。query_posts
このようなものでした:
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);
}
1つのプライマリクエリと1つのセカンダリクエリがある典型的なシナリオでは、次の3つの変数があることに注意してください。
$GLOBALS['wp_the_query']
$GLOBALS['wp_query'] // should be the copy of first one
$custom_query // secondary
これら3つのそれぞれが1Mのメモリを消費するとします。合計で3Mのメモリになります。を使用するとquery_posts
、$GLOBALS['wp_query']
設定が解除され、再度作成されます。
PHP5 +は$GLOBALS['wp_query']
、PHP4で行ったように、オブジェクトをスマートに空にする必要があります。unset($GLOBALS['wp_query']);
function query_posts($args) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($args);
}
その結果query_posts
、合計で2Mのメモリをget_posts
消費しますが、3Mのメモリを消費します。
query_posts
実際のオブジェクトを返すのではなく、オブジェクトへの参照を返すことに注意してください。
php.netから:PHPリファレンスはエイリアスであり、2つの異なる変数が同じ値に書き込むことができます。PHP 5以降、オブジェクト変数にはオブジェクト自体が値として含まれなくなりました。オブジェクトアクセサーが実際のオブジェクトを検索できるようにするオブジェクト識別子のみが含まれています。オブジェクトが引数によって送信、返される、または別の変数に割り当てられるとき、異なる変数はエイリアスではありません。それらは同じオブジェクトを指す識別子のコピーを保持します。
また、PHP5 +では、代入(=)演算子はスマートです。ハードオブジェクトコピーではなく、浅いコピーを使用します。このように記述
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
すると、データは同じオブジェクトタイプを共有するため、オブジェクト全体ではなくデータのみがコピーされます。
一例です
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'] ) ) );
結果:
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
d6db1c6bfddac328442e91b6059210b5
クエリをリセットしてください:
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'] ) ) );
結果:
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
使用しても問題が発生する可能性があります 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'] ) ) );
もちろん、解決策はwp_reset_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' ) );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
これがquery_posts
、メモリの観点からより良いと思う理由です。しかし、常にwp_reset_query
トリックを行う必要があります。
の廃止を提案するために、新しいtracチケット、チケット#36874を作成しました。query_posts()
。それが受け入れられるかどうかは良い質問のままです。
本当に大きな問題query_posts()
は、プラグインやテーマで今でも広く使用されていることです。なぜそれを決して使用しないのかというテーマについては本当に良い文章があります。ここでのWPSEに関する最も壮大な投稿は、次の投稿だと思います。
非推奨!==削除。そのため、非推奨query_posts()
にしても、低品質の開発者やWordPressを知らず、低品質のチュートリアルをガイドラインとして使用する一般の人々による使用は停止しません。人々が使うところだけでいくつかの証拠として、我々はまだここにどのように多くの質問を受けるんcaller_get_posts
でWP_Query
?これは、長年にわたって非推奨になっています。
ただし、廃止された関数と引数は、コア開発者が適切であると判断したときにいつでも削除できますがquery_posts()
、これは何百万ものサイトを破壊するため、ほとんど発生しません。そうです、おそらく完全に削除されることは決してないでしょうquery_posts()
-これはおそらく非推奨になることはほとんどないという事実につながる可能性があります。
ただし、これは出発点ですが、WordPressで何かを非推奨にしても使用を停止することはできません。
私が調達したチケットは現在クローズされており、4年前のチケットと重複しているとマークされています。まだリニューアルオープンとしては、オープンで未解決のまま。
コア開発者はこの古い忠実な小さな悪に固執しているようです。興味のある方、ここに4年前の複製チケットがあります
[やや暴言]
現時点で非難されているものはないというのが、現時点での根幹となる哲学です。非推奨の通知は、便利ですが、ある時点で関数が実際に削除されない場合は無視されます。WP_DEBUG
onで開発しない人が多く、実際の破損がなければ通知に気付かないでしょう。
OTOHハンド、この関数はgoto
ステートメントのようなものです。個人的には(予想よりも小さい定義のために)使用しgoto
ませんでしたが、デフォルトでは悪ではない状況を指し示す議論を理解できます。同じですquery_posts
ことが、にも当てはまります。これは、単純なループを作成するために必要なすべてのグローバルを設定する簡単な方法であり、ajaxまたはrest-apiコンテキストで役立ちます。私はそれらのコンテキストでも決して使用しませんが、そこでは、それはコーディングスタイルの問題であり、機能自体が悪であることがわかります。
もう少し深く進むと、主な問題はグローバルを設定する必要があることです。それが主な問題であり、設定に役立つ1つの機能ではありません。
query_posts
二次クエリよりも実際に遅いです(読み取り:メインクエリではありません)。
query_posts
それ自体ではなく、WPの読み込み時に行われた無用なクエリ