How to add custom taxonomy in custom post type permalink?

I have a custom taxonomy called campaign and a custom post type called asset. For assets, I want to have the following p

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
  • Possible duplicate of How to create a permalink structure with custom taxonomies and custom post types like base-name/parent-tax/child-tax/custom-post-type-name – Jacob Peattie Commented Sep 3, 2019 at 7:17
  • @JacobPeattie if you had spent a minute to read my post, you'd notice it's not a duplicate. I mentioned that I tried exactly what's said in the post you linked, but that's not what I am asking for. – sadmansh Commented Sep 3, 2019 at 9:27
  • My guess is that you can't conditionally add rewrites rules as you have. I believe you need to make them static and unique by add post_type to the query string. – Howdy_McGee Commented Sep 6, 2019 at 15:15
  • @Howdy_McGee can you please give me an example? – sadmansh Commented Sep 6, 2019 at 15:24
  • @sadmansh Does the url structure have to be /<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
 |  Show 1 more comment

2 Answers 2

Reset to default 6 +100

Solution would be a little tricky but you're on the right path.

  1. 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' );
  1. 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 );
  1. 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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745169059a4614811.html

相关推荐

  • How to add custom taxonomy in custom post type permalink?

    I have a custom taxonomy called campaign and a custom post type called asset. For assets, I want to have the following p

    7小时前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信