How to display regular posts & custom post types that fall under a category using just the generic category template?

The question:

1) My site has posts, and 2 custom post types (news & essays)
2) They all share normal categories like sports & health (no custom taxanomy involved)
3) Using the generic category.php template, how do I make it so this template handles all categories while displaying all content falling under it regardless of content post type.

Or simply, I would like the generic category.php template to handle all category displays but should include custom post types as well.

This may be a stupid question but have returned to WordPress after a long hiatus and am finding the default wordpress themes hard to understand to do this. Just confused and frustrated right now.

Please help

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Take a look at the query_posts() function – your amigo for altering the main/default query. You want to call global $wp_query beforehand to alter the original query instead of replacing it.

Something like this should do the trick for you. Put the first four lines in your category.php right before the main loop begins:

// Modify the default loop, include custom post types
global $wp_query;
$args = array_merge( $wp_query->query, array( 'post_type' => 'any' ) );
query_posts( $args );

// The beginning of the loop looks like this:
while ( have_posts() ) : the_post();

If you want to be more selective in displaying your post types you can provide an array with the desired post types instead of generic 'post_type'=>'any':

$args = array_merge( $wp_query->query, array( 'post_type' => array('post','news','essays') ) );

And welcome back to the WordPress universe and WPSE community.
I’m sure the frustration will be gone soon 😉

Method 2

At first I used Maugly’s solution but then i found this one in wordpress codex :

add_action( 'pre_get_posts', 'add_my_custom_post_type' );
/**
 * @param WP_Query $query
 * @return WP_Query
 */
function add_my_custom_post_type( $query ) {
    if ($query->is_main_query()) 
        $query->set( 'post_type', array( 'post', 'page', 'any_custom_type' ) );
    return $query;
}

Hope it will help someone .. maybe it’s not the cleanest but a little bit cleaner than Maugly’s solution ..

Method 3

► Here is my version of the @Kower’s suggestion. Solves a couple of problems in admin.

add_action('pre_get_posts', 'add_my_custom_post_type');

/**
 * @param WP_Query $query
 * @return WP_Query
 */
function add_my_custom_post_type($query) {
    if(
        empty($query->query['post_type'])
        or $query->query['post_type'] === 'post'
    ){
        $query->set('post_type', array('post', 'my_custom_type'));
    }
}

Method 4

I wanted to add to this, in reference to @tivnet’s answer. (I would have liked to have left a comment but my rep is not high enough)

I found the solutions worked, however they presumably had the unintended consequence of affecting the admin area as well, meaning that visiting the posts in the wp-admin (wp-admin/edit.php) would also show all pages and all custom post types in the generic post list. Confusing for other users perhaps? However, adding:

and !is_admin()

within the if() statement appears to solve this issue while keeping the pre_get_posts amend on the front end.

add_action('pre_get_posts', 'add_my_custom_post_type');

/**
 * @param WP_Query $query
 * @return WP_Query
 */
function add_my_custom_post_type($query) {
    if(
        empty($query->query['post_type'])
        or $query->query['post_type'] === 'post'
        and !is_admin()
    ){
        $query->set('post_type', 'any');
    }
}

Method 5

To include a custom post type in the regular loop (ie. posts page) just add the following code to index.php before if ( have_posts() ) :

$args = array(
'post_type'   => array('post', 'custom_post_type'),
'post_status' => 'publish',
);
$new_post_loop = new WP_Query( $args );

then modify the following two lines:

if ( have_posts() ) : change it to if ( $new_post_loop -> have_posts() ) :

and

while ( have_posts() ) : the_post(); to while ( $new_post_loop -> have_posts() ) : $new_post_loop -> the_post();

This solution avoids the problem of having the custom post type listed in the all posts screen on the backend, which using add_action(‘pre_get_posts’) produces 😉

Method 6

function namespace_add_custom_types( $query ) 
{
 if( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) 
 {
   $query->set( 'post_type', array(
  'post', 'nav_menu_item', 'your-custom-post-type-here'
   ));
  return $query;
}
}
add_filter( 'pre_get_posts', 'namespace_add_custom_types' );


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment