Thursday, October 29, 2020

A Guide to Overriding Parent Theme Functions in Your Child Theme

If you've had any experience working with parent and child themes in WordPress, you'll know that the template files in your child theme override those in your parent theme. For example, if your parent theme has a page.php file and you create a new one in your child theme, WordPress will use the one in the child theme when displaying pages.

You might think that functions would work in the same way: create a new function in your child theme's functions.php file with the same name as one in the parent theme, and it'll take precedence. Unfortunately, it isn't as simple as this.

In this tutorial, I'll show you three methods you can use to override functions from the parent theme in your child theme:

  • pluggable functions
  • function priority
  • removing functions from the hook they're attached to

How Functions in Parent and Child Themes Work

Before examining the methods for overriding functions in your child themes, it helps to understand how functions work in parent and child themes.

Firstly, you need to know that all of the functions in your parent theme will be run when you're using a child theme. You don't have to add anything to your child theme's functions file to make this happen. This is different from CSS, where you have to manually include the parent theme's stylesheet in the child theme's stylesheet.

Another thing to know is that if your parent and child themes have functions with the same name, this will break your site—unless the function in the parent theme is a pluggable function (more on this shortly). This is why it’s important to use prefixes for all your functions, and to use a different prefix in parent and child themes—just in case.

However you can change the order in which functions are fired, and you can prevent functions from being fired altogether, as we'll see shortly.

Pluggable Functions

Pluggable functions are something you code into your parent theme, so they won't be any use to you if you're working with an existing parent theme that doesn't have them.

But if you're writing your own parent theme, maybe as a starting point for future projects, or if you're creating your own theme framework, it's good practice to make your functions pluggable so that you can easily override them in child themes. It's also a good idea to look through the functions that are written into the parent theme you're using, as many of them, including the WordPress default theme, will have pluggable functions.

To write a pluggable function, you simply enclose it in a conditional tag to check if a function with that name has already been run:

So if you enclose the functions in your parent theme in a conditional tag like this, WordPress will check if there is a function with the same name in your child theme that's already been run, and if that's the case, it won't run the function from the parent theme.

Then, when you come to write a function in your child theme which you want to override the one in the parent theme, you just give it the same name as the one in the parent theme:

WordPress will run the function in the child theme first, and when it comes to the one in the parent theme, it'll check if it already exists and because it does, it won't run it.

Function Priority

If you're not using your own parent theme, or you're using a third-party one without pluggable functions, you'll need another method.

When you write functions, you can assign them a priority, which tells WordPress when to run them. You do this when adding your function to an action or filter hook. WordPress will then run the functions attached to a given hook in ascending order of priority, so those with higher numbers will run last.

Let's imagine the function in the parent theme isn't pluggable, and looks like this:

This function is attached to the init hook and hasn't been given a priority. By default, WordPress assigns a priority of 10 to functions which haven't had a priority added, so to fire your function after it, you use a number larger than 10. I tend to use 15 so that I've got some breathing room in case I want to add another function between the two later on.

This means the function in your child theme would look like this:

Alternatively, the function in your parent theme may have had a priority assigned to it:

So you just need to make sure the priority you give the function in your child theme is higher:

Removing Functions From Hooks

Sometimes, running another function after the first one isn't enough to override it—you need to make sure the function in the parent theme doesn't run at all. In this case, you can remove the parent theme function from the hook it's attached to, using the remove_action() or remove_filter() functions. The one you use will depend on whether the function is attached to an action hook or filter hook in the parent theme.

So let's return to our previous function in the parent theme:

To remove this function from its action hook and therefore prevent it from firing, you create a function in your child theme to remove it using remove_action():

However, this won't work on its own—you need to attach this function to a hook which will fire after the hook which the parent theme function is attached to. This is because you can't remove the action before it's been fired. You can find details of the order in which actions are fired in the Codex.

Once you've done this, you can simply write an alternative function to replace the parent theme function in your child theme's functions file, or you can do nothing if all you wanted to do was remove the functionality from the parent theme.

A Note on Priorities

Note that if you're trying to remove a function using remove_action() or remove_filter() and the function has had a priority assigned to it, you must include the priority when removing it, or it won't work.

So if the function in the parent theme looks like this:

... you'll need to include the same priority value when removing it:

Advanced Parent and Child Theme Functions: Plugable Functions and Extending Functions

As well as the above, there are some specific scenarios in which you might want to take things further. The following tips are in response to questions that have been asked in the comments below.

How to Partially Override a Function in the Parent Theme

Strictly speaking, you can’t partially override a function. You can only let it run or disable it. But there are workarounds.

The first is if the function you want to partially override itself contains functions that are pluggable. You might find that the function includes a call to another pluggable function from within the parent theme.

If this is the case, you can override any functions within the main function, if that’s the code you want to change. Do it by writing a new version of the pluggable function that either contains just a return statement or contains alternative code. Note that this will only work if the function is pluggable—if it isn’t, your site will break. 

However, this method only works if you’re lucky enough to need to override functionality within a function that’s provided by another contained and pluggable function.

In the vast majority of cases, this won't be an option. In these cases, you'll need to deactivate the function and replace it with a function of your own, with a different name. To create your new function, you can copy and paste the function from the parent theme into the child theme's functions.php file, and then edit it to remove the code you don’t want.

You’d use two of your own functions: one to remove the original one, and the second to provide new code, like this example overriding a parent theme called on the init hook:

How to Override Non-Pluggable Functions

Functions in the parent theme that aren’t pluggable can’t be overridden in any special way. So you’d have to use the method above, removing the function from its action hook and then writing a new function on the same action hook that provides the new code.

Don’t give the function in your child theme the same name as the function from the parent theme as this will break your site!

How to Extend Parent Theme Functions

Functions are generally not designed to be extendable. However, there may be an exception if your function includes calls to other pluggable functions.

If this is the case, you can extend the function by overriding the functions within the main function, without having to replace the whole of the main function.

In most cases, you can only extend a parent theme function in one of three ways:

  • If the function you want to extend is pluggable, copy it into your child theme and add extra code to extend it.
  • If the function isn't pluggable, remove it from its hook using remove_action() and write a new function (with a different name) on the same hook with extra code. You might want to copy code from the original function into your new function and edit that.
  • Write a second function which is called on the same hook as the first function and adds extra code that will run before or after the first function. Use the priority parameter in add_action() to specify whether your second function will run before or after the original function.

Summary

Overriding functions in a parent theme is more complicated than overriding template files or styling, but it can be done. Here I've shown you three methods for doing this:

  • If you're writing your own parent theme, or using one which has them, use pluggable functions so that a function in the child theme with the same name as one in the parent theme will replace it.
  • Assign higher priorities to functions in your child themes to ensure they're run after those in your parent theme.
  • Use remove_action() or remove_filter() to remove functions in the parent theme altogether.

Which method you use will depend on the way your parent theme is coded and whether you need to remove the parent theme function altogether or just run another function after it to override it.

No comments:

Post a Comment