Search code examples
phpwordpressurl-rewritingcustom-post-type

WordPress custom post type permalink as post ID (multiple CPTs)


I'm working on a site for a sports team with multiple age ranges. I've created two custom post types (teams and players) and want to link to each type of CPT via the post_id, rather than the post name informing the permalink.

I found some code online to adapt the permalink to the post_id, but despite passing the post_type to the function, which I thought would only adapt that cpt, it's adapting every cpt - so despite choosing to only change the team permalink, it's changing both the team and player permalinks to 'team/post_id'.

// Rewrite permalink structure
function teams_rewrite() {
    global $wp_rewrite;
    $queryarg = 'post_type=teams&p=';
    $wp_rewrite->add_rewrite_tag( '%cpt_id%', '([^/]+)', $queryarg );
    $wp_rewrite->add_permastruct( 'teams', '/teams/%cpt_id%/', false );
}
add_action( 'init', 'teams_rewrite' );

function teams_permalink( $post_link, $id = 0, $leavename ) {
    global $wp_rewrite;
    $post = &get_post( $id );
    if ( is_wp_error( $post ) )
        return $post;
        $newlink = $wp_rewrite->get_extra_permastruct( 'teams' );
        $newlink = str_replace( '%cpt_id%', $post->ID, $newlink );
        $newlink = home_url( user_trailingslashit( $newlink ) );
    return $newlink;
}
add_filter('post_type_link', 'teams_permalink', 1, 3);

Both CPTs have their own $arg in their setup:

'rewrite'=> array( 'with_front' => false, 'slug' => 'players' )
'rewrite'=> array( 'with_front' => false, 'slug' => 'teams' )

UPDATE In addition, I've just discovered that this breaks all the permalinks, except the teams CPT that is listed.


Solution

  • function teams_permalink( $post_link, $id = 0, $leavename ) {
        global $wp_rewrite;
        $post = &get_post( $id );
        if ( is_wp_error( $post ) || get_post_type($post) != 'teams')
            return $post_link;
    
        $newlink = $wp_rewrite->get_extra_permastruct( 'teams' );
        $newlink = str_replace( '%cpt_id%', $post->ID, $newlink );
        $newlink = home_url( user_trailingslashit( $newlink ) );
        return $newlink;
    }
    add_filter('post_type_link', 'teams_permalink', 1, 3);
    

    Can you try this? So here I added an extra check to make sure that the newlink is only updated for teams post_type.

    Also you where returning $post which might cause some issues since functions which are using this filter will be expecting a string therefore we are now returning $post_link