Avada is a popular wordpress theme that offers a lot of features and pre-built websites, which helps people to rapidly build their own website right out of the box. Though it’s not as popular as before, mainly due to performance reason, Avada still has consistent support and large enough communities which still makes the theme an attractive choice.
Avada offers Portfolio feature which creates its own type of post and renders the post in a specific way. In WordPress point-of-view, this portfolio is a custom post type that differentiates itself from other default post types like: Posts, Pages, Attachments, etc. This way, Avada is able to make portfolio post type to behave and render in specific way.
The first problem with portfolio feature is, although regular posts and portfolio posts are two different types of post, they are sharing a same permalink structure. This results in:
/cases/ slug can be configured in Avada option.
Both of them are stemming from
/blog/ slug because Setting -> Permalink -> Common Settings -> Custom Structure is
The ideal structure would be:
The second problem, which is a following problem after the first one, is that custom post type slug and custom taxonomy slug can’t share a same prepending slug (in this case
/cases/). Avada, by default, attaches 3 taxonomies to portfolio post type: category, skill, and tag. If any of these taxonomies has
cases as their starting custom bases in Setting -> Permalink -> Optional, it will be directed to 404 Page Not Found page.
I want all portfolio related elements (posts, taxonomies) to stem from
The ideal structure would be:
Solution: First Problem
The reason why portfolio posts prepends custom permalink structure is because that’s the default setting when registering a new post type. Portfolio post type and taxonomy registration happens at
When Avada registers portfolio post type, it does not explicitly set
false, but just leave it empty which defaults to
$front prepending the permastruct:
But be advised that source code should not be edited directly. It will easily be overwritten when there’s an update and it will cause unexpected problems.
Fortunately, WordPress provides hooks that is suitable for this kind of job. There are several hooks that can do the job, and
register_post_type_args is the one that’s most appropriate for this task.
Where can hooks be used then?
Creating a custom plugin
When site-wide modification is made, it’s often recommended to make changes with theme’s
function.php or create a custom plugin. However, making changes in
function.php is not recommended as theme updates will overwrite the file. So unless the website uses its own developed theme, it is recommended to make changes through a custom plugin.
This article will not cover much on the topic of custom plugin, but just show how to make a quick custom plugin. For more details, you can follow WordPress Plugin Development Guide.
To create a custom plugin, go to
/wp-content/plugins/ and create your own folder named after your plugin. In this example, the folder will be named
portfolio-slug and its plugin file will be named
/wp-content/plugins/portfolio-slug/portfolio-slug.php (the file you just created) with preferred text editor and copy and paste the code below:
Plugin Name is the only required header field, so you can erase rest of the field if you want to. However, it’s strongly recommended to fill out
Description field and
Author field for readability.
Save the file and go to WordPress admin page -> Plugins, and you’ll see your custom plugin among other plugins like the picture below.
Activate the plugin, and you’re ready to use hooks!
There are two types of hooks: Action and Filter. Again, this article is not going to cover great detail on this topic. For more information, take a look at WordPress Plugin Developer Handbook.
register_post_type_args is a filter type that can alter the arguments when registering a post type. To add filter, simply use
add_filter function will take the name of the filter hook as first argument, function to execute when triggered (callback function) as second, filter execution priority as third, and the number of arguments of callback function as fourth.
Open plugin-slug.php in text editor and add a line:
This means that filter has been added to
register_post_type_args hook and it will execute a function called
change_avada_portfolio_slug. The filter has a priority of 10 (lowest) and
change_avada_portfolio_slug function will take 2 arguments.
change_avada_portfolio_slug function has not been declared yet. Declare a function before/after
The function has two parameters,
$args contains all the arguments when new post type is registered like in
/wp-content/plugins/fusion-core/includes/class-fusioncore-plugin.php, and it has
rewrite property that needs to modified.
$post_type tells which post type is being registered.
There are many other post types being registered when WordPress is running and this hook will run every time when such post types are being registered.
if statement is required to restrict the function to only work on
avada_portfolio post type.
The function is basically saying, “If the post being registered is called
avada_portfolio, set the property
false. Then return
$args for WordPress to carry on with its work.”
Save the file and go to Admin page -> Settings -> Permalink.
Without making changes in settings, click Save Changes. This will refresh the permastructure.
Create a new portfolio post and you’ll see the result of your work:
Solution: Second Problem
Let’s cut to the chase here. it is possible for posts and taxonomies to use a same slug. However this has to be done in very specific way.
When a custom post type and its custom taxonomies are registered, taxonomies have to be registered first and then a custom post type in order to let them share a slug.
The problem is, when Avada registers its portfolio post type, it registers a post type first and then its taxonomies, as shown below:
There are filters and actions that can alter the values being passed, but there’s no such hooks that can alter the sequence of registration.
Here is how this article will tackle this problem:
- Instead of trying to change the outcome during registration process, wait for all the registrations to finish.
- Unregister the registered post type and taxonomies.
- Re-register the post type and taxonomies in specific order.
1. Wait for registrations to finish
WordPress hooks don’t just randomly fire any time they want. They have an acceptable sequence. For example,
muplugins_loaded is one of the earliest fired hook that runs when must-use plugins are loaded. To wait out for fusion-core plugin to finish its registration,
init hook (fires when WordPress is initialized) is not enough.
wp_loaded hook fires once WordPress, all plugins, and the theme are fully loaded and instantiated. To setup the hook, open
portfolio-slug.php with a text editor and add a line:
wp_loaded is an action type hook that can be added with
2. Unregister the post type and taxonomies
To unregister a post type, use
To unregister a taxonomy, use
But before unregisteration, post type and taxonomy should be stored as an object so that it can be used when re-registering.
To get existing post type as an object, use
To get existing taxonomy as an object, use
3. Re-register the post type and taxonomies
To register a post type, use
To register a taxonomy, use
Fortunately, these functions can receive objects saved by
Register taxonomies first, and then a post type.
There is a side effect though, Featured Image setting disappears.
In order to enable it, and prevent other possible side effects, add a line before registering the custom post type.
Finally, filter taxonomy slugs like it’s done in first solution.
To filter arguments when taxonomies are registered, use
with_front property is set to false when Avada registers the taxonomies so there’s no need to set to false again.
Remember to save the file, go to Admin page -> Settings -> Permalink, and click Save Changes, as this will refresh the permastructure.
So far, there doesn’t seem to be additional observable side effects. As long as you don’t create a portfolio post called ‘categories’, ‘skills’, or ‘tags’, it’s not going to break the website.
The solution provided could seem hacky or unorthodox, but this solution is quite update-proof unless wordpress deprecates provided hooks.
For any suggestions/corrections, please email here.
Thank you :)