Deathstorm
Deathstorm

Reputation: 847

Wordpress template files in subdirectory's

A while ago i started a new Wordpress project. But i got into an issue. Since there are multiple designs i need to create multiple templates for pages, posts and text format outputs for on the different page-templates.

So since the're are so many template files i wanted to create some subdirectory's. i know that since Wordpress 3.4 and higher you're able to use the subdirectory name page-templates for all the page templates but how could i use that for the format files and for the post files.

Yes i did try to add functions like:

 get_template_part('/template-parts/page-templates' , 'page');

And

require( get_template_directory() . '/template-parts/template-tags.php' );

The ideal directory structure i would like to create is as follows:

wp-content/themes/mytheme
- archive
- 404
- CSS
- JS
- Images 
- template-parts (dir)
-- page-templates (dir for page-template files.)
-- format-templates (dir for format-templates.)
-- post-templates (dir for post-templates.)
- header
- footer

So to be clear. I want to create the structure for template files like above. Don't mind the folders like CSS etc. Those are set the correct way. The intention is, after i've succesfully created the structure, to be able to select the templates like a page temple from the /wp-admin edit page section.

Upvotes: 10

Views: 6571

Answers (6)

Vincent Wasteels
Vincent Wasteels

Reputation: 1588

wrapping up the accepted answer in a working piece of code :

<?php

/* Pages templates in sub folders */
/* --------------------------------------------------------------------------------- */

add_filter('theme_page_templates', function($post_templates) {
  $directories = glob(get_template_directory() . '/pages/*' , GLOB_ONLYDIR);
  
  foreach ($directories as $dir) {
    $templates = glob($dir.'/*.php');

    foreach ($templates as $template) {
      if (preg_match('|Template'.' '.'Name: (.*)$|mi', file_get_contents($template), $name)) {
        $post_templates['/pages/'.basename($dir).'/'.basename($template)] = $name[1];
      }
    }
  }

  return $post_templates;
});

This could be enhanced with a recursive function, for now it only adds :

./pages/\*/\*.php

Upvotes: 0

Jeremy Tarpley
Jeremy Tarpley

Reputation: 86

I know this is an old question that already has an answer but it wasn't the solution I was looking for. Adding another option in case anyone else is searching for a way to move all WordPress template files to a subfolder. Found this code for changing the default folder for WordPress template files on Reddit and made a few small adjustments. This code can be placed in the functions.php of your theme or child theme.

/**
 * Tell WordPress that we have moved default template files to the page-templates folder.
 * Based on code from: https://www.reddit.com/r/Wordpress/comments/ffhjvw/moving_wordpress_theme_template_files_to/
 *
 * Related posts with other solutions:
 * https://stackoverflow.com/questions/60589503/moving-wordpress-theme-template-files-to-subdirectory
 * https://wordpress.stackexchange.com/questions/17385/custom-post-type-templates-from-plugin-folder
 * https://wordpress.stackexchange.com/questions/291725/store-page-template-files-in-a-subfolder
 * https://wordpress.stackexchange.com/questions/312159/how-to-move-page-template-files-like-page-slug-php-to-a-sub-directory/312611#312611
 * 
 * Template hierarchy info: 
 * https://developer.wordpress.org/reference/hooks/type_template_hierarchy/
 * https://core.trac.wordpress.org/browser/tags/5.8.1/src/wp-includes/template.php
 * https://developer.wordpress.org/themes/basics/organizing-theme-files/#page-templates-folder
 *
 * @param array $templates A list of candidates template files.
 * @return string Full path to template file.
 */
function change_template_path($templates) {

  // The custom sub-directory for page templates in your theme. 
  $custom_sub_dir = 'page-templates';

  // Don't use the custom template directory in unexpected cases.
  if(empty($templates) || ! is_array($templates)) {
    return $templates;
  }

  $page_template_id = 0;
  $count = count( $templates);
  if($templates[0] === get_page_template_slug()) {
    // if there is a custom template, then our page-{slug}.php template is at the next index
    $page_template_id = 1;
  }

  // The last one in $templates is page.php, single.php, or archives.php depending on the type of template hierarchy being read.
  // Paths of all items starting from $page_template_id will get updated
  for($i = $page_template_id; $i < $count ; $i++) {
    $templates[$i] = $custom_sub_dir . '/' . $templates[$i];
  }

  return $templates;
}

// Add filters to override the path for each WP template hierarchy.
// These are all the template hierarchy filters. You should probably only override the ones you need.
add_filter('404_template_hierarchy', 'change_template_path');
add_filter('archive_template_hierarchy', 'change_template_path');
add_filter('attachment_template_hierarchy', 'change_template_path');
add_filter('author_template_hierarchy', 'change_template_path');
add_filter('category_template_hierarchy', 'change_template_path');
add_filter('date_template_hierarchy', 'change_template_path');
add_filter('embed_template_hierarchy', 'change_template_path');
add_filter('frontpage_template_hierarchy', 'change_template_path');
add_filter('home_template_hierarchy', 'change_template_path');
// If you override the index hierarchy, be sure to add an index.php template in your custom template folder.
add_filter('index_template_hierarchy', 'change_template_path'); 
add_filter('page_template_hierarchy', 'change_template_path');
add_filter('paged_template_hierarchy', 'change_template_path');
add_filter('privacypolicy_template_hierarchy', 'change_template_path');
add_filter('search_template_hierarchy', 'change_template_path');
add_filter('single_template_hierarchy', 'change_template_path');
add_filter('singular_template_hierarchy', 'change_template_path');
add_filter('tag_template_hierarchy', 'change_template_path');
add_filter('taxonomy_template_hierarchy', 'change_template_path');

Upvotes: 2

hwl
hwl

Reputation: 373

WP_Theme class contains the method get_page_templates() that offers this filter:

apply_filters( "theme_{$post_type}_templates", $post_templates, $this, $post, $post_type );

line 1103 of class-wp-theme.php

Keeping in mind that in wordpress post and page are post_types,

add_filter( "theme_post_templates", ... and add_filter( "theme_page_templates",... should be valid.

Under the codex's "Used By" section for that method, it states:

wp-admin/includes/template.php: page_template_dropdown()

wp-admin/includes/meta-boxes.php: page_attributes_meta_box()

Which leads me to believe it would make them available on the /wp-admin/ edit page section.

Info from core files regarding the filter:

 * Filters list of page templates for a theme.
 *
 * The dynamic portion of the hook name, `$post_type`, refers to the post type.
 * @since 4.7.0 Added the `$post_type` parameter.
 *
 * @param array        $post_templates Array of page templates. Keys are filenames,
 *                                     values are translated names.
 * @param WP_Theme     $this           The theme object.
 * @param WP_Post|null $post           The post being edited, provided for context, or null.
 * @param string       $post_type      Post type to get the templates for.

I'm unsure if a relative uri works here or if you need get_theme_file_path(), but am assuming the former.

function deep_templates( $post_templates, $theme, $post, $post_type )
   $post_templates['/folder/folder/folder/file.php'] = "Page Style One";
   $post_templates['/folder/other-folder/file.php']  = "Page Style Two";
   return $post_templates;
add_filter( 'theme_page_templates', 'deep_templates' );

AND/OR

add_filter( 'theme_post_templates', 'deep_templates' );
add_filter( 'theme_my-custom-cpt_templates', 'deep_templates' );

Upvotes: 8

Asley Arbolaez
Asley Arbolaez

Reputation: 9

You need to create a Template file(inside "page-templates" directory) for each diferent design you will have.

For creating a template file accessible from de Backend(wp-admin) you need to add:

<?php
/*
Template Name: TEMPLATE-NAME
*/
?>

in the top of each file(template). Then inside each file, you can add the blocks or modules of the design using get_template_part() function.

Upvotes: -1

WizardCoder
WizardCoder

Reputation: 3461

Here is an example of what you need to do.

- directory1 (dir)
-- directory2 (dir)
--- template-file.php

To access this template with get_template_part you would do this:

get_template_part( 'directory1/directory2/template', 'file' );

'directory1/directory2 defines the directory structure. template' is the string before the - in the template name. 'file' is the string after the dash in the template name.

So in your case if you had a template file called page-contact.php in your page-templates directory, you would use.

get_template_part('template-parts/page-templates/page' , 'contact');

Upvotes: 4

stevenkellow
stevenkellow

Reputation: 75

get_template_part will only work as part of a WordPress THEME.

What you'll want to do is create your own WordPress theme, (which lives in wp-content/themes/ ) which you can then use for any PHP templates, CSS resources etc. that you want.

You can check out how to build a WordPress theme and include everything in the codex here.

Upvotes: -1

Related Questions