I am building an LMS type system in WordPress, controlled by Custom Post types
.
The post type is called Lessons
(with a slug of courses
) and it has one custom taxonomy
(category) called courses
.
The domain URL structure shows right now as:
domain.example/courses/lesson-name
.
I want it to become:
domain.example/courses/[course-name{category}]/lesson-name
or essentially:
/[cpt]/%category%/%postname%/
here is the plugin I wrote that is controlling the CPTs
now.
function rflms_post_type() {
$labels = array(
'name' => _x( 'Lessons', 'Post Type General Name', 'text_domain' ),
'singular_name' => _x( 'Lesson', 'Post Type Singular Name', 'text_domain' ),
'menu_name' => __( 'Lessons', 'text_domain' ),
'parent_item_colon' => __( 'Parent Product:', 'text_domain' ),
'all_items' => __( 'All Lessons', 'text_domain' ),
'view_item' => __( 'View Lesson', 'text_domain' ),
'add_new_item' => __( 'Add New Lesson', 'text_domain' ),
'add_new' => __( 'New Lesson', 'text_domain' ),
'edit_item' => __( 'Edit Lesson', 'text_domain' ),
'update_item' => __( 'Update Lesson', 'text_domain' ),
'search_items' => __( 'Search Lessions', 'text_domain' ),
'not_found' => __( 'No Lessons Found', 'text_domain' ),
'not_found_in_trash' => __( 'No Lessons Found in Trash', 'text_domain' ),
);
$args = array(
'label' => __( 'Lessons', 'text_domain' ),
'description' => __( 'Referable Lessons', 'text_domain' ),
'labels' => $labels,
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'supports' => array('premise-member-access', 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments'),
'menu_position' => 5,
'menu_icon' => null,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'post',
'rewrite' => array('slug' => 'courses'),
);
register_post_type( 'lessons', $args );
// Hook into the 'init' action
}
add_action( 'init', 'rflms_post_type', 0 );
// Register Custom Taxonomy
function custom_taxonomy() {
$labels = array(
'name' => _x( 'Courses', 'Taxonomy General Name', 'text_domain' ),
'singular_name' => _x( 'Course', 'Taxonomy Singular Name', 'text_domain' ),
'menu_name' => __( 'Courses', 'text_domain' ),
'all_items' => __( 'All Courses', 'text_domain' ),
'parent_item' => __( 'Parent Course', 'text_domain' ),
'parent_item_colon' => __( 'Parent Course:', 'text_domain' ),
'new_item_name' => __( 'New Course Name', 'text_domain' ),
'add_new_item' => __( 'Add New Course', 'text_domain' ),
'edit_item' => __( 'Edit Course', 'text_domain' ),
'update_item' => __( 'Update Course', 'text_domain' ),
'separate_items_with_commas' => __( 'Separate Courses with commas', 'text_domain' ),
'search_items' => __( 'Search Courses', 'text_domain' ),
'add_or_remove_items' => __( 'Add or Remove Courses', 'text_domain' ),
'choose_from_most_used' => __( 'Choose from Most Used courses', 'text_domain' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => true,
'show_in_nav_menus' => true,
'show_tagcloud' => false,
'rewrite' => array('slug' => 'courses'),
);
register_taxonomy( 'course', 'lessons', $args );
}
// Hook into the 'init' action
add_action( 'init', 'custom_taxonomy', 0 );
Change your rewrite to add the course query var:
Then filter
post_type_link
to insert the selected course into the permalink:There are also plugins like Custom Post Type Permalinks that can do this for you.
The solution for me had three parts. In my case the post type is called
trainings
.'rewrite' => array('slug' => 'trainings/%cat%')
to theregister_post_type
function.So here is how to change the permalink dynamically for a given post type. Add to
functions.php
:…and this is how to load the appropriate template on the new dynamic URL. Add to
functions.php
:Thats it! Remember to refresh the permalinks by saving the permalinks again in de backend. Or use the
flush_rewrite_rules()
function.You need to update the line where you have registered a custom post type using the
register_post_type
function.'rewrite' => array('slug' => 'courses/%cat%')
To dynamically change the permalink of the post type, you have to add this code in
functions.php
:After that, you need to flush the rewrite permalinks. Go to wp-admin > Settings > permalinks and update permalink settings then press the “Save Changes” button. It’ll return URLs like this:
domain.example/courses/[course-name{category}]/lesson-name
Got the solution!
To have hierarchical permalinks for custom post type install Custom Post Type Permalinks(https://wordpress.org/plugins/custom-post-type-permalinks/) plugin.
Update registered post type. I have post type name as help center
And here is registered taxonomy
This is line makes your permalink work
you can remove
%post_id%
and can keep/%help_centre_category%/%postname%/"
Don’t forget to flush permalinks from dashboard.
To anyone interested in the solution, without having to tinker with raw PHP code, I highly recommend the plugin Permalink Manager Lite by Maciej Bis. It’s a life saver.
It has a visual mechanism to remove or add whatever part you want in the custom post type’s URL based on ‘permastructs’:
(With all the pain involved in simple URL structuring with custom post types, we were about to give up on WP and move to another CMS. But this plugin in conjunction with ACF and CPTUI or Pods makes WordPress fairly professional.)
Yep! After a lot of research I got plugin ‘Custom Permalinks‘. Which fulfils my requirement regards – custom URL e.g.
etc.
Like this Custom Post Type – Post:
This is worked for me :
If you’re using
get_post_type_archive_link()
, maybe you will need to remove/%cat%/
from the URL usingpost_type_archive_link
filter.I found @chetan-vaghela ‘s answer almost perfect; in my use case I also wanted to be able to see a list of all posts by this post type like a typical archive page (i.e. /courses/, without any taxonomy after it). I just had to add one additional rewrite rule as follows: