If you are changing your permalinks structure differently than what is described below (e.g., going from name-based permalinks back to name and date-based permalinks), there is a WordPress plugin that can take care of you. If all you want to do is change from name and date-based permalinks to name-based permalinks, the method described below should be a bit faster, as the redirect is handled at the server level rather than at the PHP level.
This is a follow-up to my earlier post Seamless Permalink Updating. The problem I faced was that I wanted to change my WordPress permalink settings from being date and name based to something which was simply name based.
Why did I want to do this?
- Permalinks would be shorter; removing the date information results in URIs which are eleven characters shorter.
- Permalinks would not only be more readable, they would be more meaningful to humans; dates aren’t as important as the content the page itself contains. If presented with a list of permalinks from this site, users should have a good idea of what they’ll get when they click them. There’s no reason to muddy those waters by injecting date information into the mix, diluting the impact of the domain and post slug.
- The content part of the permalinks (domain name + post slug) would carry more impact in various search engines, without date information (that may or may not be recognized as dates by search engine algorithms) diluting the value of whatever keywords may be present.
- Yes, this is a blog, and yes information is posted chronologically; however, this isn’t a novel, and the material here need not be read in a chronological manner in order to understand it. Having date-based permalinks creates the illusion that the date the material was posted is more important than it really is. Besides, posts are displayed with the date anyway; why give it to the user twice when I’m betting the date included with the post is glanced over by most users.
Great reasons, I think, which should suffice for now. So I wanted to change my permalinks; what did I do about it?
WordPress makes the process ridiculously simple.
- Visit the Permalinks page of the administration panel (
/wp-admin/options-permalink.php). - Select the button labeled “Custom, specify below.”
- In the box labeled “Custom structure,” enter the text
/%postname%/ - Submit the change via the “Update Permalink Structure »” button.
- Visit your site and verify that posts are not being given permalinks in the style
example.com/post-name-here/. Beautiful, no?
Like I said, ridiculously easy!
But consider: What happens to all the links out there on the Internet to your blog which make use of the previous style of permalinks? Try it out for yourself; find an old permalink in your browser’s history that still makes use of “Date and name based” permalinks and visit it.
404! You broke the Internet! File not found! It’s the end of the world as you know it!
But don’t worry, you can feel fine about it because I have a solution, provided that you are using Apache as your server environment (chances are, you are) and mod_alias is enabled (I’m unsure how common it is). We’ll be fixing our problem using the RedirectMatch directive of mod_alias.
- Download your blog’s primary
.htaccessfile; most likely, it’ll be in the same directory as your blog’swp-config.phpfile. -
Open it up, and find WordPress’ permalinks code. If you’ve never edited your
.htaccessfile before, it will most likely be the only code present. The code looks like this, give or take a line break:# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress - Before that WordPress code, you’ll want to add one of the following:
-
If your WordPress is installed in your domain’s root directory (e.g.,
example.com/wp-config.php), add this code, adjustingexample.comto your proper domain name:RedirectMatch permanent ^/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) http://example.com/$1 -
If your WordPress is installed in a subdirectory of your domain (e.g.,
example.com/blog/wp-config.php), add this code, adjustingexample.com/blogto your proper domain name and directory:RedirectMatch permanent /blog/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) http://example.com/blog/$1
-
- Save & upload the
.htaccessfile, and revisit one of your older date-based permalinks. If all went according to plan, you should be seamlessly redirected to your new name-based permalinks.
That’s all there is to it! If anyone can provide a better means, I’m open to it, but I’ve tested this out, and it works exactly as I want it to — posts work, paged posts work, pages work, and so on. I can’t promise this won’t break any WordPress plugins, so be prepared to give up this method (which is as easy as deleting whatever you add to .htaccess and switching your permalink structure back).
For the curious, this is what the code above does, piece by piece:
- RedirectMatch
- Begins the call to Apache’s mod_alias module.
- permanent
- Sends the client (i.e., the user, whether human or robot) instruction that this redirect is a permanent redirect and that the old address is invalid and should be from now on replaced with the new.
- ^/[0-9]{4}
- The address which we’re trying to match begins with a four-digit year stamp, so we first look for a slash followed by four numbers.
- /[0-9]{2}
- The address will next have a two-digit month stamp, so we check for another slash followed by two numbers.
- /[0-9]{2}
- The address will next have a two-digit day stamp, so we check for yet another slash followed again by two numbers.
- /([a-z0-9\-/]*)
- The address will then have the post slug, which can consist of a variety of lowercase letters, numbers, and dashes. So we look for any number of those. A post slug may include additional information after it, such as a page number on paged posts, so we include any number of slashes in our search as well. It’s enclosed in parentheses so we can capture that data and use it in the next section.
- http://example.com/$1
- This is the location of where we want to redirect to. The
$1at the end will be replaced by whatever was matched by the code in parentheses in the previous statement.
Edit: Whoops! Using the above RedirectMatch code prevented viewing of day archives (e.g., /2008/01/01/); swapping the asterisk (*) out for a plus sign (+) resolved the issue and allows day archives to be viewed. The code above has been corrected.
Popularity: 36%