【问题标题】:Grouping WordPress custom posts by taxonomy按分类对 WordPress 自定义帖子进行分组
【发布时间】:2015-10-01 14:53:30
【问题描述】:

我有一个名为“产品”的自定义帖子类型,它有两个自定义分类 - “产品范围”和“产品类别”。范围用作顶级分组,而类别是其中的子分组。

我设置了一个 taxonomy-product-range.php 模板,其中包含以下代码:

<?php
$terms = get_terms('product-categories');
foreach( $terms as $term ):
?>     

<h2><?php echo $term->name;?></h2>
<ul>

    <?php                         
    $posts = get_posts(array(
        'post_type' => 'products',
        'taxonomy' => $term->taxonomy,
        'term' => $term->slug,
        'nopaging' => true
    ));
    foreach($posts as $post): setup_postdata($post);
    ?>

    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>

    <?php endforeach; ?>

</ul>           

<?php endforeach; ?>

通过输出产品并按产品类别对它们进行分组,这可以按预期工作。但是,无论您正在查看哪个档案,它都会输出所有产品。我需要它来仅输出您正在查看的存档的帖子。

感觉快到了,但我不知道如何解决它。

== 编辑 ==

每个产品都属于一个“范围”和一个“类别”。当人们访问产品范围存档页面时,我试图显示以下内容:

<h1>Range Title</h1>
<h2>Category 1 Title</h2>
<ul>
<li>Product 1 Title</li>
<li>Product 2 Title</li>
<li>Product 3 Title</li>
</ul>
<h2>Category 2 Title</h2>
<ul>
<li>Product 4 Title</li>
<li>Product 5 Title</li>
<li>Product 6 Title</li>
</ul>

【问题讨论】:

  • @CayceK 不,不是。在这种情况下这行不通
  • @PieterGoosen 并不是为了回答我为什么没有发布答案,但它与母校的想法有关。我只是发布它,以便可以看到是否有人问这个问题并且这并不能解决他们:D
  • @CayceK 似乎我必须在这里用排序证明一点。请记住,10 个术语意味着 10 个自定义查询,1000 个术语意味着 1000 个自定义查询。看看它有多贵
  • @PieterGoosen 是的,这些都是真的。请记住,我没有标记为重复,我刚才说可能相关。再次,相关与尝试解决无关。它也与建议一种方法来做到这一点无关。但是,如果另一个用户试图找到他们问题的答案,他们可能需要链接到该问题,因为这对他们来说可能更正确。我并不是要说这里的任何事情都是错误的或这里的任何事情都更好。它只是为了提供一个辅助来源,也许这会帮助其他人。 “可能”的使用也是这个想法的关键。

标签: php wordpress


【解决方案1】:

简单地删除您拥有的代码并将其替换为默认循环。您不应将主查询替换为自定义查询。使用pre_get_posts根据需要修改主查询。

这就是你的分类页面的样子

if ( have_posts() ) {
    while ( have_posts() ) {
    the_post();

        // Your template tags and markup

    }
}

由于您的问题是排序,我们将使用usortthe_posts 过滤器在循环运行之前但在主查询运行之后进行排序。我们不会使用多个循环,因为它们非常昂贵且资源密集,并且会破坏页面功能

我已对代码进行了注释,以便于理解。 (注意:以下代码未经测试,由于数组取消引用,需要 PHP 5.4+)

add_filter( 'the_posts', function ( $posts, $q ) 
{
    $taxonomy_page = 'product-range';
    $taxonomy_sort_by = 'product-categories'; 

    if (    $q->is_main_query() // Target only the main query
         && $q->is_tax( $taxonomy_page ) // Only target the product-range taxonomy term pages
    ) {
        /**
         * There is a bug in usort that will most probably never get fixed. In some instances
         * the following PHP warning is displayed 

         * usort(): Array was modified by the user comparison function
         * @see https://bugs.php.net/bug.php?id=50688

         * The only workaround is to suppress the error reporting
         * by using the @ sign before usort
         */      
        @usort( $posts, function ( $a, $b ) use ( $taxonomy_sort_by )
        {
            // Use term name for sorting
            $array_a = get_the_terms( $a->ID, $taxonomy_sort_by );
            $array_b = get_the_terms( $b->ID, $taxonomy_sort_by );

            // Add protection if posts don't have any terms, add them last in queue
            if ( empty( $array_a ) || is_wp_error( $array_a ) ) {
                $array_a = 'zzz'; // Make sure to add posts without terms last
            } else {
                $array_a = $array_a[0]->name;
            }

            // Add protection if posts don't have any terms, add them last in queue
            if ( empty( $array_b ) || is_wp_error( $array_b ) ) {
                $array_b = 'zzz'; // Make sure to add posts without terms last
            } else {
                $array_b = $array_b[0]->name;
            }

            /**
             * Sort by term name, if term name is the same sort by post date
             * You can adjust this to sort by post title or any other WP_Post property_exists
             */
            if ( $array_a != $array_b ) { 
                // Choose the one sorting order that fits your needs
                return strcasecmp( $array_a, $array_b ); // Sort term alphabetical ASC 
                //return strcasecmp( $array_b, $array_a ); // Sort term alphabetical DESC
            } else {
                return $a->post_date < $b->post_date; // Not sure about the comparitor, also try >
            }
        });
    }
    return $posts;
}, 10, 2 ); 

编辑

这是您的循环在编辑中按顺序显示页面的外观

if ( have_posts() ) {
    // Display the range term title
    echo '<h1>' . get_queried_object()->name . '</h1>';

    // Define the variable which will hold the term name
    $term_name_test = '';

    while ( have_posts() ) {
    the_post();

        global $post;
        // Get the terms attached to a post
        $terms = get_the_terms( $post->ID, 'product-categories' );
        //If we don't have terms, give it a custom name, else, use the first term name
        if ( empty( $terms ) || is_wp_error( $terms ) ) {
            $term_name = 'SOME CUSTOM NAME AS FALL BACK';
        } else { 
            $term_name = $terms[0]->name;
        }

        // Display term name only before the first post in the term. Test $term_name_test against $term_name
        if ( $term_name_test != $term_name ) {
            // Close our ul tags if $term_name_test != $term_name and if not the first post
            if ( $wp_query->current_post != 0 )
                echo '</ul>';

            echo '<h2>' . $term_name . '</h2>';

            // Open a new ul tag to enclose our list
            echo '<ul>';
        } // endif $term_name_test != $term_name

        $term_name_test = $term_name;

        echo '<li>' . get_the_title() . '</li>';    

        // Close the ul tag on the last post        
        if ( ( $wp_query->current_post + 1 ) == $wp_query->post_count ) 
            echo '</ul>';

    }
}

编辑 2

上面的代码现在已经过测试并且可以工作了。根据要求,这是在我的本地安装上运行的测试。对于这个测试,我使用了 OP 中的代码和我的代码。

结果

此结果是通过Query Monitor Plugin 获得的。此外,所有结果都包括由小部件、导航菜单、自定义功能等进行的相同额外查询

  • OP 中的代码 -> 318 db 查询在 0.7940 秒内,页面生成时间为 1.1670 秒。内存使用量为 12.8Mb

  • 我的回答代码 -> 46 db 查询在 0.1045 秒内,页面生成时间为 0.1305 秒。内存使用量为 12.6Mb

正如我之前所说,证据在布丁中

【讨论】:

  • 我回到chat
  • 修复了一个错误。请查看新循环
  • @CayceK 你真的应该在你的开发站点上安装查询监视器。它真的很有帮助。真正好的是,它分解了每个执行的查询,因此您确切地知道哪个查询是缓慢且低效的。有一件事是肯定的,自定义查询很昂贵,特别是如果您有非常大的帖子
  • @CayceK 检查this post 以及我刚才所做的。您也可以使用此方法进行排序。该方法(作为自定义查询)的好处在于您可以使用瞬态来保存查询,这使得查询非常快
  • OP 绝对感谢为提供解决方案所做的所有工作。我刚刚对其进行了测试,并且效果很好。非常非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-28
  • 2013-06-22
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 2014-05-15
相关资源
最近更新 更多