List All WordPress Posts by Category

If you are looking for a way to automatically generate a post index page, with all the post title & link in a WordPress website, the simple way is to use WP_Query, with “posts_per_page=-1” as $args.

There are ways to organize the list, for example, group the post by Category. In this case, we can add a new parameter in $args, which is “cat”, and put the query inside a category loop. Here are the code snippets.

Example 1: List all posts

$the_query = new WP_Query("posts_per_page=-1");
if ($the_query->have_posts()) :
    while ($the_query->have_posts()) :
    	$the_query->the_post();
    	echo '
  • '.get_the_title().'
  • '; endwhile; endif; echo '';

     

    Example 2: List all posts by category

    $cats = get_categories();
    
    foreach ($cats as $cat) {
    
        $cat_id= $cat->term_id;
        echo "

    ".$cat->name."

      "; $the_query = new WP_Query("cat=$cat_id&posts_per_page=-1"); if ($the_query->have_posts()) : while ($the_query->have_posts()) : $the_query->the_post(); echo '
    • '.get_the_title().'
    • '; endwhile; endif; echo '
    '; }

     

    I like tweaking script performance. Example 2 is straightforward using built-in WordPress functions, but not efficient in terms of performance. By interacting directly with Database, we only need to query one time. Here is another version to get all posts by category.

    Example 3: List all posts by category

    global $wpdb;
    
    $posts = $wpdb->get_results("
    	SELECT A.term_id, A.taxonomy, B.name AS category, C.object_id, D.post_title AS title, D.post_name AS slug
    	FROM $wpdb->term_taxonomy AS A
    	JOIN $wpdb->terms AS B JOIN $wpdb->term_relationships AS C JOIN $wpdb->posts AS D
    	WHERE A.taxonomy='category'
    		AND A.term_id = B.term_id
    		AND A.count > 0
    		AND A.term_taxonomy_id = C.term_taxonomy_id
    		AND C.object_id = D.ID
    	ORDER BY category, title");
    
    if ($posts) {
    	$postCategory = '';
    	$siteURL = get_home_url().'/';
    
    	foreach ($posts as $post) {
    		if ($post->category !== $postCategory) {
    			if ($postCategory !== '' ) {
    				$htmlOutput .= '';
    			}
    			$htmlOutput .= '

    '.$post->category.'

      '; $postCategory = $post->category; } $htmlOutput .= '
    • '.$post->title.'
    • '; } $htmlOutput .= '
    '; } echo $htmlOutput;