I’ve got several site running on the brilliant minimalistic Hamilton theme for WordPress. It is a free theme created by Anders Norén.

The only thing I found missing was to be able to display posts and pages easily in the same way they appear on the blog posts page.

After bit of experimenting, I came up with code for a WordPress shortcode that’ll do the trick. There’s a download link below.

With this shortcode you can do things like:

display_posts type="page" category="front-page" orderby="manual" order="ASC" class="alignwide"

or:

display_posts type="post" orderby="date" order="DESC" limit="3" class="alignwide three-columns-grid"

Both examples are used on the front page of my Venice Street Photography site.

On another site Sei Sola?, the plugin is also used, like here to show posts by a specific author:

display_posts author="martina" class="alignwide"

The possible arguments are:

  • author=”author-slug
  • category=”category-slug
  • tag=”tag-slug
  • parent=”page-id
  • type=”post” or type=”page”
  • limit=”NN” (number of posts/pages to retrieve)
  • order=”ASC” or order=”DESC”
  • orderby=”date|menu|title|id”
  • class=”additional classes

The code is kept simple on purpose, because I made this just for myself and I don’t need more than what it currently does.

The file below can be used as a WordPress plugin. Create a folder “hamilton-display-posts” in your WordPress plugin folder, and copy the code below into a file “hamilton-display-posts.php” in that folder. Then you’ll find it the plugin list where it can be activated.

The code

<?php /**
 * Plugin Name: Hamilton display_posts
 * Plugin URI: https://www.venicestreetphotography.com/
 * Description: A display_posts shortcode for theme Hamilton
 * Version: 1.0
 * Author: René Seindal
 * Author URI: https://rene.seindal.dk/
 * License: GNU General Public License version 2.0
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
 */

// Lists of posts

function hamilton_display_posts_shortcode($atts = [], $content = null, $tag = '') {
    // normalize attribute keys, lowercase
    $atts = array_change_key_case((array)$atts, CASE_LOWER);
 
    // override default attributes with user attributes
    $atts = shortcode_atts([
        'author' => NULL,
        'category' => NULL,
        'tag' => NULL,
        'parent' => NULL,
        'type' => 'post',
        'limit' => 12,
        'order' => 'DESC',
        'orderby' => 'date',
        'class' => NULL,
    ], $atts, $tag);

    if ($atts['orderby'] == 'menu' or $atts['orderby'] == 'manual') { $atts['orderby'] = 'menu_order'; }

    //error_log(print_r($atts, true));

    $query_args = array(
        'post_status' 		=> 'publish',
        'post_type'			=> $atts['type'],
        'orderby' 			=> $atts['orderby'],
        'order'				=> $atts['order'],
        'posts_per_page' 	=> $atts['limit'],
    );

    if (!empty($atts['author'])) {
        $query_args['author_name'] = $atts['author'];
    }
    if (!empty($atts['category'])) {
        $query_args['category_name'] = $atts['category'];
    }
    if (!empty($atts['tag'])) {
        $query_args['tag'] = $atts['tag'];
    }
    if (!empty($atts['parent'])) {
        $query_args['post_parent'] = $atts['parent'];
    }

    //error_log(print_r($query_args, true));

    ob_start();
    $posts = get_posts( $query_args );
    if ( $posts ) {
        global $post;
        foreach( $posts as $post ) {
            setup_postdata( $post );
            get_template_part( 'content' );
        }
        wp_reset_postdata();
    }
    $output = ob_get_clean();
    
    $class = '';
    if (!empty($atts['class'])) {
        $class = ' ' . esc_attr($atts['class']);
    }

    return '<div class="posts' . $class . '" id="posts">' . $output . '</div><!-- .posts -->';
}

add_action('init', function () {
    add_shortcode('display_posts', 'hamilton_display_posts_shortcode');
});

Leave a Reply