How to Override Wordpress Shortcodes Defined by Parent Themes
How to override shortcodes from a child theme that are defined in a parent theme in Wordpress.
By. Jacob
Edited: 2020-11-24 10:42
To override a shortcode that is defined by a parent theme, you will need to first remove the shortcode added by the parent, and then add your own replacement shortcode after; to do this, you use the remove_shortcode and add_shortcode functions — but remember, these should be used with a specific hook and prioity to work.
The remove_shortcode function should be called at a specific time — typically using the after_setup_theme hook in the child theme should allow you to execute code after the parent theme has been loaded; but that is not always the case, since the parent theme can add features at different times and prioities as well.
The only way to know exactly the right hook and priority to use is to look at the parent theme's code. If the parent uses init to add its features, then you will not be able to use after_setup_theme from your child, since it takes place earlier in the initialization process.
The following code, used in functions.php, should work in some cases:
add_action('after_setup_theme', 'replace_parent_theme_features');
function replace_parent_theme_features() {
// First we remove the parent shortcode
remove_shortcode('parent_shortcode_name');
// Then we add our own replacement shortcode
add_shortcode('parent_shortcode_name', 'my_child_shortcode');
}
function my_child_shortcode() {
return '<p>My output</p>';
}
Here are some hooks that might work in your case:
- init
- after_setup_theme
- wp_loaded
If this does not work in your case, I recommend you investigate whether the shortcode you want to override has actually been loaded at the time you are trying to remove it. This can be done by printing the contents of the $shortcode_tags variable — more on this in the Troubleshooting section.
Troubleshooting
For whatever reason, overriding a shortcode from a child-theme does not always seem to work. I am not quite sure why, since I rarely need to edit themes — but, I assume that whether it can be done probably depends on how the parent theme was designed.
The official Wordpress documentation does not adequately describe the process of overriding shortcodes defined by a parent, from a child theme, so we have to experiment on our own. I, of course, recommend examining the code in the parent theme to determine which hook you need to use.
If you can not examine the code, you can instead check if the shortcode you are trying to override is actually loaded when you try to remove it. Again, remember that the parent can add features at different times doing the initialization process; since you need to first remove the parent-shortcode, you will need to use a hook and a priority after the parent theme has finished adding features. I think the default priority is often 10 for parent theme features, which means that we should at least use a priority of 11 or higher to ensure that our hook fires after the parent's hook.
The parent can also use different hooks and priorities to load its features, so there is probably no one-size-fits-all solution. For example, if a parent is using the init hook and you are using the after_setup_theme hook, then the priority you pick in your child theme will make no difference — the shortcodes from the parent will not have been loaded yet, because init fires after the after_setup_theme hook.
The following code should tell you if a given shortcode is loaded:
add_action('init', 'replace_parent_theme_features', 20);
function replace_parent_theme_features() {
global $shortcode_tags;
print_r($shortcode_tags);
exit();
}
You can experiment with different hooks and priorities to find a suitable configuration. The above code should output a list of shortcodes that has been loaded.
The best way to replace shortcodes
Changing parent-theme features from functions.php alone might not be the best way to do things. A decently designed theme should allow you to override most — if not everything — from a child theme. If the parent is object orientated, then it might have something like this at the top of PHP classes:
if ( ! class_exists( 'some_class_name' ) ) :
some_class_name {
// Code goes here...
}
endif;
This makes it possible for you to replace the entire class with your own; the simplest way to do this is to copy the class into your child theme, and then include it from the child- functions.php file:
include_once get_stylesheet_directory() . '/shortcodes.php';
In my case, I just needed to replace the shortcodes class in the parent theme, so I simply made a copy of the file in the root of the child theme's directory. Of course, you might want to categorize your files in different directories, but I think you get the idea by now.
Note. The child-theme's root directory is usually:
/var/www/some-wordpress-site/wp-content/themes/my-child-theme/
If you struggle to understand file system paths and URLs, I recommend you also read this article: Absolute and Relative Paths.
The order that things are loaded
In the previous sections I have talked about hooks and priorities, but it is going to be hard for you to understand how these are used if you do not know why they are needed.
A child theme is by default executed before a parent theme. Unfortunately, this also means that some of the things users might need to modify is not yet available from the child theme — one solution to this scenario is the Wordpress hooking system.
When learning about Wordpress hooks, it can be extra confusing because there is a lot of conflicting information on which hook to use for certain things. A reason for this can be that certain hooks only work under certain circumstances, and may not work for the Wordpress theme that you are using — so keep this in mind if something does not work.
The functions.php file in the child theme is also executed before the corresponding file in the parent theme — but again, this can be dealt with using the hooking system. Typically, if you want to make changes to a parent theme, you might use either of init, after_setup_theme, and wp_loaded
Alternatively, for larger changes, you might want to override a PHP class in the parent theme completely. To do that, you can include something like the following in the child's functions.php:
include_once get_stylesheet_directory() . '/shortcodes.php';
But, this also assumes that the class in the parent theme is plugable; meaning that the parent theme should not include its own version of the file if a class with the same name has already been included. You should examine the parent theme's code to learn if this is the case before deciding on how to develop your child theme.
Recommendations on developing Wordpress sites
While it is very easy to make changes to Wordpress websites, I often find that people implement their modifications incorrectly. If you develop Wordpress websites professionally — that is, if you are paid for your work — then there are a few things you can do to make things much easier for yourself and others that might work on the site.
1. Remember to Add Comments to Your Code.
2. When editing the CSS of a Wordpress website, add the code in style.css file rather than random places from the Wordpress front-end..!
3. Avoid adding new features in functions.php and from the code snippets plugin; instead you should either create a plugin that can be enabled/disabled, or create a separate file that you include in functions.php.
4. All comments and documentation should ideally be written in English. You do not know who might work on your code in the future, and they might not be able to understand your local language. Also, if you create something cool, you might want to distribute it later, at which point English will help you reach a broader audience.
5. Avoid developing directly on a live server, instead you should use a local test-server, ideally on your own localhost so you do not have to upload files constantly. If you must test things on a live server, I recommend you use a test parameter. I.e.:
if ($_GET['test'] === 'true') {
add_action('init', 'replace_parent_theme_features', 20);
}
This ensures that your code is only executed when the test parameter is filled out in the URL.
Tell us what you think: