admin管理员组文章数量:1414614
I have a custom taxonomy called campaign
and a custom post type called asset
. For assets, I want to have the following permalink structure: mysite/<campaign_name>/<asset_name>
. I have achieved this by the following code, but now if I go to any normal page with the url structure mysite/<pagename>
it gives a 404. And when I comment out the rewrite slug part in the function for registering the custom post type, or add this instead ams/%campaign%
, it works but that's not the URL structure I want for my custom post type.
Code for registering custom taxonomy:
...
'rewrite' => array(
'slug' => '',
'with_front' => true,
),
...
Code for registering custom post type:
...
rewrite' => array(
'slug' => '%campaign%',
'with_front' => true,
),
...
Functions for rewrite rules:
function ams_asset_add_rewrite_rules( $rules ) {
global $post;
if ($post->post_type == 'asset' ) {
$new = array();
$new['([^/]+)/(.+)/?$'] = 'index.php?asset=$matches[2]';
$new['(.+)/?$'] = 'index.php?campaign=$matches[1]';
return array_merge( $new, $rules );
}
return $rules;
}
add_filter( 'rewrite_rules_array', 'ams_asset_add_rewrite_rules' );
// Handle the '%campaign%' URL placeholder
function ams_asset_filter_post_type_link( $link, $post = 0 ) {
if ( $post->post_type == 'asset' ) {
$cats = wp_get_object_terms( $post->ID, 'campaign' );
if ( $cats ) {
$link = str_replace( '%campaign%', $cats[0]->slug, $link );
}
}
return $link;
}
add_filter( 'post_type_link', 'ams_asset_filter_post_type_link', 10, 2 );
Edit: it's not a duplicate. I explained why that possible duplicate question doesn't solve my problem.
I have a custom taxonomy called campaign
and a custom post type called asset
. For assets, I want to have the following permalink structure: mysite/<campaign_name>/<asset_name>
. I have achieved this by the following code, but now if I go to any normal page with the url structure mysite/<pagename>
it gives a 404. And when I comment out the rewrite slug part in the function for registering the custom post type, or add this instead ams/%campaign%
, it works but that's not the URL structure I want for my custom post type.
Code for registering custom taxonomy:
...
'rewrite' => array(
'slug' => '',
'with_front' => true,
),
...
Code for registering custom post type:
...
rewrite' => array(
'slug' => '%campaign%',
'with_front' => true,
),
...
Functions for rewrite rules:
function ams_asset_add_rewrite_rules( $rules ) {
global $post;
if ($post->post_type == 'asset' ) {
$new = array();
$new['([^/]+)/(.+)/?$'] = 'index.php?asset=$matches[2]';
$new['(.+)/?$'] = 'index.php?campaign=$matches[1]';
return array_merge( $new, $rules );
}
return $rules;
}
add_filter( 'rewrite_rules_array', 'ams_asset_add_rewrite_rules' );
// Handle the '%campaign%' URL placeholder
function ams_asset_filter_post_type_link( $link, $post = 0 ) {
if ( $post->post_type == 'asset' ) {
$cats = wp_get_object_terms( $post->ID, 'campaign' );
if ( $cats ) {
$link = str_replace( '%campaign%', $cats[0]->slug, $link );
}
}
return $link;
}
add_filter( 'post_type_link', 'ams_asset_filter_post_type_link', 10, 2 );
Edit: it's not a duplicate. I explained why that possible duplicate question doesn't solve my problem.
Share Improve this question edited Sep 3, 2019 at 9:28 sadmansh asked Sep 3, 2019 at 5:23 sadmanshsadmansh 552 silver badges12 bronze badges 6 | Show 1 more comment2 Answers
Reset to default 6 +100Solution would be a little tricky but you're on the right path.
- You need to register taxonomy and post type with dynamic rewrite:
function wpse346452_cpt() {
register_taxonomy( 'campaign', 'asset', array( 'label' => 'Campaing' ) );
register_post_type( 'asset', array(
'public' => true,
'label' => 'Asset',
'rewrite' => array(
'slug' => '%campaign_name%',
),
) );
}
add_action( 'init', 'wpse346452_cpt' );
- You need to replace that dynamic rewrite so that it represents the term attached to it:
function wpse346452_permalink( $post_link, $post ) {
if( is_object( $post ) && $post->post_type == 'asset' ) {
$terms = wp_get_object_terms( $post->ID, 'campaign' );
if( $terms ) {
return str_replace( '%campaign_name%' , $terms[0]->slug , $post_link );
}
}
return $post_link;
}
add_filter( 'post_type_link', 'wpse346452_permalink', 10, 2 );
- Now you get 404 because the rewrite rule is not defined yet. Each time you have a new term under campaign, you need a new rule. So let's add rewrite rules for each available terms dynamically:
function wpse346452_dynamic_rw_rules() {
$terms = get_terms( array(
'taxonomy' => 'campaign',
'hide_empty' => false,
) );
if( !empty( $terms ) ) {
foreach( $terms as $term ) {
add_rewrite_rule(
'^' . $term->slug . '/(.*)/?$',
'index.php?post_type=asset&name=$matches[1]',
'top'
);
}
}
}
add_action( 'init', 'wpse346452_dynamic_rw_rules' );
Now it will work as you needed. But the downside is, whenever you add new campaign, you need to go to permalink settings and save, thus flush rewrite rules. So let's automate that too:
function wpse346452_flush_rewrite( $term_id, $tt_id, $taxonomy = 'campaign' ) {
if( $taxonomy === 'campaign' ) {
$term = get_term_by( 'term_taxonomy_id', $tt_id );
add_rewrite_rule(
'^' . $term->slug . '/(.*)/?$',
'index.php?post_type=asset&name=$matches[1]',
'top'
);
if( !function_exists( 'flush_rewrite_rules' ) ) {
require_once WPINC . '/rewrite.php';
}
flush_rewrite_rules();
}
}
add_action( 'edit_term', 'wpse346452_flush_rewrite', 10, 3 );
add_action( 'create_campaign', 'wpse346452_flush_rewrite', 10, 3 );
Here we're hooking into create and edit term and if the taxonomy is campaign then we're firing flush_rewrite_rules()
to refresh permalinks.
This is the only perfect method of doing this as far my knowledge. But there's a limitation for doing this. As there's no limit of adding terms, it can conflict with rewrite rules from other plugins. So need to be used carefully.
My answer isn't directly applicable to your case as my experience is about doing funky stuff with CPT permalinks, but without taxonomies. But the end result was more or less the same as half of the site's content ended up showing 404 after starting to use custom permalink structures.
It took me ages to figure out what was going on and get the problem fixed. The problem was that WordPress had started thinking that some of the content were attachments instead of pages/posts/CPTS. To get the content showing again, I hooked a custom function to parse_request
and basically brute forced the $wp->query_vars
to be correct.
It might not be the most elegant or efficient solution, but it did the trick. I did try playing around with adding custom rewrite rules, but that got me nowhere as I couldn't wrap my head around the rewrite concepts.
Here's a simplified and stripped down version of the code I used to solve the 404 problem. The basic idea is that I just used what query_vars
I had, did custom $wpdb
query to get the right data, and then pushed that data to query_vars
and removed unnecessary data from it.
add_action( 'parse_request', 'modify_parse_request' );
function modify_parse_request( $wp ) {
if ( is_admin() || ! is_main_query() ) {
return;
}
global $wpdb;
// var_dump($wp->query_vars); // see whats really happening with your query
if ( ! empty( $wp->query_vars['attachment'] ) ) {
// $path = explode( '/', $wp->request ); // you might need to get the page name from request
$sql = "
SELECT ID, post_name, post_type
FROM $wpdb->posts
WHERE post_name=%s
";
$post = $wpdb->get_results( $wpdb->prepare( $sql, $wp->query_vars['attachment'] ) ); // modify this
// "brute force" the query variables to be correct
if ( $post ) { // modify this
$wp->query_vars['p'] = $post->ID;
$wp->query_vars['post_type'] = $post->post_type;
$wp->query_vars['name'] = $wp->query_vars['attachment'];
unset( $wp->query_vars['attachment'] );
}
}
}
This is definetly not an copy-paste example, but just some food or thought. Maybe using this as a starting point, you can get your pages working again, if you use your custom taxonomy+cpt_post_name permalink structure.
本文标签: How to add custom taxonomy in custom post type permalink
版权声明:本文标题:How to add custom taxonomy in custom post type permalink? 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745169059a2645860.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
post_type
to the query string. – Howdy_McGee ♦ Commented Sep 6, 2019 at 15:15/<campaign>/<asset>/
or can it be prefixed with something unique to the post type so WordPress doesn't get it confused with Pages such as:/assets/<campaign>/<asset>/
? – Howdy_McGee ♦ Commented Sep 6, 2019 at 15:41