[Edited]
I changed the purpose of my site into an language learning site.
Now the CPT is setup as following:
{ Language } - { Subject }
- English speaking (slug: english-speaking )
- English writing (english-writing )
- English reading ( english-speaking )
- English writing (english-writing)
Single CPT setup
Because each CPT might have different taxonomy… so it is preferred this would be taking into consideration of the code.
Say: CPT “English Speaking” has a custom taxonomy of “Speaking Task” (speaking-task) with terms “task-1”, “task-2”, “task-3” … . But: CPT “English Writing” has no taxonomy at all.
Desired URL for single CPT post item:
With custom taxonomy terms:
- www.domain.com/{language}/{subject}/{ term-slug }/{custom-question-id}/{post-name}
- ex. www.domain.com/english/speaking/speaking-1/32/blah-blah-blah
Without custom taxonomy terms:
- www.domain.com/{language}/{subject}/{custom-question-id}/{post-name}
- ex. www.domain.com/english/writing/32/blah-blah-blah
The URL rewrite part for Single CPT is not a problem for me now thanks to your teaching and genius code provided in the new answer
What I am struggling with is the rewrite for the CPT Archive page below:
CPT Archive setup
I am trying to create a custom CPT Archive template with the following setup for URL:
www.domain.com/ { language } / { subject } ex. www.domain.com/english/speaking
www.domain.com/ { language } / { subject } / { terms-slug }
- ex1. www.domain.com/english/speaking (instead of listing all posts, I wish to make it default to list out to “speaking-1”)
- ex2. www.domain.com/english/speaking/speaking-1 (only list out post under “speaking-1” )
- ex3. www.domain.com/english/speaking/speaking-2 (only list out post under “speaking-2” )
———————————————————————————————————
In [archive-english-speaking.php] , I have the following code:
// use add_rewrite_rule in funcitons; query_vars "task" is terms of speaking-task taxonomy
global $wp_query;
$task_no = $wp_query->query_vars['task'];
if (preg_match("/[1-6]/", $task_no)) {
$task = ( 'speaking-' . $task_no );
} else {
$task_no = ( '1' );
$task = ( 'speaking-' . $task_no );
}
$posts_per_page = 10;
$the_query = new WP_Query( array(
'post_type' => 'english-speaking',
'taxonomy' => 'speaking-task',
'term' => $task,
/*'paged' => $paged,
'posts_per_page' => $posts_per_page,*/
'orderby' => 'meta_value_num',
'meta_key' => 'wpcf-question-id',
'order' => 'ASC', /* ASC/DESC */
) );
———————————————————————————————————
In [functions.php] , I have the following code:
function custom_rewrite_tag() {
//taxonomy speaking-task =?
add_rewrite_tag('%task%', '([^/]*)');
}
add_action('init', 'custom_rewrite_tag', 10, 0);
// Custom Question ID from custom field
function cqid() {
$cqid = get_post_meta( get_the_ID(), 'wpcf-question-id', true );
return $cqid;
}
function my_questions_cpt_list() {
return [
// Format: POST_TYPE => QUESTION_SUBJECT_SLUG
'english-listening' => 'listening',
'english-speaking' => 'speaking',
'english-reading' => 'reading',
'english-writing' => 'writing',
// Add more items as needed, or if and when you register another CPT
// for questions.
];
}
add_action( 'init', 'my_questions_cpt_add_rewrite_rules' );
function my_questions_cpt_add_rewrite_rules() {
// Archive Page
add_rewrite_rule( '^english/speaking/?$','index.php?post_type=english-speaking&taxonomy=speaking-task&task=$matches[1]', 'top' );
add_rewrite_rule( '^english/speaking/([^/]*)/?$','index.php?post_type=english-speaking&taxonomy=speaking-task&task=$matches[1]', 'top' );
//
$cpt_list = my_questions_cpt_list();
foreach ( $cpt_list as $post_type => $q_subject ) {
if ( empty( $post_type ) ) {
continue;
}
if ( ! $s = preg_quote( $q_subject ) ) {
continue;
}
add_rewrite_rule('^english/(' . $s . ')/(\d+)/(\d+)/([^/]+)/?','index.php?' . $post_type . '=$matches[4]','top');
}
}
add_filter( 'post_type_link', 'my_questions_cpt_custom_permalink', 10, 2 );
function my_questions_cpt_custom_permalink( $permalink, $post ) {
$taxonomy = 'speaking-task';
$cpt_list = my_questions_cpt_list();
if ( false === strpos( $permalink, '?' ) &&
$post && isset( $cpt_list[ $post->post_type ] ) ) {
$cats = get_the_terms( $post, $taxonomy );
if ( $cats && ! is_wp_error( $cats ) ) {
// If assigned to multiple tasks (or categories), then we use just
// the first task/term.
$cat_id = $cats[0]->slug; //term_id
$task = $cat_id[strlen($cat_id)-1];
$cqid = cqid();
$s = $cpt_list[ $post->post_type ];
$permalink = home_url( 'english/' . $s . '/' . $task . '/' . $cqid . '/' . $post->post_name . '/' );
$permalink = user_trailingslashit( $permalink, 'single' );
}
}
return $permalink;
}
———————————————————————————————————
@Sally The code above is limited to my programming level, I used your first answer and modified it... it is kind working in localhost but the archive url got 404 or blank page when I moved it to online hosting server...
slug
argument inrewrite
parameter while registering the post type. Then a str_replace inpost_type_link
filter oradd_rewrite_rule
should do it.