有关主查询和自定义查询在此自定义主题中如何工作的一些疑问?


20

我是WordPress主题开发的新手,但对PHP的了解却不是这样(我来自Java和C#),并且在此自定义主题中存在以下情况

如您在主页上看到的,我首先显示一个部分(在evidenza中名为Articoli),其中包含精选帖子(我已经使用特定标签实现了该帖子),并且在其下还有另一个区域(名为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>

<?php
// 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主查询?

好的,继续。我将显示所有没有“功能”标签的帖子。为此,我使用以下代码片段,相反,它修改了主查询:

    <?php
    // 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标签)以外的所有帖子来修改(实际上过滤)它

因此,如何使用带有此功能的上一个查询(用于显示特色帖子的查询)仅显示主题中未特色的帖子?还是我必须创建一个新查询?

Answers:


33

您的实际问题基本上是何时运行自定义查询以及何时使用主查询。让我们分为三个部分

第一部分

何时运行自定义查询(这不是确定的列表)

  • 创建自定义内容滑块

  • 在页面中创建特色内容区域

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

  • 如果您需要静态首页上的自定义内容

  • 显示相关,热门或信息性帖子

  • 主查询范围之外的任何其他辅助或补充内容

何时使用主查询。

在上显示主要内容

  • 在您的主页上,并将该页面设置为后端中的博客页面

  • 所有存档页面,包括诸如archive.php,category.php,author.php,taxonomy.php,tag.php和date.php之类的模板

  • 更新:在真实页面和静态首页上显示自定义内容(请参阅在真实页面和静态首页上使用pre_get_posts

第二部分

要选择所有具有特色的帖子,我使用以下行来创建一个新的WP_Query对象,该对象定义具有具有特定标签特色的查询:

因此,据我了解,这不是WordPres主查询,而是由我创建的新查询。据我了解,最好是创建一个新查询(如已完成),并且当我要执行此类操作时不使用主查询

正确。这超出了主查询的范围。这是辅助查询或补充内容,无法使用主查询创建。您应该始终使用WP_Queryget_posts创建自定义查询。

切勿使用它 query_posts来创建自定义查询,甚至任何其他查询。我的重点。

注意:此功能并不旨在由插件或主题使用。如后面所述,有更好的,性能更高的选项可以更改主查询。query_posts()是通过将页面的主查询替换为新的查询实例来修改页面的主查询的过于简单和有问题的方式。它效率低下(重新运行SQL查询),并且在某些情况下(特别是在处理帖子分页时,通常会完全失败)。

继续

好的,继续,我显示所有没有featured标签的帖子,为此,我使用此代码段,相反,该代码段修改了主查询:

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

所以我认为这太可怕了。是真的吗

完全错误,您的陈述很遗憾是正确的。如前所述,切勿使用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 )));
?>

好的,一旦完成,您将看到来自feature标签的帖子使用主查询和默认循环显示在您的主页中。

从首页删除此标签的正确方法是使用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] );
    }
}

第三部分

额外的阅读材料将对将来有所帮助


我的荣幸。很高兴您发现它很有用。Enjou :-)
Pieter Goosen

哇,真是个答案!不过,我缺少一条关键信息:如何在主帖子页面之外告诉WP“这是帖子页面” ?假设我想要一个类别为10、11、12的帖子列表和另一个类别为13、14、15的列表。我知道如何使用pre_get_posts将类别注入主查询,但是如何告诉WP将其呈现为具有适当分页的帖子列表?我真的必须按照您的广泛回答在这里wordpress.stackexchange.com/a/215027/74134,因为它是页面吗?WordPress当然可以在一个站点中允许多个博客列表吗?
马克·贝里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.