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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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