Same template for several custom post types

Hello

I have several custom post types that share archive and single templates but being different from the usual single post.

The WordPress way would be to create one archive and single php for each CPT with the same content. But which would be the roots DRY way? Should I modify base.php? Or should I do some kind of

    if ( "cpt1"  === $post->post_type
            || "cpt2"  === $post->post_type
            || "cpt3"    === $post->post_type
            || "cpt4"    === $post->post_type
            || "cpt5"    === $post->post_type
          ) :
    
      get_template_part( 'templates/content', 'archive-cpts' );

in index.php and something similar in single.php?

Any other suggestion?

Thanks

It’s a judgement call. For minor changes between templates, I would use a conditional. For major changes I would use a new template.

In your case I would probably create archive-custom.php and filter template_include to get the CPTs to use it. With the singles I would probably just edit single.php and load the custom content via get_template_part.

I would definitely tidy up your logic and remove it from the templates though, so that it can be reused.

1 Like

You mean with my own wrapper and priority lower than 99 right??
Thanks a lot

I also think minor changes can go into the file, until it starts to look messy, then you’ll need to move it to new files.

Not sure what you mean by your own wrapper, but the priority needs to be less than 99 for the Roots wrapper to find the appropriate base file.

The point is that base file is the same one (same heading, logo, footer, etc, but the changing part is the content so: Can I create a function that selects a custom-archive-for-several-cpt.php instead of index.php or archive.php, having just one base.php???

Nevermind, (I leave my previous paragraph just in case it might help others). I just realized that with template_include we are modifying what we are calling from base.php include roots_template_path();, right? So we have just one base.php.

Please, could you tell me if this is the right way, including the filter call, in /lib/custom.php

    function custom_cpt( $template ) {
    if ( "cpt1"  === $post->post_type
            || "cpt2"  === $post->post_type
            || "cpt3"    === $post->post_type
            || "cpt4"    === $post->post_type
            || "cpt5"    === $post->post_type
          ) :
         $new_template = locate_template( array( 'custom-archive-for-several-cpt.php' ) );
    		if ( '' != $new_template ) {
    			return $new_template ;
    		}
    	}
    endif;
    
        	return $template;
        }
    
    add_filter('template_include', 'custom_cpt', 98);

and then in custom-archive-for-several-cpt.php just the content between

    <main class="main <?php echo roots_main_class(); ?>" role="main">
    
    </main>

Thanks

1 Like

Rather than access the global variable, you’re probably better off using get_post_type() and you don’t need to call it umpteen times.

Either use in_array or set it to a variable scoped to the function.

Perfect, I assume the rest is correct right?
The return $template and add_filter('template_include', 'custom_cpt', 98); is the part I had doubts about.

Thanks a lot for your support.

The rest looks fine. The easiest way is to test it on your dev server.

Perfect. It is working fine:

function template_productos( $template ){
  if ( in_array( get_post_type(), array( "cpt1", "cpt2", "cpt3") ) ) :
    $new_template = locate_template( array( "templates/cpt-template.php" ) );
    if ( "" !== $new_template ) {
      return $new_template ;
    }
    endif;
    return $template;
}
add_filter( 'template_include', 'template_productos', 98 );

Really seeing the potential of working like this in terms of organisation and workflow.

I don’t find how to close this thread… Thanks for your support!

I’m doing a very similar thing. Which is to render the same template file for the singular view of a few different post types. It works fine, however, the Show Current Template plugin thinks single.blade.php template is being used instead. It all works fine, but it’s just a little confusing. Am I doing this right?

add_filter('template_include', function( $original_template ) {

    if ( is_singular( [ 'audio-video', 'print', 'brands', 'digital-social', 'integrated', 'experiential' ] ) ) {
        return locate_template( ['views/project-single.blade.php'] );
    } else {
        return $original_template;
    }
});