admin管理员组文章数量:1290981
[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/{language}/{subject}/{ term-slug }/{custom-question-id}/{post-name}
- ex. www.domain/english/speaking/speaking-1/32/blah-blah-blah
Without custom taxonomy terms:
- www.domain/{language}/{subject}/{custom-question-id}/{post-name}
- ex. www.domain/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/ { language } / { subject } ex. www.domain/english/speaking
www.domain/ { language } / { subject } / { terms-slug }
- ex1. www.domain/english/speaking (instead of listing all posts, I wish to make it default to list out to “speaking-1”)
- ex2. www.domain/english/speaking/speaking-1 (only list out post under “speaking-1” )
- ex3. www.domain/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...
[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/{language}/{subject}/{ term-slug }/{custom-question-id}/{post-name}
- ex. www.domain/english/speaking/speaking-1/32/blah-blah-blah
Without custom taxonomy terms:
- www.domain/{language}/{subject}/{custom-question-id}/{post-name}
- ex. www.domain/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/ { language } / { subject } ex. www.domain/english/speaking
www.domain/ { language } / { subject } / { terms-slug }
- ex1. www.domain/english/speaking (instead of listing all posts, I wish to make it default to list out to “speaking-1”)
- ex2. www.domain/english/speaking/speaking-1 (only list out post under “speaking-1” )
- ex3. www.domain/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...
Share Improve this question edited Aug 21, 2018 at 5:30 Atimmy asked Apr 19, 2018 at 8:56 AtimmyAtimmy 557 bronze badges 3 |2 Answers
Reset to default 2(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/english/speaking
http://example/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. =)
(Updated/new answer)
For the original question
I changed my original answer because there's actually a way simpler solution (without having to use the add_rewrite_rule()
function, or hooking to the parse_request
filter) in achieving this permalink structure (for your "questions" CPT):
/{SLUG}/question/{TASK ID}/{POST SLUG}
For example, you could have these permalinks:
/science/question/2/science-question-1
/math/question/4/math-question-1
/english/question/4/english-question-1
So how to achieve that?
When you register a "question" CPT via the register_post_type()
function, set the rewrite slug
to {SLUG}/question/%task_id%
where {SLUG}
is any slug such as science
, math
, and english
.
register_post_type( 'science-question', array(
'label' => 'Science Questions',
'public' => true,
'rewrite' => array(
// The rewrite slug. You can change 'science' to whatever you like.
'slug' => 'science/question/%task_id%',
),
// Other args here.
) );
register_post_type( 'math-question', array(
'label' => 'Math Questions',
'public' => true,
'rewrite' => array(
// The rewrite slug. You can change 'math' to whatever you like.
'slug' => 'math/question/%task_id%',
),
// Other args here.
) );
Then for the custom taxonomy "Task" (registered via the register_taxonomy()
function), set the taxonomy slug to task
like this example:
// Set the slug to 'task'.
register_taxonomy( 'task', array( '{POST TYPE}', '{POST TYPE}', ... ), array(
'label' => 'Tasks',
'public' => true,
// Other args here.
) );
(The {POST TYPE}
could be science-question
, math-question
, etc.)
Next, add this code which will register the custom rewrite tag %task_id%
:
add_rewrite_tag( '%task_id%', '(\d+)' );
And add this code which will replace the %task_id%
tag in the post permalink:
// Replaces %task_id% in the permalink (i.e. $post_link).
add_filter( 'post_type_link', 'my_filter_questions_post_type_link', 10, 2 );
function my_filter_questions_post_type_link( $post_link, $post ) {
if ( false !== strpos( $post_link, '%task_id%' ) ) {
$cats = get_the_terms( $post, 'task' );
$cat_id = 0;
// If the post was assigned to at least one "task" category.
if ( $cats && ! is_wp_error( $cats ) ) {
$cat_id = $cats[0]->term_id;
}
// Else, /{SLUG}/question/0/{POST SLUG} should work well. =) But of
// course, all "question" CPT posts should be assigned to *at least*
// one "task".
$post_link = str_replace( '%task_id%', $cat_id, $post_link );
}
return $post_link;
}
The full sample code is available here. :)
Don't forget to flush the rewrite rules!
It is necessary and here's how: Just go to the "Permalink Settings" page. That's all.
But if the rewrite rules were not flushed (you can confirm by visiting the "question" page), then on the "Permalink Settings" page, click on the "Save Changes" button without having to make any changes.
How to get the value of task_id
Use get_query_var( 'task_id' )
. Example:
$task_id = get_query_var( 'task_id' );
$term = get_term( $task_id );
PS: I know the question has changed, but I updated this answer because it could help someone else. ;)
本文标签: custom post typesPermalink for CPT with taxonomy
版权声明:本文标题:custom post types - Permalink for CPT with taxonomy 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741519317a2383085.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
slug
argument inrewrite
parameter while registering the post type. Then a str_replace inpost_type_link
filter oradd_rewrite_rule
should do it. – Abhik Commented Apr 21, 2018 at 5:11