How to create tabled index of posts in a certain category

There several different ways to achieve that: a custom template, a metabox, or a shortcode. In all cases you will probably use get_posts() or WP_Query to fetch the posts and some method to set the category. The following sample code illustrates that with a shortcode.

Basic usage

You just write the shortcode in your post editor on a page or a blog post:

[posttable catname="Uncategorized"]

enter image description here

The code

In a plugin you register the shortcode and you create a function to return the output. Be aware that a shortcode always just returns a string, it doesn’t use echo or print.

<?php
/* Plugin Name: T5 Post Table Shortcode
 * Description: Create a table of post with: <code>[posttable catname="category-name"]</code>.
 */

add_shortcode( 'posttable', 't5_posttable_shortcode' );

/**
 * Create a table with all post from a category.
 *
 * @param  array $attr
 * @return string
 */
function t5_posttable_shortcode( $attr )
{
    $defaults = array (
        'catname' => FALSE,
        /* table attributes */
        'class'   => FALSE,
        'id'      => FALSE,
        /* name of a registered script to enqueue in the footer if
         * results are found. */
        'script'  => FALSE,
        'order'   => 'DESC',
        'orderby' => 'date'
    );
    extract( shortcode_atts( $defaults, $attr ) );

    $get_posts_args = array (
        'numberposts' => -1,
        'order'       => strtoupper( $order ),
        'orderby'     => $orderby,
        'post_type'   => 'post'
    );

    if ( $catname and $category = get_term_by( 'name', $catname, 'category' ) )
    {
        $get_posts_args['cat'] = $category->term_id;
    }

    if ( ! $posts = get_posts( $get_posts_args ) )
    {
        return '<!-- nothing found -->';
    }

    $out="<table";
    $class and $out .= " class="$class"";
    $id    and $out .= " id='$id'";
    $out .= '><thead><tr><th scope="col">' . __( 'Name' )
        . '</th><th scope="col">' . __( 'Date' )
        . '</th><th scope="col">' . __( 'Comments' )
        . '</th></tr></thead><tbody>';

    $dateformat = get_option( 'date_format' );

    foreach ( $posts as $post )
    {
        $out .= sprintf(
            '<tr><td><a href="%1$s">%2$s</a></td><td>%3$s</td><td>%4$d</td></tr>',
            get_permalink( $post->ID ),
            get_the_title( $post->ID ),
            get_the_time( $dateformat, $post->ID ),
            get_comments_number( $post->ID )
        );
    }

    $script and wp_enqueue_script( $script );

    return "$out</tbody></table>";
}

That’s very rough; I have just sketched it hastily. You have to register the script name separately if you need some kind of a table sorter (jQuery tablesorter is nice).
To understand the other parameters read the docs for WP_Query.

To use the excerpt or thumbnail just add …

apply_filters( 'get_the_excerpt', $post->post_excerpt )

… or …

get_the_post_thumbnail( $post->ID )

… where you need it.

For example like this:

get_the_title( $post->ID ) 
    . get_the_post_thumbnail( $post->ID ) 
    . apply_filters( 'get_the_excerpt', $post->post_excerpt )

The result

In TwentyEleven it looks like this:

enter image description here

The parameters id and class should offer enough flexibility to adjust the styles. 🙂

Leave a Comment