You have a lot of issues here.
-
Stay away from defining globals and constants if you can. The global scope is an evil place to be. WordPress has made a huge mess of the global scope already, don’t make it a bigger mess than it already is. You can make use a static variable inside your function/filter
-
Avoid using
TEMPLATEPATH
. You should useget_template_directory_uri()
. IIRC, there was a notice somewhere of future depreciation ofTEMPLATEPATH
, but citation is needed on this aslocate_template()
for one still usesTEMPLATEPATH
. But anyway, useget_template_path_directory_uri()
for parent themes, that is the correct way -
You would want to use
locate_template()
to search for a specific template, and notfile_exists
. Let WordPress handle WordPress stuff. Only use PHP (or for that matter custom SQL) if WordPress does not provide a native function/means of doing something. The native functions are there to take care of other stuff that you might be forgetting about when using custom PHPIn the new context, if we use
locate_template()
, we do not need to useget_template_directory_uir()
.locate_template()
by default handles that section for us. That is why it is important to use native WordPress functions to handle a specific jobYou have a double slash in your generated filenames. Your constant is
/single/
and your file name is/single.php
, which renders/single//single.php
. You need to remove a slash in iether of the two to avoid the duplicate slash -
single-{$post_type}.php
is by default used for custom post types -
If you are working with the post object of a single post page outside the loop, rather use
get_queried_object()
which is much more reliable than the$post
global. -
Although your syntax is valid, it is better to use curly brackets (
{}
) instead of the:
andendforeach
syntax. This also goes for the syntax of your conditionl statements. I prefer curlies as they are easy to debug should my code fail -
If you create a custom hierarchy like you have, always set
index.php
as your ultimate fallback template asindex.php
is required by all themes
Lets properly rewrite your code (NOTE: I’m using closures which have the downside that it cannot be removed by remove_filter()
, so change it to normal spaghetti if you wish.). We will be using the logic inside get_single_template()
to help us here
(The code requires PHP 5.4+ and is untested)
add_filter( 'single_template', function ( $template )
{
// Get the current single post object
$post = get_queried_object();
// Set our 'constant' folder path
$path="single/";
// Set our variable to hold our templates
$templates = [];
// Lets handle the custom post type section
if ( 'post' !== $post->post_type ) {
$templates[] = $path . 'single-' . $post->post_type . '-' . $post->post_name . '.php';
$templates[] = $path . 'single-' . $post->post_type . '.php';
}
// Lets handle the post post type stuff
if ( 'post' === $post->post_type ) {
// Get the post categories
$categories = get_the_category( $post->ID );
// Just for incase, check if we have categories
if ( $categories ) {
foreach ( $categories as $category ) {
// Create possible template names
$templates[] = $path . 'single-cat-' . $category->slug . '.php';
$templates[] = $path . 'single-cat-' . $category->term_id . '.php';
} //endforeach
} //endif $categories
} // endif
// Set our fallback templates
$templates[] = $path . 'single.php';
$templates[] = $path . 'default.php';
$templates[] = 'index.php';
/**
* Now we can search for our templates and load the first one we find
* We will use the array ability of locate_template here
*/
$template = locate_template( $templates );
// Return the template rteurned by locate_template
return $template;
});
EDIT
The code above is tested and working as expected.
EDIT 2 – Pre PHP 5.4 (T_Rex still roam the darkness)
add_filter( 'single_template', function ( $template )
{
// Get the current single post object
$post = get_queried_object();
// Set our 'constant' folder path
$path="single/";
// Set our variable to hold our templates
$templates = array();
// Lets handle the custom post type section
if ( 'post' !== $post->post_type ) {
$templates[] = $path . 'single-' . $post->post_type . '-' . $post->post_name . '.php';
$templates[] = $path . 'single-' . $post->post_type . '.php';
}
// Lets handle the post post type stuff
if ( 'post' === $post->post_type ) {
// Get the post categories
$categories = get_the_category( $post->ID );
// Just for incase, check if we have categories
if ( $categories ) {
foreach ( $categories as $category ) {
// Create possible template names
$templates[] = $path . 'single-cat-' . $category->slug . '.php';
$templates[] = $path . 'single-cat-' . $category->term_id . '.php';
} //endforeach
} //endif $categories
} // endif
// Set our fallback templates
$templates[] = $path . 'single.php';
$templates[] = $path . 'default.php';
$templates[] = 'index.php';
/**
* Now we can search for our templates and load the first one we find
* We will use the array ability of locate_template here
*/
$template = locate_template( $templates );
// Return the template rteurned by locate_template
return $template;
});