(Updated/new answer)
So here I’m going straight to the code you need: (but do read the updated version of the original answer)
Register the CPT’s and Set the proper rewrite slug
-
This is for the “English Speaking” CPT, which is assigned to the
custom taxonomy “Speaking Task”:register_post_type( 'english-speaking', array( 'label' => 'English Speaking', 'public' => true, 'rewrite' => array( 'slug' => 'english/speaking/%speaking_task%/%question_id%', ), // Other args here. ) );
-
This is for the “English Writing” CPT, which is not assigned to
any taxonomy:register_post_type( 'english-writing', array( 'label' => 'English Writing', 'public' => true, 'rewrite' => array( 'slug' => 'english/writing/%question_id%', ), // Other args here. ) );
Register the custom taxonomy “Speaking Task”
register_taxonomy( 'speaking-task', array( 'english-speaking' ), array(
'label' => 'Speaking Tasks',
'public' => true,
'rewrite' => array(
'slug' => 'english/speaking',
),
// Other args here.
) );
Make sure the rewrite slug
is set to english/speaking
.
The “English Speaking” archive would be accessible at:
-
http://example.com/english/speaking
-
http://example.com/english/speaking/{SPEAKING TASK SLUG}
Register the custom rewrite tags
add_rewrite_tag( '%question_id%', '(\d+)' );
add_rewrite_tag( '%speaking_task%', '([^/]+)' );
Add the code for replacing the custom rewrite tags
add_filter( 'post_type_link', 'my_filter_questions_post_type_link', 10, 2 );
function my_filter_questions_post_type_link( $post_link, $post ) {
// Replaces/rewrites %question_id% in the permalink.
if ( false !== strpos( $post_link, '%question_id%' ) ) {
$id = get_post_meta( $post->ID, 'wpcf-question-id', true );
// A default value is necessary, and the value has to be a 0.
$id = $id ? $id : '0';
$post_link = str_replace( '%question_id%', $id, $post_link );
}
// Replaces/rewrites %speaking_task% in the permalink.
if ( false !== strpos( $post_link, '%speaking_task%' ) ) {
// A default value is necessary, but the term/category doesn't need to
// actually exists. So you could, for example, use 'all' as the value.
$slug = 'uncategorized';
$cats = get_the_terms( $post, 'speaking-task' );
if ( $cats && ! is_wp_error( $cats ) ) {
$slug = $cats[0]->slug;
}
$post_link = str_replace( '%speaking_task%', $slug, $post_link );
}
return $post_link;
}
Flush the rewrite rules
Refer to my other answer if you don’t know how to flush the rules..
Use get_query_var()
to retrieve the rewrite tag values
-
get_query_var( 'question_id' )
for%question_id%
-
get_query_var( 'task_slug' )
for%task_slug%
The full sample code is available here. 🙂
UPDATE
If you use a plugin to register the post type, you can filter (set/change) the rewrite slug
via the register_post_type_args
filter, like so:
add_filter( 'register_post_type_args', 'my_filter_post_type_args', 10, 2 );
function my_filter_post_type_args( $args, $post_type ) {
if ( ! isset( $args['rewrite'] ) ) {
$args['rewrite'] = array();
}
if ( 'english-speaking' === $post_type ) {
$args['rewrite']['slug'] = 'english/speaking/%speaking_task%/%question_id%';
} elseif ( 'english-speaking' === $post_type ) {
$args['rewrite']['slug'] = 'english/writing/%question_id%';
}
return $args;
}
And likewise if you use a plugin to register the custom taxonomy, you can filter (set/change) the rewrite slug
via the register_taxonomy_args
filter, like so:
add_filter( 'register_taxonomy_args', 'my_filter_taxonomy_args', 10, 2 );
function my_filter_taxonomy_args( $args, $taxonomy ) {
if ( ! isset( $args['rewrite'] ) ) {
$args['rewrite'] = array();
}
if ( 'speaking-task' === $taxonomy ) {
$args['rewrite']['slug'] = 'english/speaking';
}
return $args;
}
You might need to set a lower priority — i.e. change the 10
to 11
or a higher value (number) — greater number = lower priority, whereas lower number = higher priority.
Alternatively, without custom coding, and if the plugin allows you to manually set the rewrite slug of the custom post type or taxonomy, then just use the appropriate box/field to enter the appropriate rewrite slug. =)