Update URL Snippet to Canonical Permalink URL

My permalinks is in the format domain.com/post-id/post-slug

I notice this is a great choice for permalinks as I can share articles with a short URL like domain.com/123

Read More

But when I go to this short url, should it not redirect to show the full URL, becuase in the adress bar its only showing domain.com/123

Any setting to do to update the URL to the actual, without putting any additional load or the server.

UPDATE: My requirement is not to get a shortlink. Rather to convert an URL fragment to the full URL.

For eg: If I type domain.com/123/wrong-slug it gets corrected to domain.com/123/correct-slug
but if I type domain.com/123 it doesn’t get corrected to domain.com/123/post-slug

Related posts

4 comments

  1. Why?

    I think the reason why

    a) domain.com/123
    

    is not redirected back to

    b) domain.com/123/post-slug
    

    with the /%post_id%/%postname%/ permalinks settings, is that the matched rule is:

    [matched_rule] => ([0-9]+)(/[0-9]+)?/?$
    

    You can get that information from the global $wp object.

    There are other useful informations in $wpavailable after the wp action:

    Example (post): domain.com/123/post-slug/

    [query_vars] => Array
        (
            [p] => 123
            [page] => 
            [name] => post-slug
        )
    
    [query_string] => p=123&name=post-slug
    [request] => 123/post-slug
    [matched_rule] => ([0-9]+)/([^/]+)(/[0-9]+)?/?$
    [matched_query] => p=123&name=post-slug&page=
    [did_permalink] => 1
    

    Example (post): domain.com/123/:

    [query_vars] => Array
        (
            [p] => 123
            [page] => 
        )
    [query_string] => p=123
    [request] => 123
    [matched_rule] => ([0-9]+)(/[0-9]+)?/?$
    [matched_query] => p=123&page=
    [did_permalink] => 1
    

    Example (page): domain.com/hello-world/:

    [query_vars] => Array
        (
            [page] => 
            [pagename] => hello-world
        )
    
    [query_string] => pagename=hello-world
    [request] => hello-world
    [matched_rule] => (.?.+?)(/[0-9]+)?/?$
    [matched_query] => pagename=hello-world&page=
    [did_permalink] => 1
    

    Redirect example:

    Here’s an example how to redirect from a) to b) using information from the global $wp object:

    add_action( 'wp', function(){
        global $wp;
        if( is_numeric( $wp->request ) && empty( $wp->query_vars['page'] ) )
        {
            wp_redirect( get_permalink( absint( $wp->request ) ), 301 );
            exit();
        }
    });
    

    i.e. we redirect when the page query varaible is not set and the request is numeric.

    ps: I just want to mention that this is using the wp action, that is fired rather late, but before the template_redirect action, allowing the redirect possible.

    I also tried to come up with an example that is not using the $_SERVER variable ๐Ÿ˜‰

    Hope this helps.

  2. The shortlink of a WordPress post is on default domain.com/?p=30, not the Id after the domain. If you like a permalink to the ID as shortlink for each post, then is this possible via a plugin.

    The follow source is a example.

    add_filter('get_shortlink', 'fb_custom_shortlink_filter');
    function fb_custom_shortlink_filter() {
        global $post;
    
        return get_site_url() . '/fb/' . $post->ID;
    }
    

    enter image description here

    But if you will use the page in the front end with this new short url, is a rewrite important. Below a solution for php and a enhancement in the htaccess.

    Add the source in a plugin and add this to the front end or add in the theme file index.php. The source check the value token from the url. This is only possible ,if you enhance the url via mor_rewrite modul in the .htaccess, see below.

    if ( ! empty( $_GET['token'] ) ) {
      $id = strip_tags( $_GET['token'] );
      if ( is_numeric( $id ) ) {
        header( $_SERVER['SERVER_PROTOCOL'].' 301 Moved Permanently' );
        header( 'Location: ' . get_site_url() . '?p=' . $id );
        exit();
      }
    }
    
    header( $_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found' );
    header( 'Status:404' );
    die( '404 Not Found' )
    

    The rewrite inside the .htaccess

      RewriteEngine on
      RewriteCond   %{REQUEST_FILENAME} !-d
      RewriteCond   %{REQUEST_FILENAME} !-f
      RewriteRule   (.*) index.php?token=$1 [QSA,L]
    
  3. This is the closest I got. It makes URLs like what you wanted work: domain.com/123

    // refresh/flush permalinks in the dashboard if this is changed in any way
    add_filter( 'generate_rewrite_rules', 'create_post_id_url' );
    function create_post_id_url( $wp_rewrite ) {
        $feed_rules = array(
            '(d+)' => 'index.php?p='.$wp_rewrite->preg_index(1)
        );
        $wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
    }
    

    Add this anywhere (e.g. in functions.php), go to Settings > Permalinks and then Save.


    The only issue with this approach is that the the user will stay on domain.com/123 and won’t be redirected to the canonical version (domain.com/123/post-name). It’s not really much of an issue since you already have a canonical link in the <head> of the website, so it’s not an issue for search engines. It could actually be considered an advantage since the user doesn’t have to wait for a redirect.


    The alternative would be just using links like domain.com/?p=123. They are only 3 characters longer and don’t add any load on the server รขย€ย” they already work.


    In the end, why do you even need short urls? Twitter automatically shortens all URLs, I do not see any need to do it nowadays, they just impair the readability of URLs.

  4. You can use the following htaccess rule for redirecting domain.com/post-id to domain.com/post-id/post-slug.

    RedirectMatch 301 ^/(d+)$ http://domain.com/?p=$1
    

    Put this rule on top of the WordPress’s default rules.

Comments are closed.