skip to Main Content

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?

3

Answers


  1. Chosen as BEST ANSWER

    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;
    }
    

  2. 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

    Login or Signup to reply.
  3. 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;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search