How do I customize my WordPress shortlink structure in link-template.php without a plugin?

Right now my shortlink structure looks something like this:

example.com/?p=451

Read More

I would prefer it to look more like this:

example.com/abc123

Any ideas how I can alter the code to do just this?

Related posts

Leave a Reply

3 comments

  1. Okay, so, as mentioned in my comment to you: altering core files is not a good idea. But here is a plugin solution.

    First we’re going to create our own rewrite rules that rewrite s/123 (replace 123 with a post ID) to index.php?short=123. We’ll also have to filter the WordPress query variables so we can use them later.

    <?php
    add_action( 'init', 'wpse26869_add_rewrites' );
    function wpse26869_add_rewrites()
    {
        add_rewrite_rule( '^s/(d+)$', 'index.php?short=$matches[1]', 'top' );
    }
    
    add_filter( 'query_vars', 'wpse26869_query_vars', 10, 1 );
    function wpse26869_query_vars( $vars )
    {
        $vars[] = 'short';
        return $vars;
    }
    

    The add_rewrite_rule call says “rewite s followed by a slash and a string of one or more digits to index.php?short=the_string_of_digits.

    Then we can hook into template redirect and see if our query variable is there. If it is, we’ll try and get a permalink out of it. If that fails, we’ll throw a 404 error. Otherwise, we’ll use `wp_redirect’ to send folks to the actual post.

    <?php
    add_action( 'template_redirect', 'wpse26869_shortlink_redirect' );
    function wpse26869_shortlink_redirect()
    {
        // bail if this isn't a short link
        if( ! get_query_var( 'short' ) ) return;
        global $wp_query;
    
        $id = absint( get_query_var( 'short' ) );
        if( ! $id )
        {
            $wp_query->is_404 = true;
            return;
        }
    
        $link = get_permalink( $id );
        if( ! $link )
        {
            $wp_query->is_404 = true;
            return;
        }
    
        wp_redirect( esc_url( $link ), 301 );
        exit();
    }
    

    Finally, we hook into get_shortlink to change how our rel=”shortlink” appears in the <head> section of the site, and elsewhere. This new shortlink structure will reflect the rewrite rule we wrote above.

    <?php
    add_filter( 'get_shortlink', 'wpse26869_get_shortlink', 10, 3 );
    function wpse26869_get_shortlink( $link, $id, $context )
    {
        if( 'query' == $context && is_single() )
        {
            $id = get_queried_object_id();
        }
        return home_url( 's/' . $id );
    }
    

    As a plugin:
    https://gist.github.com/1179555

  2. Aside from @ChristopherDavis’s answer, you can also do it in a PHP independent way, using .htaccess. Simply add this rule:

    RewriteEngine On
    RewriteRule ^s/(d+)$ index.php?p=$1 [L]
    

    Alternative without mod_rewrite, using mod_alias:

    RedirectMatch Permanent ^/s/(d+)$ /?p=$1
    

    The only problem is, two redirects happen here (instead of 1) — (for example) if user visits http://example.com/s/121/ he is redirected by the web server to http://example.com/index.php?p=121/ and then by WordPress to the actual permalink of the post.

    The advantage is, this never breaks! Plugins may break, but this does not.

    PS: I use this (short link structure would be http://example.com/-121 where 121 is post ID):

    RewriteEngine On
    RewriteRule ^-(d+)$ index.php?p=$1 [L]
    
  3. using Redirection plugin, you can add a redirect which achieves this without touching PHP or .htaccess.

    prerequisites

    • install and set up Redirection plugin

    add redirect

    • go to Tools > Redirection
    • click add new button

    redirect parameters

    • source url: ^/s/(d+)$
    • url options (located far right): choose regex
    • target url: /index.php?p=$1

    this method has the following advantages

    • no PHP coding, no .htaccess editing
    • access tracking – you can see how many are hitting the shortlink redirect right from the dashboard
    • 404 logging – helps with troubleshooting in case you mess up the regex
    • flexibility – if you want, you could create multiple shortlink redirects based on post type or source (e.g. email vs. print vs. media vs. youtube) for tracking purposes
    • you can optionally make any rule case-insensitive – this is especially useful if you are counting on people to enter this URL manually

    notes

    thanks to @its_me for the .htaccess method as this gave me the exact regex expressions i needed