0

I have registered the two following custom post types:

function dogs() {

    $labels = array(
        'name' => 'Dogs'
    );

    $args = array(
        'labels' => $labels, 
        'public' => true,
        'has_archive' => true,            
        'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' )
    );

    register_post_type( 'dog', $args );
}

function cats() {

    $labels = array(
        'name' => 'Cats'
    );

    $args = array(
        'labels' => $labels, 
        'public' => true,
        'has_archive' => true,
        'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' )
    );

    register_post_type( 'cat', $args );
} 

In the archive page for the 'dog' post type (mysite.com/dog), I want to display posts that use both the 'dog' and the 'cat' post type. So I've created a custom template called archive-dog.php and altered the main query like this:

add_action( 'pre_get_posts', 'cats_and_dogs' ) );

function cats_and_dogs( $query ) {
    if( ! is_admin() && is_post_type_archive( 'dog' ) ) {
        if( $query->is_main_query() ) {  
            $query->set( 'post_type', array( 'dog', 'cat'  ) );
            $query->set( 'posts_per_page', 4 );
            $query->set( 'post_status', 'publish' );  
            $query->set( 'post__not_in', get_option( 'sticky_posts' ) ); 
        } 
    }         
}

When I visit mysite.com/dog, I would expect Wordpress to automatically pick up archive-dog.php and display both 'dog' and 'cat' posts. Instead, while it does display both 'dog' and 'cat' posts, it does not pick up the archive-dog.php but falls back to archive.php. If I remove the 'cat' post type from the altered main query and only leave 'dog', everything works fine. How can I have both both post types and my custom archive template?

1
  • Have you tried reversing the order for the post_types? It's a hack but worth a try.
    – Welcher
    Commented Nov 21, 2017 at 13:56

1 Answer 1

2

You can manage this via the template_include hook.

add_filter( 'template_include', 'cats_and_dogs_living_together', 99 );

function cats_and_dogs_living_together( $template ) {

    if ( is_post_type_archive( array ( 'cat', 'dog' ) ) ) {
        $new_template = locate_template( array( 'archive-dog.php' ) );
        if ( '' != $new_template ) {
            return $new_template;
        }
    }
    return $template;
}

Hope this helps!

2
  • Thank you, yes, this works. But now I wonder, was the issue I was having an intended Wordpress behavior? In other words, is it "normal" that Wordpress doesn't pick up the right template when multiple custom post types are specified?
    – grazdev
    Commented Nov 21, 2017 at 14:30
  • I think it's because the rewrite found cat before dog and when it didn't find a matching archive-cat.php, the templating system did what it is supposed to do an fell back to archive.php. Might be work reversing the order in the query just to see if that makes a difference
    – Welcher
    Commented Nov 22, 2017 at 14:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.