Click here to go back to our child theme setup index.
So far in our child theme series we’ve looked at how to create a basic child theme and also how to take it a bit further by overriding template files. This time we’re going to look at some more advanced usage by replacing functions in a parent theme with a new one in our child theme.
For an example we’re going to replace the featured product widget that’s in our Elite theme with one that’s in our child theme. We’ve already copied the actual file to our child theme and made the changes there. But unlike file like single.php or page.php, WordPress seems to ignore the file in our child theme. That’s because the file in the parent theme is loaded via a function. So to change the function, we need to override it with a new one in the child theme. Here’s how to do that.
- Create a functions.php file in your child theme. Start the file off with
<?php
- Next copy the function from the parent theme that contains the loading of the widgets and paste it into the child theme’s functions.php file. In our Elite theme it looks like this:
// Load Other Files if ( ! function_exists( 'elite_files' ) ):function elite_files() { // include required files include(get_template_directory()."/includes/fonts.php"); include(get_template_directory()."/includes/titles.php"); include(get_template_directory()."/includes/images.php"); include(get_template_directory()."/includes/queries.php"); include(get_template_directory()."/includes/scripts.php"); include(get_template_directory()."/includes/body-tag.php"); include(get_template_directory()."/includes/custom-js.php"); include(get_template_directory()."/includes/shortcodes.php"); include(get_template_directory()."/includes/custom-css.php"); include(get_template_directory()."/includes/author-fields.php"); include(get_template_directory()."/includes/content-limit.php"); include(get_template_directory()."/includes/tha-theme-hooks.php"); include(get_template_directory()."/includes/theme-customizer.php"); include(get_template_directory()."/includes/comment-functions.php"); include(get_template_directory()."/includes/custom-meta-boxes/elite.php"); // Custom Post Types include(get_template_directory()."/includes/post-types/staff.php"); include(get_template_directory()."/includes/post-types/slides.php"); include(get_template_directory()."/includes/post-types/testimony.php"); include(get_template_directory()."/includes/post-types/admin-style.php"); // include widgets include(get_template_directory()."/includes/widgets.php"); include(get_template_directory()."/includes/widget-page.php"); include(get_template_directory()."/includes/widget-posts.php"); include(get_template_directory()."/includes/widget-video.php"); include(get_template_directory()."/includes/widget-social.php"); include(get_template_directory()."/includes/widget-product.php"); include(get_template_directory()."/includes/widget-testimony.php"); include(get_template_directory()."/includes/widget-attention.php"); include(get_template_directory()."/includes/widget-featured-page.php"); include(get_template_directory()."/includes/widget-facebook-like-box.php"); } endif; // elite_files add_action( 'after_setup_theme', 'elite_files' );
It’s very important that the function begins with a statement like
if ( ! function_exists( 'elite_files' ) ):
If it does not, then you won’t be able to override it with the child theme using this method.
- Find the line that loads the widget you’d like to use. For the Featured Product widget, it’s
include(get_template_directory()."/includes/widget-product.php");
- WordPress has two functions that do similar things. The get_template_directory() function will load a file from the parent theme. The get_stylesheet_directory() function will load from the child theme if there is one. So, we’ll want to change
include(get_template_directory()."/includes/widget-product.php");
to
include(get_stylesheet_directory()."/includes/widget-product.php");
- Save your changes.
That should cause WordPress to load our new widget from the child theme instead of the parent. Now we can make any changes to the widget without worrying about losing them in an update.
You can take this principal and make other changes to the theme’s functionality this way. Sometimes when I need to modify the extra metaboxes in a theme, I will use this method to load a new copy of them from a child theme by overriding the function that loads them in the parent.
So that’s a quick run-through of how to make changes to a theme’s functionality by using a child theme. With these tools you should be able to do just about anything you want to with a child theme now.
Shannon June 9, 2016
This is just what I was looking for! Thank you for the missing piece of the puzzle 🙂
louis October 29, 2015
Hello Bill,
Apologies for being so late here, what i’m trying to do is adjust some lines in my parent themes widgets.php via the use of a child theme.
I went to functions.php in my parent and copied the line that says
include get_template_directory() . ‘/inc/widgets.php’;
(this line is not in an if statement)
and I paste it in to my functions.php in child theme and changed it to
include get_stylesheet_directory() . ‘/inc/widgets.php’;
to call the edited widgets.php that is in my child theme.
Didn’t work, do you know where I’m going wrong?
Bill Robbins October 29, 2015
Hi Louis,
Great question. In order to override a function, like the code inside widgets.php with a child theme, the code in the parent theme has to be inside an if statement or can be modified via a filter.
Since that line isn’t in a if statement in your parent theme, here’s what I would do. I would suggest commenting out that line in the parent theme by adding this:
//
at the beginning of the line. That way when you go to load it in your child theme that code won’t have been loaded in the parent too. You might ask the developer to wrap that function in an if statement so you can override it more easily in the future.
Hope that helps,
Bill
Neko June 7, 2015
Hello Bill, I hope it’s not too late to ask a question concerning this.
I’ve been running through the code for a theme I’m working with, but I can’t seem to find anything suitable to replace ‘elite_files’. What would that function look like normally, and would it be found in the functions.php file? It might be that the theme just doesn’t support editing widgets, but I thought I’d ask just in case I was missing something.
Great tutorial by the way. I can’t believe no one really thought to explain this so thoroughly until now. Thanks for your hard work!
Bill Robbins June 8, 2015
Hey Neko, not too late to ask at all. It sounds like the widget is being loaded from that function in the functions.php file. If the function is wrapped with something like this:
if ( ! function_exists( 'elite_files' ) ):
then what you can do is copy the actual function from the parent theme and place it in the child theme. Keep it just like it is, except for the call that loads the widget you want to change. Say it looks like this:
include( get_template_directory()."/includes/widget-social.php" );
What you would do there is change the get_template_directory (which tells WordPress to look inside the parent theme) to get_stylesheet_directory (which tells WordPress to look in the child theme if it exists). Then you can copy the widget file to the child theme, keeping the same directory structure and edit away.
Hope that helps out 🙂
manisha April 11, 2015
Hi, First of all thanks for this nice tutorial.
I did everything in a same way you explained and after that I got the same issue cannot redeclare class. After that I fixed this via renaming the class. But after that I am seeing same content twice.
Like this is the class: new HRB_Edit_Profile_Social_Meta_Box_child
n new HRB_Edit_Profile_Social_Meta_Box being called from parent theme. This is how I am getting content twice. Could you please suggest me some solution in able to fix this duplicacy.
Hope you get my issue. Looking for solution asap.
Thank you
Bill Robbins April 13, 2015
Good Morning Manisha,
It sounds like the original theme wasn’t set up to allow you to replace this function. You discovered that simply copying the function caused things to crash since it duplicates the name. But changing the name of the function in the child theme, only duplicates the output because WordPress doesn’t know that you’re trying to override an existing function.
One option would be to look and see if there are any functions that load this one that are wrapped in a if_exists statement. You may have to replace a higher up function in order to cause this to work.
If that’s not possible, then you’ll have to edit the parent theme directly. A WordPress theme has to be created in a certain way for this type of customization to be possible. The author of the theme may not have done that. If they haven’t there’s not much you can do. This part depends on them
Just keep a separate copy of your customizations in case you need to add them again after an update. It’s not ideal, but it may be your only real option.
Bill
alan March 24, 2015
Hi Bill,
Very helpful, but I am having an error :
I have added code :
include(get_template_directory().”/inc/widgets/widgets.php”);
but error is :
Fatal error: Cannot redeclare spacious_widgets_init() (previously declared in /home/url/wp-content/themes/spacious/inc/widgets/widgets.php:17) in /home/url/wp-content/themes/spacious-child/inc/widgets/widgets.php on line 166
it seems both file widgets.php are called ?
Thanks
Bill Robbins March 25, 2015
Good question. It sounds like the function that sets up widgets is not wrapped in a conditional “if exists” statement. So that’s causing two functions to have the same name which isn’t allowed.
You can change the name of the spacious_widgets_ir function that’s in your child theme. It’ll likely be in that file twice so change it in both spots.
That should let that function work, though it won’t replace the one in the parent. The parent theme needs to have the “if_exists” conditional for replacement to be pissible.
Francis January 6, 2015
The explanation really clear things up for me before diving in creating my own child-theme wp. Thanks for sharing.
Bill Robbins January 6, 2015
I’m glad that helped out Francis 🙂
Steve December 4, 2014
Very helpful! In the WP Codex they don’t really explain how to override enqueued files. They make it sound like any replacement file you put in the child theme will be selected automatically, but that only works for template files in the WP hierarchy.
Still, I feel like child themes is missing a level of granularity. If a function in my parent theme is updated, my child theme is still using the modified function from before the update.
Bill Robbins December 4, 2014
Glad that helped you out. Child themes do help out a good bit with updating, but it is a solution with compromises.