获取所有类别和这些类别中的帖子

时间:2012-02-24 作者:Ben

我正在寻找一种可以打印以下内容的解决方案:

Cat 1        Cat 2        Cat 3
 Post 1       Post 1       Post 1
 Post 2       Post 2       Post 2
 Post 3                    Post 3
                           Post 4

EDIT

我正在寻找只需要一次数据库查询的东西!所以如果你有foreach 在代码中,后跟new WP_Query 那么这不是我想要的(我计划把这个放到我的网站主页上)。

8 个回复
SO网友:Pieter Goosen

EDIT REVISIT NO 2

我从没碰过Transient API, 直到今天我看到@MikeSchinkel回答this post. 这激励我再次访问这篇文章。经过一些测试,我得出以下结论:

执行时间从约0.07秒减少到约0.002秒

数据库查询时间减少了大约一半

对于瞬态,只执行2个db查询

代码是如何工作的(只讨论从REVISIT):

STEP 1

我们需要保存$q 对于临时用户,这是保存带有帖子标题的类别列表的值。

STEP 2

我们首先需要检查是否存在瞬态,如果不存在,则创建瞬态。如果瞬态存在,则检索其信息

STEP 3

此信息现在通过foreach 循环打印包含类别名称和帖子标题的列表。

STEP 4

目前,瞬态将每12小时更新一次。这可以根据您的需要进行设置。然而,每次帖子状态改变时,都需要删除并重新创建瞬态。这可能是从草稿到发布,一篇新文章或一篇被丢弃的文章。要做到这一点,您需要利用delete_transient 将连接到transition_post_status 每次帖子状态改变时都会触发

以下是完整的代码:

在您的功能中。php

add_action( \'transition_post_status\', \'publish_new_post\', 10, 3 );

function publish_new_post() {
   delete_transient( \'category_list\' );
}
在需要显示列表的模板中

<?php
if ( false === ( $q = get_transient( \'category_list\' ) ) ) {

    $args = array( 
        \'posts_per_page\' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = \'<a href="\'. get_permalink() .\'">\' . get_the_title() .\'</a>\';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

set_transient( \'category_list\', $q, 12 * HOUR_IN_SECONDS );
}

foreach ($q as $key=>$values) {
        echo $key;

        echo \'<ul>\';
            foreach ($values as $value){
                echo \'<li>\' . $value . \'</li>\';
            }
        echo \'</ul>\';
    }


?>
REVISIT

我最近提出了一个非常轻量级的解决方案,比其他可能的解决方案快得多。在我的测试站点上,根据Query Monitor 而其他方法给我大约0.35秒的生成时间和50个额外的db查询。

这是我的方法的分解

STEP 1

首先需要使用创建自定义查询WP_Query 检索所有已发布的帖子

$args = array( 
        \'posts_per_page\' => -1
    );

    $query = new WP_Query($args);   
    $q = array();

    while ( $query->have_posts() ) { 

    }

    /* Restore original Post Data */
    wp_reset_postdata();

Step 2

使用get_the_category, 检索帖子所属的所有类别的列表。

$categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

        }

STEP 3

为帖子标题和帖子类别分配变量

$a = \'<a href="\'. get_permalink() .\'">\' . get_the_title() .\'</a>\';
以及

$b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

STEP 4

将这两个变量组合成一个多维数组

$q[$b][] = $a;
要查看阵列中发生的情况,只需执行var_dump

?><pre><?php var_dump($q); ?></pre><?php

STEP 5

使用foreach 循环,创建按类别排序的帖子列表

foreach ($q as $key=>$values) {
    echo $key;

    echo \'<ul>\';
        foreach ($values as $value){
            echo \'<li>\' . $value . \'</li>\';
        }
    echo \'</ul>\';
}

ALL TOGETHER NOW!

这是完整的代码

<?php

    $args = array( 
        \'posts_per_page\' => -1
    );

    $query = new WP_Query($args);   
    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = \'<a href="\'. get_permalink() .\'">\' . get_the_title() .\'</a>\';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }

    /* Restore original Post Data */
    wp_reset_postdata();

    foreach ($q as $key=>$values) {
        echo $key;

        echo \'<ul>\';
            foreach ($values as $value){
                echo \'<li>\' . $value . \'</li>\';
            }
        echo \'</ul>\';
    }

?>

SO网友:lowtechsun

我只是想添加从this question 我有过。这将缓存类别的查询,并缓存每个类别中的帖子,包括帖子内容。第一次填充缓存时,会有正常的数据库查询,但是一旦填充,就会提供缓存的类别和帖子,因此不再有数据库查询。

// Transients API all categories and all posts
$query_categories = get_transient(\'cached_categories\');
if ( false === $query_categories){
    $args_cat = array(
        // order by category name ascending
        \'orderby\' => \'name\',
        \'order\' => \'ASC\',
        // get only top level categories
        \'parent\' => 0
    );
    // Instead of caching a WP Query I cache \'get_categories()\'.
    $query_categories = get_categories($args_cat);
    // var_dump($query_categories);
    set_transient(\'cached_categories\', $query_categories, DAY_IN_SECONDS );
}

// Full posts query
// if there are categories filled with posts
if (!empty ($query_categories) && !is_wp_error( $query_categories )) {

    foreach ($query_categories as $category) {

        // var_dump($category);
        $query_category_posts = get_transient(\'cached_posts_\' . $category->slug );
        if ( false === $query_category_posts ){

            // Query all posts by slug inside each category
            $args_category_posts = array(
                \'post_type\' => \'post\',
                // The category slug and category name we get from the foreach over all categories
                \'category_name\' => $category->slug
            );

            // Here I cache the WP_Query, though this runs for all categories.
            // Because of that the \'$category->slug\' is used to serve a string and not an object.
            $query_category_posts = new WP_Query($args_category_posts);         
            set_transient( \'cached_posts_\' . $category->slug , $query_category_posts, DAY_IN_SECONDS );
        }

        if ($query_category_posts->have_posts()) {
            while ($query_category_posts->have_posts()) {
                $query_category_posts->the_post(); ?>
                <article class="<?php echo $category->slug ?>-article">
                    <h2 class="<?php echo $category->slug ?>-article-title">
                        <a href="<?php echo get_permalink() ?>"><?php echo get_the_title() ?></a>
                    </h2>
                    <p class="<?php echo $category->slug ?>-post-info">
                        <?php the_time(\'d. m. Y\') ?>
                    </p>
                    <div <?php post_class() ?> >
                        <?php the_content(); ?>
                    </div>
                </article> <?php
            }
        } // end loop
    } // end foreach
wp_reset_postdata() ;
} // end if there are categories filled with posts

SO网友:Floris

这是我的解决方案,可以得到这些类别中的类别和帖子作为一个结果。

我的示例基于自定义帖子类型分类类别document_category 和自定义帖子类型documents. 但我相信你会明白的。

$result = [];

$categories = get_terms( [
    \'taxonomy\' => \'document_category\'
] );

foreach ( $categories as $index => $category ) {
    $args      = [
        \'post_type\'      => \'documents\',
        \'posts_per_page\' => - 1,
        \'public\'         => true,
        \'tax_query\'      => [
            [
                \'taxonomy\'         => \'document_category\',
                \'field\'            => \'term_id\',
                \'terms\'            => $category->term_id,
                \'include_children\' => true
            ]
        ]
    ];
    $documents = get_posts( $args );

    $result[ $index ][\'category\']  = $category;
    $result[ $index ][\'documents\'] = $documents;
}

return $result;

SO网友:NikHiL Gadhiya

try now this code

$cat_ids=array();
foreach (get_categories() as $cat)
{
    array_push($cat_ids, $cat->cat_ID);
}
$the_query = new WP_Query(array(\'post_type\'=>\'post\', array(\'category__and\' => $cat_ids) ) );
if( $the_query->have_posts() ): 
    while ( $the_query->have_posts() ) : $the_query->the_post(); 
        echo the_title();
    endwhile;
endif; 
wp_reset_query();
SO网友:Sagive

您可以使用此。。。设置您需要的帖子数量。。。

此外,我已经把它都放在一个div中,所以你可以做的结构和设计你的寻找。

<?php  
    $allcats = get_categories(\'child_of=0\'); 

    foreach ($allcats as $cat) :
        $args = array(
            \'posts_per_page\' => 3, // set number of post per category here
            \'category__in\' => array($cat->term_id)
        );

        $customInCatQuery = new WP_Query($args);

        if ($customInCatQuery->have_posts()) :
            echo \'<div>\';
            echo \'<h3>\'.$cat->name.\'</h3>\';
            echo \'<ul>\';
            while ($customInCatQuery->have_posts()) : $customInCatQuery->the_post(); ?>

            <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
        <?php
            endwhile; 
            echo \'</ul></div>\'; 
        ?>

<?php
        else :
            echo \'No post published in:\'.$cat->name;                
        endif; 
        wp_reset_query();
    endforeach; 
?>
希望这有帮助。

SO网友:Webord

我已经为自己构建了一些我经常使用的东西,下面是代码,您可以在$categories 数组,如果要获取可以使用的所有类别get_terms(), 并提供一组术语对象,但要小心,这段代码中没有层次结构的处理方法。

$categories = array( 1, \'slug\', 3 );
echo \'<ul>\';
foreach($categories as $category) {
    $term = ( is_numeric($category) || is_object($category) ? get_term( $category, \'category\' ) : get_term_by( \'slug\', $category, \'category\' ) );
    $args = array(
        \'cat\' => $term->term_id
        // Add any other arguments to fit your needs
    );
    $q = new WP_Query( $args );
    if( $q->have_posts() ) {
        echo \'<li><a href="\' . get_term_link( $term->term_id, \'category\' ) . \'">\' . $term->name . \'</a><ul>\';
        while( $q->have_posts() ) {
            $q->the_post();
            echo \'<li><a href="\' . get_permalink() . \'">\' . get_the_title() . \'</a></li>\';
        }
        echo \'</ul></li>\';
    } else {

    }
}
echo \'</ul>\';

SO网友:Neil Davidson

未经测试,但我会尝试的最简单方法之一是:

<?php
    $category_ids = get_all_category_ids();
    foreach ($category_ids as $values) {
        $args = array(\'category\' => $value);
        $posts_array = get_posts( $args );
        foreach ($posts_array as $post) : setup_postdata($post);
?> 
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
        endforeach;
        wp_reset_query();
    }
?>

SO网友:jasonflaherty

如果您正在寻找插件,List Category Posts 可能对你有用。

在进行查询之前,请查看get_posts

结束