Skip to main content

The Right Way to Override Theme Functions

I started building my first WordPress site last week and almost immediately starting customizing the theme. Rather than editing the default theme directly, however, I created a child theme, basing it off one of the many theme frameworks available for WordPress. Creating the child theme was painless, and there is plenty of information on how to do so.

Pretty soon though, I got to the point where tweaking CSS rules wasn’t going to cut it: I needed to go deeper. I needed to change some of the functions in the parent theme. But while there was plenty of information on creating child themes, information on overriding theme functions was nowhere to be found. The closest I came was this helpful post.

This is an odd disconnect. How could there be so much information on one part of a best practice (creating a child theme), but basically none on how to make that best practice really work?

I can’t answer that question. But I do have my own version of how to override theme functions in WordPress – The Right Way.

The Child is the Father of the Man

(Bonus points if you get the reference.)

Here’s the basic outline for what I think is the Right Way To Do It:

  1. Copy (in full) the function you want to override from the parent theme.
  2. Paste it into functions.php in the root of your child theme’s folder. If functions.php doesn’t exist, create it.
  3. Rename the function from parent_theme_function to child_theme_function.
  4. Deactivate the parent function.
  5. Activate the child function.

The first three steps are self-explanatory, so I’ll just cover the last two steps.

Deactivate the Parent Function

There are actually two steps here. First, create a one-line function that removes the parent function from its “phase”. Then, add that one-line function to WordPress’ bootstrap phase (‘init’), so that the parent function actually gets removed.

Confused? Don’t worry. Here’s an example of how you would remove the thematic_blogtitle() function from the Thematic theme. Code comin’!

// Remove the default Thematic blogtitle function
function remove_thematic_actions() {
    remove_action('thematic_header','thematic_blogtitle',3);
}
// Call 'remove_thematic_actions' (above) during WP initialization
add_action('init','remove_thematic_actions');

In this case, we are removing the parent theme function (thematic_blogtitle) from the thematic_header phase.

How do you know what the proper phase is? Look for a line like this in the parent function’s theme files:

add_action('phase','function', 'priority');

You can usually find this right after the function’s declaration. The line that adds thematic_blogtitle looks like this:

add_action('thematic_header','thematic_blogtitle',3);  

Note that you have to use the same priority that was used to add the function in the parent theme (in this case, 3) when you remove it. If no priority was used in the original add_action, you can skip it.

Activate Your Child Function

To replace thematic_blogtitle, we just need to tell WordPress to call our child theme function in the place where it used to call the parent theme function. So, if our new function were called fancy_theme_blogtitle, we would add the following to functions.php:

add_action('thematic_header','fancy_theme_blogtitle', 3);

Save functions.php and voila! The code from fancy_theme_blogtitle is run instead of the code from thematic_blogtitle, and we didn’t have to hack the parent theme. This is crucial, because if there is ever an update to Thematic, we can get all the upgradey goodness without having to worry about how it will affect our child theme. Excellent!

All Together Now

Putting all the code together:

// Removes thematic_blogtitle from the thematic_header phase
function remove_thematic_actions() {
    remove_action('thematic_header','thematic_blogtitle',3);
}
// Call 'remove_thematic_actions' during WP initialization
add_action('init','remove_thematic_actions');

// Add our custom function to the 'thematic_header' phase
add_action('thematic_header','fancy_theme_blogtitle', 3);

Know a Better Way?

As I stated previously, I’ve only been using WordPress for about a week. If you know a better way to do this, by all means, please let me know!

Awesome!!!

Thanks so much! I just ran into exactly this problem and was just about to give up and hack the Thematic functions up.

Your fix saved me some headaches. I’ll be trying it out now…

modify functions.php

I’m trying to separate the parent of the child theme, I try to modify functions.php (hybrid theme, and child theme), and doing it alone.
Hybrid theme is the parent, Critical theme is the child, i try to make one but with the characteristics of the child,
is this possible?

dsf

You can join the theme club for free or pay a minimal yearly fee to get help and in-depth tutorials on customizing your site.

Wow

After burning a lot of time looking for a way to custom replace a footer display function without touching the update-prone php code of the parent theme, I thankfully found this page and gave its info a try in a WP 3.0 child theme. It worked beautifully! Thank you.

A small modification

This works great for some, but not all themes because in some cases the parent functions.php contains functions that kick in too quickly. For example if you were to try to replace twentyten_widgets_init() you would not be able to with the script above. That’s because the child functions.php is called before the parent functions.php, so even if you unhook the function it gets rehooked later on. To fix this change init to after_setup_theme in the remove action call like this:

// Call 'remove_thematic_actions' during WP initialization
add_action('after_setup_theme','remove_thematic_actions');

I found this tip at http://ottopress.com/2010/wordpress-protip-child-themes/

What if this was the code I wanted to override?

Hi,
In my theme the code below is what I would want to override in a child theme functions.php… Using your method… How would I do this? … (I’m no php ace :-(

// Sidebars:
if ( function_exists('register_sidebar') ) {
    register_sidebar(array(
        'name'=>'Left Sidebar',
        'before_widget' => '<div id="%1$s" class="widget %2$s"><div class="menutop">&nbsp;</div>',
        'after_widget' => '<div class="menubottom">&nbsp;&nbsp;</div></div>',
        'before_title' => '<div class="widget-title"><h3>',
        'after_title' => '</h3></div>',
    ));
    register_sidebar(array(
        'name'=>'Right Sidebar',
        'before_widget' => '<div id="%1$s" class="widget %2$s"><div class="menutop">&nbsp;</div>',
        'after_widget' => '<div class="menubottom">&nbsp;&nbsp;</div></div>',
        'before_title' => '<div class="widget-title"><h3>',
        'after_title' => '</h3></div>',
    ));
    register_sidebar(array(
        'name'=>'Left Inner Sidebar',
        'before_widget' => '<div id="%1$s" class="widget %2$s"><div class="menutop">&nbsp;</div>',
        'after_widget' => '<div class="menubottom">&nbsp;&nbsp;</div></div>',
        'before_title' => '<div class="widget-title"><h3>',
        'after_title' => '</h3></div>',
    ));
    register_sidebar(array(
        'name'=>'Right Inner Sidebar',
        'before_widget' => '<div id="%1$s" class="widget %2$s"><div class="menutop">&nbsp;</div>',
        'after_widget' => '<div class="menubottom">&nbsp;&nbsp;</div></div>',
        'before_title' => '<div class="widget-title"><h3>',
        'after_title' => '</h3></div>',
    ));

Hope you can help!
 Ken

Sorry!

The code tags didn’t seem to work…

Ken

unregister_sidebar()

Hi Ken,

I’m not sure whether you want to remove the sidebars or edit the before and after wrappers, but either way, I think you want to use unregister_sidebar().

For example, suppose you want to wrap titles in <h2>s in the Right Inner Sidebar instead of the current <h3>s. First, you would unregister the Right Inner Sidebar:

unregister_sidebar('Right Inner Sidebar');

Then, you would re-add the sidebar with your modifications:

register_sidebar(array(
    'name'=>'Right Inner Sidebar',
    'before_widget' => '<div id="%1$s" class="widget %2$s"><div class="menutop">&nbsp;</div>',
    'after_widget' => '<div class="menubottom">&nbsp;&nbsp;</div></div>',
    'before_title' => '<div class="widget-title"><h2>', /** Changed to <h2> **/
    'after_title' => '</h2></div>', /** Changed to <h2> **/
));

All of this would be done in functions.php in your child theme.

Override function by copying, if using function_exists() call

Some functions can be overridden simply by copying them into your functions.php of your child them, keeping the same name but making changes to the function. This works if the parent theme function is wrapped in “if function exists”.

twenty_ten_setup() is an example

  • To override twentyten_setup() in a child theme, add your own twentyten_setup to your child theme’s functions.php file.

if ( ! function_exists( 'twentyten_setup' ) ):

I found this at:
http://ideapress.googlecode.com/svn-history/r9/trunk/functions.php

where it states:
When using a child theme (see http://codex.wordpress.org/Theme_Development and http://codex.wordpress.org/Child_Themes), you can override certain functions (those wrapped in a function_exists() call) by defining them first in your child theme’s functions.php file. The child theme’s functions.php file is included before the parent theme’s file, so the child theme functions would be used.

This is incentive to always use function_exists() when writing functions for themes.

Also look for childtheme_override_

Hi Daniel,

Excellent tip. If you’re using twentyten as a base theme, I would certainly recommend using that method to override base theme functions.

Thematic handles the situation a little differently: instead of checking to see if the function has already been defined, Thematic looks for a specially named override function. Override functions in Thematic take the following format:

function childtheme_override_name_of_function_to_override()

Note that the name of the override function literally begins with childtheme_override. That’s not a placeholder as it would be in Drupal. To restate:

  • If your child theme is named graviton, then the name of the override function begins with childtheme_override.
  • If your child them is named nanobot, then the name of the override function still begins with childtheme_override.

Kind of lame, but hey. It’s a system.

so helpful

thaks for this post!

thaks for this post!

thaks for this post!

Most helpful

Exactly what I needed to know. Using hooks is a great technique, but there is a lack of “how-to” explanations. Thanks!

THANKYOU!!THANKYOU!!THANKYOU!

THANKYOU!!THANKYOU!!THANKYOU!!THANKYOU!!THANKYOU!!THANKYOU!!THANKYOU!!THANKYOU!!THANKYOU!!

In my child theme, I want to

In my child theme, I want to override this so I do this in the child theme’s functions.php file:

function childtheme_entry_title() {
.. my custom code here ..
echo apply_filters( ‘childtheme_entry_title’, $title );
}
add_action( ‘hybrid_before_entry’, ‘childtheme_entry_title’ );

Now, I get 2 entry titles on my posts - 1 from the Hybrid functions and 1 from my child theme functions.

How do I override the hybrid_entry_title() function with my childtheme_entry_title and still use the hybrid_before_entry hook?

Thanks in advance, PHP gurus.

Problem

I’m having the problem that when I add an override function in thematic, ie:

function childtheme_override_blogtitle() {
echo ’

override of blog title

’;
}
 add_filter(‘thematic_header’,’childtheme_override_blogtitle’);

the blog-title div is not added in the location that the standard blog-title div is; rather, it is appended at the end of the header. this doesn’t actually make much sense that this is happening to me at all… ideas?

figured it out!

i needed to set the priority in my add action call, ie:

function childtheme_override_blogtitle() {
echo ’

override of blog title

’;
}
 add_filter(‘thematic_header’,’childtheme_override_blogtitle’,3);

i had to add the 3!! not sure why. any ideaS?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <img> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre> <h1> <h2> <h3> <h4> <h5> <h6>
  • Lines and paragraphs break automatically.
  • Adds typographic refinements.

More information about formatting options