问题描述

我在 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。