On many of the client sites I build, I find there are times when I need to include a post listing on a page. I'm not talking about archive pages here, but adding a custom listing to an existing static page.
For example, I might want to list some posts on the 'About' page, or the site may require an in-depth page for a topic, with a list of posts and custom post types related to that topic.
One way to do this is by creating a custom page template to include the current page content plus the results of a second custom query, but if you want more flexibility over how you list posts, or just want to do it a few times, a shortcode will be a simpler solution.
In this tutorial, I'll show you how to create a simple shortcode to list all posts of a custom post type, and then I'll expand on that to create a shortcode with various parameters that users can specify to list posts however they want.
What You Need to Complete This Tutorial
You will need the following resources:
- A development installation of WordPress
- Access to your plugins folder so you can create and upload the shortcode plugin
You'll find all of the code to create this plugin in the code download.
Getting Started: Creating the Content
Before setting up the shortcode, you'll need to register a custom post type and two custom taxonomies, which we'll be using to test the shortcode.
The code to do this is contained in the plugin I've written for the shortcode, though on a live project, I'd recommend separating this out from the shortcode plugin itself.
Create a new file in your plugins folder and call it post-listing-shortcode.php.
Add the code below to the file.
Note: Creating the custom post types and taxonomies isn't central to the learning from this tutorial. If you want, you can copy this code from the download file and skip this stage.
<?php /* Plugin Name: WPTutsPlus Post-listing shortcode Plugin URI: http://rachelmccollin.co.uk Description: This plugin provides a shortcode to list posts, with parameters. It also registers a couple of post types and tacxonomies to work with. Version: 1.0 Author: Rachel McCollin Author URI: http://rachelmccollin.co.uk License: GPLv2 */ // register custom post type to work with add_action( 'init', 'rmcc_create_post_type' ); function rmcc_create_post_type() { // clothes custom post type // set up labels $labels = array( 'name' =--> 'Clothes', 'singular_name' => 'Clothing Item', 'add_new' => 'Add New', 'add_new_item' => 'Add New Clothing Item', 'edit_item' => 'Edit Clothing Item', 'new_item' => 'New Clothing Item', 'all_items' => 'All Clothes', 'view_item' => 'View Clothing Item', 'search_items' => 'Search Clothes', 'not_found' => 'No Clothes Found', 'not_found_in_trash' => 'No Clothes found in Trash', 'parent_item_colon' => '', 'menu_name' => 'Clothes', ); register_post_type( 'clothes', array( 'labels' => $labels, 'has_archive' => true, 'public' => true, 'hierarchical' => true, 'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail','page-attributes' ), 'taxonomies' => array( 'post_tag', 'category' ), 'exclude_from_search' => true, 'capability_type' => 'post', ) ); } // register two taxonomies to go with the post type add_action( 'init', 'rmcc_create_taxonomies', 0 ); function rmcc_create_taxonomies() { // color taxonomy $labels = array( 'name' => _x( 'Colors', 'taxonomy general name' ), 'singular_name' => _x( 'Color', 'taxonomy singular name' ), 'search_items' => __( 'Search Colors' ), 'all_items' => __( 'All Colors' ), 'parent_item' => __( 'Parent Color' ), 'parent_item_colon' => __( 'Parent Color:' ), 'edit_item' => __( 'Edit Color' ), 'update_item' => __( 'Update Color' ), 'add_new_item' => __( 'Add New Color' ), 'new_item_name' => __( 'New Color' ), 'menu_name' => __( 'Colors' ), ); register_taxonomy( 'color', 'clothes', array( 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'rewrite' => true, 'show_admin_column' => true ) ); // fabric taxonomy $labels = array( 'name' => _x( 'Fabrics', 'taxonomy general name' ), 'singular_name' => _x( 'Fabric', 'taxonomy singular name' ), 'search_items' => __( 'Search Fabrics' ), 'all_items' => __( 'All Fabric' ), 'parent_item' => __( 'Parent Fabric' ), 'parent_item_colon' => __( 'Parent Fabric:' ), 'edit_item' => __( 'Edit Fabric' ), 'update_item' => __( 'Update Fabric' ), 'add_new_item' => __( 'Add New Fabric' ), 'new_item_name' => __( 'New Fabric' ), 'menu_name' => __( 'Fabrics' ), ); register_taxonomy( 'fabric', 'clothes', array( 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'rewrite' => true, 'show_admin_column' => true ) ); } ?>
This tells WordPress about the plugin and registers the custom post type 'clothes' and the two taxonomies, 'color' and 'fabric'.
Save this plugin and activate it via the Plugins page in WordPress.
Now you have your custom post type and taxonomies in place, create some posts using them. In the screenshot below you can see the content I've created:
Creating a Simple Listing Shortcode
If you only want to list content in one way using your shortcode, you can create a very simple shortcode which doesn't use parameters.
Open your plugin file again and add the following:
// create shortcode to list all clothes which come in blue add_shortcode( 'list-posts-basic', 'rmcc_post_listing_shortcode1' ); function rmcc_post_listing_shortcode1( $atts ) { ob_start(); $query = new WP_Query( array( 'post_type' => 'clothes', 'color' => 'blue', 'posts_per_page' => -1, 'order' => 'ASC', 'orderby' => 'title', ) ); if ( $query->have_posts() ) { ?> <ul class="clothes-listing"> <?php while ( $query->have_posts() ) : $query->the_post(); ?> <li id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </li> <?php endwhile; wp_reset_postdata(); ?> </ul> <?php $myvariable = ob_get_clean(); return $myvariable; } }
This creates a simple shortcode, using WP_Query
to run a custom query on your content and output the results in a list. When I type [list-posts-basic]
into a page the results are as shown in this screenshot:
Adding Some Parameters to Modify the Query
The shortcode will be much more useful if users can add their own parameters, choosing for example:
- How many posts to list
- What post type to query
- Categories to include
- Fabrics and colors to include
- Ordering parameters
To add this to the shortcode, you make use of the shortcode_atts()
function, which allows you to specify some default attributes which users can override.
Once again in your plugin file and below the code for the first shortcode, add the following:
// create shortcode with parameters so that the user can define what's queried - default is to list all blog posts add_shortcode( 'list-posts', 'rmcc_post_listing_parameters_shortcode' ); function rmcc_post_listing_parameters_shortcode( $atts ) { ob_start(); // define attributes and their defaults extract( shortcode_atts( array ( 'type' => 'post', 'order' => 'date', 'orderby' => 'title', 'posts' => -1, 'color' => '', 'fabric' => '', 'category' => '', ), $atts ) ); // define query parameters based on attributes $options = array( 'post_type' => $type, 'order' => $order, 'orderby' => $orderby, 'posts_per_page' => $posts, 'color' => $color, 'fabric' => $fabric, 'category_name' => $category, ); $query = new WP_Query( $options ); // run the loop based on the query if ( $query->have_posts() ) { ?> <ul class="clothes-listing "> <ul class="clothes-listing "> <li id="post-<?php the_ID(); ?>">></li> </ul> </ul> <?php $myvariable = ob_get_clean(); return $myvariable; } }
Note: Using ob_start()
and ob_get_clean()
ensures that the loop is output in the place in your page or post that you've added the shortcode. If you don't add these, the list will be displayed at the top of the content.
By default this lists all posts in descending order of date, so if you type [list-posts]
into a page or post, the result is as in this screenshot:
However, if you add some parameters things get more interesting. For example, to list all clothes which come in the color black, I type [list-posts type="clothes" color="black" orderby="name" order="ASC"]
:
Or to list all clothes in the 'smart' category I type [list-posts type="clothes" category="smart" orderby="name" order="ASC"]
:
If you need to you can specify more attributes which users can work with, but you have to include all of the available ones in your plugin, in the extract( shortcode_atts))
function.
You don't have to specify a default for all of them - for example I've left the category and taxonomy parameters empty in the example. The parameters you can define are any of those which can be specified for WP_Query
- for a full list, see its Codex page.
Summary
Being able to insert a post listing into a page or post can be very useful. It saves you having to modify your template files or write a custom page template.
The shortcode you've learned how to create in this plugin could be used in many ways, and of course you could easily change what's output by the shortcode - my example outputs a bulleted list with post titles enclosed in a link to their page, but you could replace the code inside the loop with the template tags to display the content, featured images, or anything else.
Resources
Some useful resources on the topics covered above:
Comments