問題描述

我在 WordPress 主題開發中是非常新的,我不是那麼在 PHP(我來自 Java 和 C#),並在 this custom theme 中有以下情況

正如你可以在首頁中看到的,我首先顯示一個包含特色帖子的部分 (名為 Articoli 的 evidenza)(我已經使用特定的標籤實現了),還有一個區域 (名為 Ultimi Articoli) 包含最新的帖子這不是特色的帖子。

要做到這一點我使用這個代碼:

<section id="blog-posts">

<header class="header-sezione">
        <h2>Articoli in evidenza</h2>
</header>

<!--<?php query_posts('tag=featured');?>-->



<?php
    $featured = new WP_Query('tag=featured');

    if ($featured->have_posts()) :
            while ($featured->have_posts()) : $featured->the_post();
            /*
             * Include the post format-specific template for the content. If you want to
             * use this in a child theme, then include a file called called content-___.php
             * (where ___ is the post format) and that will be used instead.
             */
            get_template_part('content', get_post_format());

        endwhile;
        wp_reset_postdata();
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
    ?>


<header class="header-sezione">
    <h2>Ultimi Articoli</h2>
</header>

<?
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>

<?php
    if (have_posts()) :
        // Start the Loop.
        while (have_posts()) : the_post();

            /*
             * Include the post format-specific template for the content. If you want to
             * use this in a child theme, then include a file called called content-___.php
             * (where ___ is the post format) and that will be used instead.
             */
            get_template_part('content', get_post_format());

        endwhile;
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
    ?>

</section>

它工作正常,但我對這個解決方案的質量有一些疑問,以及它的工作原理。

要選擇所有的特色帖子,我使用這一行創建一個新的 WP_Query 對象,定義具有特定標籤 featured 的查詢:

$featured = new WP_Query('tag=featured');

然後我使用它的 have_posts()方法迭代這個查詢結果。

所以,從我所理解的,這不是 WordPress 的主要查詢,但它是由我創建的一個新的查詢。從我的理解,最好創建一個新的查詢 (如完成),而不是使用主查詢,當我想執行這種操作。

是真的還是我錯過了什麼?如果是真的可以解釋一下,為什麼最好創建一個新的自定義查詢,而不是修改 Wordpress 主查詢?

好的,繼續我顯示所有沒有功能標籤的帖子,要做到這一點,我使用這個代碼片段,相反修改主要查詢:

    <?
    // get the term using the slug and the tag taxonomy
    $term = get_term_by( 'slug', 'featured', 'post_tag' );
    // pass the term_id to tag__not_in
    query_posts( array( 'tag__not_in' => array ( $term->term_id )));
    ?>

    <?php
        if (have_posts()) :
            // Start the Loop.
            while (have_posts()) : the_post();
get_template_part('content', get_post_format());

            endwhile;
        else :
            // If no content, include the "No posts found" template.
            get_template_part('content', 'none');

        endif;
        ?>

所以我覺得這很可怕是真的嗎

要做同樣的操作,我發現我已經添加到 functions.php 的這個函數

function exclude_featured_tag( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'tag__not_in', 'array(ID OF THE FEATURED TAG)' );
    }
}
add_action( 'pre_get_posts', 'exclude_featured_tag' );

此函數具有在創建查詢變量對象之後但在運行實際查詢之前調用的鈎子。

所以從我所理解的,它將一個查詢對象作為輸入參數,修改它選擇所有不包括特定標籤的帖子 (在我的例子中是 featured 標記帖子)

那麼如何使用以前的查詢 (用於顯示精選帖子的),這個功能可以在我的主題中顯示不是特色的帖子?還是要創建一個新的查詢?

最佳解決方案

您的實際問題基本上是何時運行自定義查詢,何時使用主查詢。讓我們分三部分

第一部分

何時運行自定義查詢 (這不是一個確定的列表)

  • 創建自定義內容滑塊

  • 在頁面中創建精選內容區域

  • 在 page.php 模板中,如果您需要顯示帖子

  • 如果您需要靜態首頁上的自定義內容

  • 顯示相關的,熱門的或信息的帖子

  • 主查詢範圍之外的任何其他輔助或補充內容

何時使用主查詢。

顯示主要內容

  • 在您的主頁上,頁面設置為後端的博客頁面

  • 所有歸檔頁面,包括 archive.php,category.php,author.php,taxonomy.php,tag.php 和 date.php

  • 更新:在真實頁面和靜態首頁上顯示自定義內容 (請參閲 Using pre_get_posts on true pages and static front pages)

第二部分

To select all the featured posts I use this line that create a new WP_Query object that define a query having the specific tag featured:

So, from what I have understand, this is not the WordPres main query but it is a new query created by me. From what I have understand it is better create a new query (as done) and not use the main query when I want perform this kind of operations

正確。這超出了主查詢的範圍。這是無法使用主查詢創建的輔助或補充內容。您應該始終使用 WP_Queryget_posts 來創建自定義查詢。

不要使用 query_posts 創建自定義查詢,甚至任何其他查詢。我的重點

Note: This function isn’t meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).

繼續

Ok, going on I show all the posts that have not the featured tag, to do this I use this code snippet that on the contrary modify the main query:

query_posts( array( 'tag__not_in' => array ( $term->term_id ))); 

So I think that this is pretty horrible. Is it true?

這是錯誤的,你的聲明是不幸的。如前所述,永遠不要使用 query_posts 。它運行一個完整的新查詢,這對於性能不利,大多數情況下會分頁,這是分頁正常工作的主要查詢的組成部分。

這是您的主要內容,因此您應該使用主查詢與默認循環,這應該是這樣,這就是你需要的

<?php
    if (have_posts()) :
        // Start the Loop.
        while (have_posts()) : the_post();

            get_template_part('content', get_post_format());

        endwhile;
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
?>

你可以完全擺脱這部分,刪除它,燒掉它並忘記它

<?
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>

好的,一旦你這樣做,你會看到功能標籤的帖子使用主查詢和默認循環顯示在你的主頁上。

從主頁上刪除該標籤的正確方法是使用 pre_get_posts 。這是更改主要查詢和鈎子的正確方法,您應該始終使用它來更改主內容循環。

所以 pre_get_posts 的代碼是正確的,這是你應該使用的函數。只要一件事,總是做一個檢查,你不在一個管理頁面,因為 pre_get_posts 也改變了後端。所以這是在 functions.php 中使用的正確的代碼來刪除從主頁標記的帖子

add_action( 'pre_get_posts', 'exclude_featured_tag' );
function exclude_featured_tag( $query )
{
    if (    !is_admin()
         && $query->is_home()
         && $query->is_main_query()
    ) {
        $query->set( 'tag__not_in', [ID OF THE FEATURED TAG] );
    }
}

第三部分

額外的閲讀材料將來會有所幫助

參考文獻

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