Search code examples
wordpresshookpermalinks

WordPress post_link produces permalink that cannot be visited


I write the following codes to change the permalinks of posts with some specific categories, as below:

/* 2024-12-04: Define custom permalinks for some specific posts */
function post_custom_permalink($permalink, $post) {
    // Check if post belongs to some specific categories
    if (has_category('case-studies', $post)) {
        $permalink = home_url('case-studies/' . $post->post_name . '/');
        return $permalink;
    }
    else if (has_category('guides', $post)) {
        $permalink = home_url('guides/' . $post->post_name . '/');
        return $permalink;
    }
    else if (has_category('tools', $post)) {
        $permalink = home_url('tools/' . $post->post_name . '/');
        return $permalink;
    }    
    
    // For all other cases, return the original permalink
    return $permalink;
}
add_filter('post_link', 'post_custom_permalink', 10, 2);

Now the problem is: when I create a post "Test Tool" with category tools, its permalink is shown as https://www.sample.com/tools/test-tool/.

But when I visit https://www.sample.com/tools/test-tool/, I will get 404 not found error. If I visit https://www.sample.com/test-tool/, I can see the post. Why?


Solution

  • Using the post_link filter only changes the link, it doesn't inform WordPress' rewrite rules about the permalink change. To support the change, use the add_rewrite_rule() function to define the additional rule for accessing posts (untested):

    add_action( 'init', static function () : void {
       add_rewrite_rule( '^case-studies/([^/]+)(?:/([0-9]+))?/?$', 'index.php?name=$matches[1]&page=$matches[2]', 'top' );
        ...
    } );
    

    Remember to flush the rewrite rules after implementing.