問題描述

我遇到了一個奇怪的問題。

説你訪問一個隨機 url,三個或更多的層次:

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 等等。有人可以解釋一下嗎

我發現到目前為止

只有三點或更多級別深入的原因是,在 WP 查找帖子和附件之前,這些結果會導致其他一些行為。

似乎即使 WP 在一點上將該請求識別為 404,然後獲取最新的帖子。在 @kaiser@G.M. 的幫助下,我已經將其跟蹤到了/wp-includes/class-wp.php:608 的某個地方

最佳解決方案

你可能會驚訝,但沒有什麼奇怪的。

首先讓我們澄清一下,在 WordPress 中,當您訪問前端 URL 時,您將觸發查詢。總是。

該查詢只是一個標準的 WP_Query,就像通過以下方式運行的那樣:

$query = new WP_Query( $args );

只有一個區別:$args 變量由 WordPress 使用 WP::parse_request()方法生成。該方法的作用是查看 URL,並重寫規則,並將 URL 轉換為參數數組。

但是,由於 URL 是 non-valid,那個方法不能做到這一點呢?查詢 args 只是一個這樣的數組:

array( 'error' => '404' );

(來源 herehere) 。

所以將該數組傳遞給 WP_Query

現在嘗試做:

$query = new WP_Query( array( 'error' => '404' ) );
var_dump( $query->request );

您是否驚訝於查詢完全是 OP 中的查詢?我不是。

所以,

  1. parse_request()構建一個帶有錯誤鍵的數組

  2. 該數組被傳遞給 WP_Query,它只是運行它

  3. 在查詢後運行的 handle_404(),查看'error'參數,並將 is_404()設置為 true

所以 have_post()is_404()是無關的。問題是 WP_Query 在出現錯誤時沒有向 short-circuit 詢問系統,所以一旦對象被建立,傳遞一些參數就可以運行查詢。

編輯:

有兩種方法來克服這個問題:

  • 創建 404.php 模板; WordPress 將加載 404 網址,您不需要檢查 have_posts()

  • 強制 $wp_query 在 404 上為空,類似於:

    add_action( 'wp', function() {
        global $wp_query;
        if ( $wp_query->is_404() ) {
            $wp_query->init();
            $wp_query->is_404 = true; // init() reset 404 too
        }
    } );
    

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。