11

I'm working on a child theme, I strongly prefer not to override the main template files in order to maintain simplicity of the child theme as well as minimize the amount of code and maintenance over time.

In the loop, the index.php template in parent theme uses: get_template_part( 'content' );

which will bring in content.php, I'm looking to have it behave more like get_template_part( 'content', get_post_format() ); or similar in order to bring in different templates such as content-aside.php, etc, without creating an index.php in the child theme to overwrite the parent for a single line change.

get_template_part() consists of:

function get_template_part( $slug, $name = null ) {

    do_action( "get_template_part_{$slug}", $slug, $name );
    $templates = array();
    $name = (string) $name;
    if ( '' !== $name )
        $templates[] = "{$slug}-{$name}.php";

    $templates[] = "{$slug}.php";
    locate_template($templates, true, false);
}

So there's an action available, in my case called get_template_part_content

I can hook onto the action with something like:

add_action( 'get_template_part_content', 'child_post_styles', 10, 2 );

function child_post_styles ( $slug, $name ) {
    if( false == $name ){
        $name = get_post_format();
        $templates = array();
        if ( '' !== $name )
            $templates[] = "{$slug}-{$name}.php";

        $templates[] = "{$slug}.php";
        locate_template($templates, true, false);
    }
}

This obviously results in post duplication, one from my hooked function, which can display the desired template, and the other from the normal locate_template call in get_template_part()

I'm having trouble finding a way to accomplish this without duplication, or without ending page render right after serving my template part by doing something stupid such as a break or exit

  • Check this post – Pieter Goosen Jul 8 '14 at 19:00
  • 3
    Welcome to miserable life without template inheritance. :) – Rarst Jul 8 '14 at 19:54
3

There is no hook to do this. Copy the index.php to the child theme and make the single line change. Also, tell the parent theme's author that they should make the same change in their theme, for flexibility.

  • This is false now, see @t-toudua answer here – Ivan Castellanos Dec 14 '16 at 0:20
  • His answer is not a solution, because the template part still loads and includes. The action hook cannot override that. – Otto Dec 14 '16 at 13:27
  • True, but you could use ob_start inside it and the ob_end at some later hook so its executed but never echoed, which usually is good enough. Or you could use exit() to force terminate PHP (after you manually add everything still missing: footer, etc) – Ivan Castellanos Dec 15 '16 at 0:04
  • And that is still not a solution. Suppressing output is not the same as overriding things. – Otto Dec 17 '16 at 7:39
  • Exiting doesn't suppress output; it effectively stops execution at that point. – Ivan Castellanos Dec 18 '16 at 15:09
6

I think it's not exactly possible the way you want to achieve. It's really annoying to not getting a filter there to alter template files names :(

I have a workaround on it though. Let use content.php for the comparison.

// content.php file 
$format = get_post_format();
if( '' != $format ){
    get_template_part( 'content-'. $format );
}
else{
    get_template_part( 'content-default' );
}

I haven't used the second argument of get_template_part function, rather i passed suffix on the first argument to avoid infinitive calls on content.php file if there's no 'content-'. $format file.

  • I think this is a good way to do that. Not sure why it's not accepted :) – Anh Tran Jul 16 '14 at 2:17
  • Reputation matters, maybe :) – Shazzad Jul 16 '14 at 15:23
  • Sorry @Shazzad, I gave your answer an upvote though as it is very clever :) If I could accept two, I would. – TomHarrigan Jul 22 '14 at 14:19
3

Well, there is SOLUTION:

add_action('init', function(){ remove_all_actions('get_template_part_content'); });
add_action('get_template_part_content', 'yourFunc', 99, 2 );
function yourFunc ( $slug, $name ) {

    .........any codes here.............
    if ($name == 'header'){
       //but this will be executed before loading template... At this moment, Wordpress doesnt support any hooks for before/after LOAD_TEMPLATE...
    }
}

but think carefully, in which hook you should insert that action... to manually get location, use, i.e. locate_template('content-header.php', false);

0

If you want to pull in a file called content-aside.php you call the function like this:

get_template_part( 'content', 'aside' );

The second parameter is the name of the filer after the hyphen. If your file is in a sub-directory (templates/content-aside.php):

get_template_part( 'templates/content', 'aside' );

Is that what you're looking to do?

  • Thanks, I understand that. I'm looking to not have to create an index.php in the child theme to overwrite the parent themes index.php for a single line change. It adds more maintenance to the child theme. Hoping to accomplish via a hook if possible. – TomHarrigan Jul 8 '14 at 18:22

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.