Reputation: 844
In my WordPress v6.0.2, I have a custom taxonomy country
and a custom post_type interest
.
With post_type_link
filter (another working function) and with the below function, I am rewriting custom post_type URLs as https://www.example.com/country_name/interest_term
:
add_filter('generate_rewrite_rules', 'country_cpt_generating_rule');
function country_cpt_generating_rule($wp_rewrite) {
$rules = array();
$terms = get_terms(array(
'taxonomy' => 'country',
'hide_empty' => false,
));
$post_type = 'interest';
foreach ($terms as $term) {
$rules[$term->slug . '/interest/([^/]*)$'] = 'index.php?interest=$matches[1]&post_type=' . $post_type . 'name=$matches[1]';
}
$wp_rewrite->rules = $rules + $wp_rewrite->rules;
}
While I have single-interest.php
custom post_type template to show custom content, single posts are redirecting to home page with error404
class added to the body.
A var_dump(get_queried_object());
returning null
.
I have flushed permalinks and also tried checking is_singular()
to template redirecting, that did not worked.
How can I have a custom page template for single-interest
with above custom URL?
Upvotes: 3
Views: 888
Reputation: 130
here is the complete solution for your requirement. Please note that you do not have to regenerate new rewrite rules to be able to work with custom post-type URLs. instead, I have used filters to modify URLs based on your need. Let me know if this solves your issue. Please do not forget to flush your permalinks. There might be some edge cases that I did not put my focus on because mainly I was focusing on achieving your requirements.
add_action('init', 'register_cpt_type');
add_filter('pre_term_link', 'change_term_links', 10, 2);
function change_term_links( $termlink, $term ) {
$post_type = isset( get_taxonomy( $term->taxonomy )->object_type[0] ) ? get_taxonomy( $term->taxonomy )->object_type[0] : '';
if( $post_type === 'interest' ) {
$termlink = explode('/', $termlink) != '' ? explode('/', $termlink): '';
unset($termlink[1]);
$termlink = implode('', $termlink);
}
return $termlink;
}
function register_cpt_type() {
$args = array(
'label' => 'Interest',
'description' => 'Add new interest from here',
'public' => true,
'public_queryable' => true,
'exclude_from_search' => false,
'show_ui' => true,
'show_in_menu' => true,
'show_in_admin_bar' => true,
'query_var' => true,
'capability_type' => 'post',
'rewrite' => array(
'slug' => '%country%',
'with_front' => false
),
'hierarchical' => false,
'show_in_rest' => true,
'with_front' => false,
'has_archive' => true,
'menu_icon' => 'dashicons-chart-pie',
'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'author', 'revisions', 'custom-fields', 'comments')
);
register_post_type('interest', $args);
$args = array(
'label' => 'Country',
'public' => true,
'show_ui' => true,
'query_var' => true,
'show_in_rest' => true,
'hierarchical' => true,
'rewrite' => array(
'slug' => '%country%',
'with_front' => false
),
);
register_taxonomy( 'country', 'interest', $args );
}
add_filter('post_type_link', 'single_cpt_postlink', 10, 2);
function single_cpt_postlink( $post_link, $post ) {
$post_type = get_post_type( $post->ID ) != '' ? get_post_type( $post->ID ) : '';
if( $post_type == 'interest' ) {
$term_slug = get_the_terms( $post->ID, 'country' ) != '' ? get_the_terms( $post->ID, 'country' )[0]->slug : '';
if( ! empty( $term_slug ) ) {
$post_link = str_replace('%country%', $term_slug, $post_link);
}
}
return $post_link;
}
Upvotes: 1
Reputation: 844
I have taken cue from this SO answer and below code worked for me:
// custom url
add_action('init', 'custom_init');
add_filter('post_type_link', 'interest_permalink', 10, 3);
function custom_init() {
global $wp_rewrite;
$interest_structure = '/%country%/%interest%';
$wp_rewrite->add_rewrite_tag("%interest%", '([^/]+)', "interest=");
$wp_rewrite->add_permastruct('interest', $interest_structure, false);
}
function interest_permalink($permalink, $post_id, $leavename) {
$post = get_post($post_id);
$rewritecode = array(
'%country%',
$leavename ? '' : '%postname%',
);
if ('' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft'))) {
if (strpos($permalink, '%country%') !== FALSE) {
$terms = wp_get_object_terms($post->ID, 'country');
if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) {
$country = $terms[0]->slug;
} else {
$country = 'unassigned_country';
}
}
$countryreplace = array(
$country,
$post->post_name,
);
$permalink = str_replace($rewritecode, $countryreplace, $permalink);
} else {
}
return $permalink;
}
Upvotes: 0
Reputation: 130
It seems you are wanting to access the CPT single page. In order to do that please follow the code below
add_filter( 'single_template', 'get_interest_single_template' ), 99);
function get_interest_single_template( $single_template_path ) {
if (is_singular('interest')) {
$single_template = plugin_dir_path(__FILE__) . '/single-interest.php' ;
}
return $single_template;
}
Now inside the "single-interest.php". you can var_dump( get_queried_object() ). Which should give you the values of the WP_Post Object data. Since this template is directly coming from a plugin the custom template file should be placed inside a plugin or the custom single-interest file should be placed inside the theme file in this format "single-interest.php". Also, I would like to add the following points, since you are using a custom post type, you do not have to regenerate custom slugs. Because WordPress does regenerate the custom slugs for you. I would recommend you not use 'generate_rewrite_rules' because WordPress did create those slugs for you while creating the custom post type. What you can do is pass the slug value inside the 'parse_request' filter hook. For reference please refer to this page here
Upvotes: 0