permalink independent on the post’s name stored in the database

I’m trying to make a custom permalink structure for my posts.

www.example.com / post / %post_id% / %posttitle% /

In this permalink, the post’s ID comes first, then the post’s title after it.


Things I know until now

postname is usually stored in the wp_posts table in the post_name row, and it controlles the post’s URL. ie: if the post’s post_name is my-post-name, it’s default URL will be www.example.com/post/my-post-name.

post names are stored in the database in a way such that every post has a unique post name. If two posts have the same title (for example new-advanced-topic), the first post’s name will be new-advanced-topic and the second post’s name will be new-advanced-topic-2. And so there URLs will differ from each other.


What I want

But I don’t want the post’s URL to depend on the post’s name stored in the database.

The structure I want is similar to

www.example.com / post / %post_id% / %posttitle% /

Suppose that There is 2 posts stored in the database with these values

╔════╦════════════════════╦═════════════════════╗
║ ID ║     post_title     ║      post_name      ║
╠════╬════════════════════╬═════════════════════╣
║ 25 ║ new-advanced-topic ║ new-advanced-topic  ║
║ 26 ║ new-advanced-topic ║ new-advanced-topic2 ║
╚════╩════════════════════╩═════════════════════╝
  • I want the post’s URL to depend only on the post’s ID. So if the user requested www.example.com/post/25/pla-pla-pla, The post that will be displayed is the one which it’s id is 25.
  • When a user requests the link www.example.com/post/{%post_id%}/pla-pla-pla, I want WordPress to redirect him to www.example.com/post/{%post_id%}/{%post_title%}.

So if user requested www.example.com/post/25/pla-pla-pla, WordPress will redirect him to www.example.com/post/25/new-advanced-topic and display the post with ID=25.

And if user requested www.example.com/post/26/new-advanced-topic2, WordPress will redirect him to www.example.com/post/26/new-advanced-topic and display the post with ID=26.

And if user requested www.example.com/post/100/new-advanced-topic, a 404 error should appear to him since there’s no post stored in the database with ID=100.

I tried to write a new rewrite_rule to do this but I couldn’t figer any way to write it’s regex.

How can I do this using the wp_rewrite rules.

2 s
2

We have to do this keeping post_name unique. Otherwise, it might cause many troubles. We can use post_title with sanitize_title. In this way, you can keep your URL nice and clean, and your post_name will remain unique as well.

First we will need to write custom permalink structure.

function my_awesome_permalink( $url, $post, $leavename ) {
    $url= trailingslashit( home_url('/post/'. $post->ID ."https://wordpress.stackexchange.com/". sanitize_title($post->post_title) ."https://wordpress.stackexchange.com/" ) );
    return $url;
}
add_filter( 'post_link', 'my_awesome_permalink', 10, 3 );

Now, our custom permalink structure is ready. It will become www.example.com/post/{%post_id%}/{%post_title%} e.g.: www.example.com/post/25/my-awesome-post-title . We will need to add proper rewrite rule to make WP understand and return the right post.

add_action('generate_rewrite_rules', 'custom_rewrite_rules');
function custom_rewrite_rules( $wp_rewrite ) {
    $new_rules['^post/([0-9]+)/([^/]+)/?'] = 'index.php?p=$matches[1]';
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
    return $wp_rewrite;
}

With above code, you will be able to make your post permalink structure to www.example.com/post/25/my-awesome-post-title and it will show correct post.

One problem with above code is, you won’t be able to edit post slug from post editor. But your post url now comes from post title, which is editable!

Leave a Comment