3

I have a sub-directory in my Wordpress theme (there are a lot of pages and I want a more logical structure). I have a custom post type called "entry" but if I place the archive-entry.php template in my sub-directory it is no longer picked up by the theme.

Is there a way I can put my custom post type archive templates in a sub-directory?

2

Unlike page templates, WordPress doesn't look in subdirectories for post template pages. The base function used for locating such templates is locate_template() (see source), which looks in the root directory of your theme (and parent theme).

(On the other hand get_page_templates() searches sub-directory).

You can use template_include filter (which filters the absolute path to your template) to change the template used:

add_filter( 'template_include', 'wpse119820_use_different_template' );
function wpse119820_use_different_template( $template ){

   if( is_post_type_archive( 'entry' ) ){
       //"Entry" Post type archive. Find template in sub-dir. Look in child then parent theme

       if( $_template = locate_template( 'my-sub-dir/archive-entry.php' ) ){
            //Template found, - use that
            $template = $_template;
       }
   }            


   return $template;
}
  • Strange, I thought I tried this! Anyway this works for me now. Thanks! – benedict_w Oct 24 '13 at 15:59
  • Minor performance note: template_include fires AFTER WordPress has already gone through the trouble of trying to locate the template file. So I wouldn't recommend doing this if it's just to make your folders pretty. – Curtis Oct 30 '17 at 16:55
1

As explained by @StephenHarris, the template loader does not do this by default.

While Stephen's answer looks fine to me, I was working on one before he posted and it is a bit different. I used the archive_template hook and generated the template name using get_queried_object.

add_action(
  'archive_template',
  function($template) {
    $path = pathinfo($template);
    if (!empty($path['filename'] && 'archive' === $path['filename']) {
      $pg = get_queried_object();
      if (!empty($pg->name)) {
        $t = locate_template('archive/'.$pg->name.'.php');
        if (!empty($t)) {
          $template = $t;
        }
      }
    }
    return $template;
  }
);

It is rough code. It may be buggy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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