私は奇妙な問題に遭遇しました。
ランダムなURLにアクセスしたとしましょう。3つ以上のレベルがあります。
http://example.com/a/b/c
http://example.com/a/b/c/d
...
is_404()
はtrue
です。ここまでは順調ですね。しかし、どういうわけか最後の投稿が問い合わせされています。
$wp_query->request
です
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, 5
もちろんこれはhave_posts()
がtrue
を返すようにします。誰かがこれを説明できますか?
私がこれまでに見つけたこと:
3つ以上のレベルで深く入り込むだけの理由は、その前にWPが投稿や添付ファイルを探すので、どういうわけか他の振る舞いをするからです。
WPはリクエストをある時点で404として認識していますが、最新の投稿を取得しているようです。 @kaiser および @ G.Mの助けを借りて。 これを /wp-includes/class-wp.php:608 からどこかに追跡しました。
あなたは驚くかもしれませんが、そこに奇妙なことは何もありません。
まず最初に、WordPressでフロントエンドのURLにアクセスしたときにクエリを起動することを明確にしましょう。常に。
そのクエリは、標準のWP_Query
です。
$query = new WP_Query( $args );
唯一の違いがあります:$args
変数は WP::parse_request()
メソッドを使ってWordPressによって生成されます。その方法は、URLと書き換え規則を見て、URLを引数の配列に変換するだけです。
しかし、URLが無効であるためにそのメソッドがそれを実行できない場合はどうなりますか? query argsはこのような単なる配列です。
array( 'error' => '404' );
そのため、その配列はWP_Query
に渡されます。
今やってみてください:
$query = new WP_Query( array( 'error' => '404' ) );
var_dump( $query->request );
あなたはクエリがまさにOPのものであることに驚いていますか?私は違います。
そう、
parse_request()
はエラーキーで配列を構築しますWP_Query
に渡され、それが実行されるだけです。handle_404()
クエリの後、'error'
パラメータを調べ、is_404()
をtrueに設定します。そのため、have_post()
とis_404()
は関係ありません。問題はWP_Query
が何か問題が発生したときにクエリをショートするシステムを持っていないことです。オブジェクトが構築されたら、それにいくつかの引数を渡してクエリを実行します。
編集:
この問題を解決するには2つの方法があります。
404.php
テンプレートを作成します。 WordPressはそれを404個のURLにロードするので、have_posts()
をチェックする必要はありません。404では$wp_query
を強制的に空にします。
add_action( 'wp', function() {
global $wp_query;
if ( $wp_query->is_404() ) {
$wp_query->init();
$wp_query->is_404 = true; // init() reset 404 too
}
} );