List posts by Category Shortcode for WordPress

Usually the archive pages in WordPress leave a lot to be desired and sometimes you want to list posts by category so users have a much nicer way of interacting with your content so it can be useful to have access to a list posts by category shortcode.

What we’re aiming for is a listing similar to:

list posts by category shortcode

While you can modify the archive page template in your theme to have this listing, it would be a lot simpler to just have a list posts by category shortcode that you can use anywhere you want. And that’s what we’re going to build.

Create a new plugin

Creating a new plugin is really straight forward, we just need to create a new file and add these php commets to the top of the file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/**
 * Plugin Name: Taxonomy Archive Shortcode
 * Plugin URI: https://www.cozmoslabs.com
 * Description: A simple shortcode to list a taxonomy archive and the posts for each term ex: [list_taxonomy_archive cpt="book" tax="genre"]
 * Version: 1.0
 * Author: Cristian Antohe
 * Author URI: https://www.cozmoslabs.com
 * License: GPL2
 */
 
/*  Copyright 2016 Cristian Antohe
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License, version 2, as 
    published by the Free Software Foundation.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
// Start writing code after this line!

Create a new shortcode

We’ll need code to register a new shortcode: [list_taxonomy_archive]

By default this shortcode will create a listing with all the categories and the posts found inside those categories. However, you can also define a custom taxonomy or custom post type like so: [list_taxonomy_archive cpt=”book” tax=”genre”]

1
2
3
4
5
6
7
add_shortcode('list_taxonomy_archive', 'wckc_list_taxonomy_archive');
function wckc_list_taxonomy_archive($atts){
    $a = shortcode_atts( array(
        'cpt' => 'post',
        'tax' => 'category',
    ), $atts );
}

So far our shortcode doesn’t do anything. Next we’ll need to look into querying all the taxonomy terms and the posts that have them assigned.

Query all taxonomy terms and the posts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    $terms = get_terms( array('taxonomy' => $a['tax'], 'hide_empty' => false) );
 
    if( $terms ){
        $output .= '<div class="list_tax_archive">';
        foreach ($terms as $term) {
            if ( is_array($term) && isset($term['invalid_taxonomy']) )
                return;
 
            $args = array (
                'post_type'         => $a['cpt'],
                $a['tax']           => $term->slug,
                'posts_per_page'    => '-1',
            );
 
            // The Query
            $posts = get_posts($args);
 
            if( empty($posts)){
                return;
            }
            $output .= "<h4> {$term->name} </h4>";
            $output .= '<ul class="term_archive">';
            foreach($posts as $post){
                $output .= '<li><a href="'.get_permalink( $post ).'">'.get_the_title( $post ).'</a></li>';
            }
            $output .= '</ul>';
 
        }
        $output .= '</div>';
    }

What we’re doing is:

  • Get all the terms of our taxonomy using get_terms
  • For each term that is assigned to at least 1 post, query for those particular posts using get_posts

The code for the list posts by category shortcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
 * Create a shortcode that lists all cpt's ordered by taxonomy term
 */
 
add_shortcode('list_taxonomy_archive', 'wckc_list_taxonomy_archive');
function wckc_list_taxonomy_archive($atts){
    $a = shortcode_atts( array(
        'cpt' => 'post',
        'tax' => 'category',
    ), $atts );
 
    $output = '';
 
    $terms = get_terms( array('taxonomy' => $a['tax'], 'hide_empty' => false) );
 
    if( $terms ){
        $output .= '<div class="list_tax_archive">';
        foreach ($terms as $term) {
            if ( is_array($term) && isset($term['invalid_taxonomy']) )
                return;
 
            $args = array (
                'post_type'         => $a['cpt'],
                $a['tax']           => $term->slug,
                'posts_per_page'    => '-1',
            );
 
            // The Query
            $posts = get_posts($args);
 
            if( empty($posts)){
                return;
            }
            $output .= "<h4> {$term->name} </h4>";
            $output .= '<ul class="term_archive">';
            foreach($posts as $post){
                $output .= '<li><a href="'.get_permalink( $post ).'">'.get_the_title( $post ).'</a></li>';
            }
            $output .= '</ul>';
 
        }
        $output .= '</div>';
    }
    return $output;
 
}

You can also download and install the plugin:

Get List posts by category

Subscribe to get early access

to new plugins, discounts and brief updates about what's new with Cozmoslabs!

5 thoughts on “List posts by Category Shortcode for WordPress

  1. Just what I was looking for! Except, using the default shortcode ([list_taxonomy_archive]) I get all posts under each category. Or, when I try the other option ([list_taxonomy_archive cpt=”book” tax=”genre”]) using a category slug I get nothing. Any thoughts? Thank you!

  2. Hi I tried this php code on wordpress4.9.6 and I can not see it in plu-in how come? …. let you know thanks

    1. It already does that. For example, you use the shortcode like so: [list_taxonomy_archive cpt=”book” tax=”genre”]

      you can then replace it with

      [list_taxonomy_archive cpt=”post” tax=”tag”]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.