2

Right now my shortlink structure looks something like this:

example.com/?p=451

I would prefer it to look more like this:

example.com/abc123

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

4
  • 1
    Do you mean edit the core file itself? If so, that's probably not a good idea as it makes upgrading harder. A plugin would be the way to go. Commented Aug 29, 2011 at 18:34
  • @Christopher Davis This is true...Ahhh I was trying to avoid a plugin as many seem to slow down my sites.
    – Matt
    Commented Aug 29, 2011 at 21:07
  • 3
    Plugins don't slow down sites. Overly complex plugins that try to do too much slow down sites. I run upwards of 50 plugins and have no issues. Just something to keep in mind: simple is better.
    – Otto
    Commented Aug 29, 2011 at 22:14
  • How will you create this structure easily at the time of placing it? Commented Sep 13, 2017 at 22:27

3 Answers 3

5

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

6
  • I'm actually having a little bit of trouble with this plugin. Right now my ShortUrl (without any plugin or modification to WordPress) looks like this structure: example.com/?p=451 How can I get it to look like this: example.com/short451 (I guess 451 is the post id?)
    – Matt
    Commented Sep 2, 2011 at 13:37
  • You need to change your permalink settings to pretty permalinks. settings > permalinks Commented Sep 2, 2011 at 14:00
  • do I need to somehow activate this option? I don't see it in settings > permalinks
    – Matt
    Commented Sep 2, 2011 at 15:46
  • Nope, just select something other than default for your permalink structure and it should work. Commented Sep 2, 2011 at 16:18
  • 1
    One redirect happens. example.com/s/121 is rewritten, not redirected. The function hooked into template_redirect actually does the redirect from short URL to the canonical permalink. Commented Jul 2, 2012 at 4:56
1

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]
0
0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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