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.

  • I haven't even thought this through properly but I can promise you that you are up for a world of pain with that as soon as you e.g. use plugins. – kraftner Feb 8 '16 at 16:30
  • 1
    The part of requesting post/25/anything-here and serve the post with ID 25 and redirecting to correct URL, is the easy part. Having two same slugs I think is more difficult. Currently WordPress allows same slugs for diffrent content types but not for the same content type. Think about it, it is really a very bad approach. It is bad to have two same titles, even worst if they share the slug. I can not think in any valid use case or any good reason to do it. Why do you want to do such thing?. – cybmeta Feb 8 '16 at 20:10

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 .'/'. sanitize_title($post->post_title) .'/' ) );
    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!

| improve this answer | |
  • 2
    @birgire thanks for pointing it out. I actually copied it from my functions.php and forgot to remove that part. Edited now. – тнє Sufi Feb 10 '16 at 14:33
  • It didn't work :( . I added it to the functions.php file and it didn't work. I tried also to add flush_rewrite_rules(); and nothing changed. – Yazan W Yusuf Feb 10 '16 at 17:12
  • 1
    @YazanWYusuf did you put these codes properly? I have tested, and working. However, you will need to resave permalink from Settings > Permalink. It will flush rewrite rules. And you should avoid using flush_rewrite_rules(), unless extensively necessary. – тнє Sufi Feb 10 '16 at 23:56

What I understand that you want to use post ID instead of Post Title .

and you have trouble because of the same titles name .

If that's right , the solution will be like following :

1 - change permalink to custom structure like the following figure

enter image description here

2- go to phpmyadmin and change your posts name like following figure

enter image description here

| improve this answer | |
  • if that is not the answer just tell me more – heshamhussain Feb 3 '16 at 3:36
  • I want both of the post ID and Post Title to appear in the URL. But choosing the right post to display should depend only on the post ID. The Post's title has no affect in displaying posts. Beside that, I don't want to change the database every time someone adds a new post. I want to do this using rewrite_mod so it's applied on all posts. – Yazan W Yusuf Feb 3 '16 at 4:03
  • 1
    there are many problem may appear to you , if you use the same post titles [ SEO ], look to this article wpbeginner.com/plugins/… – heshamhussain Feb 3 '16 at 4:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.