6

Let's say I've the following file in my parent theme folder: 'theme-folder/inc/custom.php'

Then I created a child theme.

How can I check if that file exists in the child theme, then fetch it, otherwise fetch it from the parent theme?

get_template_directory() always fetches the file from the parent theme.

While get_stylesheet_directory() requires the file to exists in the child theme.

3

locate_template will attempt to find the specified file in the child theme, and fall back to the parent theme if it does not exist:

locate_template('inc/custom.php', true);

Setting the second parameter to true causes it to require the file instead of just determining the path.

As the name suggests, locate_template is meant for loading template files. It has some additional overhead that you most likely don't need for loading libraries. A stripped down version would be:

function load_theme_file($path) {
    if ( file_exists( STYLESHEETPATH . '/' . $path )) {
        include( STYLESHEETPATH . '/' . $path );
    } else {
        require( TEMPLATEPATH . '/' . $path );
    }
}

Usage:

load_theme_file('inc/custom.php');

Edit: I just wanted to provide a quick note about potential issues with this overall approach.

Letting a child theme override files works well for templates, but for libraries there is more room for error. If a child theme needs to modify a single function, you would have to copy that entire file, overriding every function in that file in the process.

If the parent theme is updated and changes have been made to any of the functions in the overwritten file it can cause problems. You can mitigate this issue by breaking up your libraries into smaller chunks, but that can make your code base harder to maintain.

A better solution, in my opinion, is to use an object oriented approach. Allow a child theme to extend classes you define and then use the child theme's class. In the implementing classes the child theme would only have to define methods it needs to overwrite. In the parent theme you could specify which methods should not be overwritten by making them final.

You can also mitigate the need for child themes to replace entire files by using filters and actions generously.

  • I think I'm going to use load_theme_file function. Does it have any drawbacks? – Ahmed Saad Jun 19 '15 at 15:06
  • 1
    @AhmedSaad Nothing comes to mind. For what you are trying to do I can't think of a more straightforward approach. – Mathew Tinsley Jun 19 '15 at 15:15
  • Apparently, include inside this function is not the same as include outside it. Looks like I've to use global for some variables in the included file. Is it normal? – Ahmed Saad Jun 19 '15 at 15:43
  • 1
    One of the things locate_template does is import some global variables into the current scope. I stripped that out because for libraries this isn't necessary; a function would have to import the variable regardless. If you need access to all of those variables without importing them use locate_template. – Mathew Tinsley Jun 19 '15 at 15:45
  • 1
    @AhmedSaad I added a note about potential drawbacks. – Mathew Tinsley Jun 19 '15 at 16:07
2

get_template_part() would do that, if I understand your question.

get_template_part('inc/custom');

It is sort of built to do exactly that, if I am reading you right:

Makes it easy for a theme to reuse sections of code and an easy way for child themes to replace sections of their parent theme.

  • I heard that you should use require_once instead of get_template_part for including your custom php files in the theme. – Ahmed Saad Jun 19 '15 at 4:36
  • 2
    Why? Where did you hear that? – s_ha_dum Jun 19 '15 at 5:03
  • 1
    @AhmedSaad very probably reason you heard that is get_template_part don't use require_once, but require, it means that in theory a lib may be required more than once using get_template_part. Note that the answer you accepted uses include as well (instead of include_once or require_once, that's better). Moreover, you don't need to manually throw exception using require_once because require_once will do that for you. – gmazzap Jun 19 '15 at 11:29
  • 1
    "This is absolutely the wrong way to load function files. Please do not do this. That’s a template-loading function, which will allow child themes to overwrite the file." -- the point being made is conditional. It is wrong because the child theme can overwrite the file. However, in your case, that is exactly what you want to happen. Doing things the way you are, with the accepted answer, is just rewriting code already in place. – s_ha_dum Jun 19 '15 at 14:45
  • 1
    I just did correct you. You are doing exactly the same thing you are just writing new code to do it. If you don't want a child to overwrite the file use include or require. If you do, use get_template_part() or reinvent the wheel. Your choice. – s_ha_dum Jun 19 '15 at 15:16

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.