Third party cookies may be stored when visiting this site. Please see the cookie information.

PenguinTutor YouTube Channel

Apache mod_rewrite with Query String - redirecting wordpress pages to posts

I'm in the process or reorganising some of the posts on my blog at www.watkissonline.co.uk. I had some particularly long posts which I'd created as pages. I'm now going to move these to posts, and then create some "overview" pages to link to the posts.

The change in wordpress is fairly straightforward. Editing in the database directly it's just a case of change the status from static to published. The problem is that I want to provide redirection, so that anyone using the old URLs will still work, and so that the search engine rankings that the pages already have isn't lost.

If you are not familiar with mod_rewrite then it is a very powerful tool that allows you to remap pages in apache using regular expressions. It goes much further than the mod_alias tools such as Redirect and RedirectMatch.

The problem is that following that basic introduction doesn't allow you to include the query string in the match (the bit of the url after the question mark ?). So I looked at a couple of different methods listed below, which allowed the query string to be used in the rewrite rule:

I am running Apache 2 on Ubuntu, which separates the configuration files into each virtual host. The file I updated is therefore /etc/apache2/sites-available/watkissonline.

I already had an entry enabling mod_rewrite rules:
RewriteEngine on

I also added a couple of lines to enable logging so I could see if it was working correctly:
RewriteLog <logdirectoryandfilename>
RewriteLogLevel 1

Then the RewriteRule entries go below those. At first I looked at using the QSA "Query String Append" function. This means that by adding [QSA] at the end of a rewrite rule any query string (anything after the question mark ?) from the originating URL is copied to the end of the rewritten URL. This however did not work for what I wanted as wordpress uses different parameters to the same script, rather than having different scripts.

For example the one I've remapped is page 59, which is now post 59. As a page the URL is http://watkissonline.co.uk/?page_id=59 , but after converting it to a post it became http://watkissonline.co.uk/?p=59 . So I needed a rule that would actually change the query string, not just copy it over.

The solution is to use a RewriteCond directive. RewriteCond (conditions) can look at different parts of the request, not just the basic part of the URL. For example the RewriteCond can be used to look at the IP address of the requester, the browser being used (UserAgent) or the one I'm interested in the query string.

The entries that I created are:

RewriteCond %{query_string} ^page_id=59$
RewriteRule ^/wordpress/ /wordpress/?p=59 [R,L]

Although these are over two lines it is in effect the same rule.

The first line looks in the query_string and if it is with page_id=59, then it will apply the following rule. If that doesn't match then that rule will not be applied.

The second line then performs a replace using p instead of the page_id.

That is sufficient for this example. Another useful bit of information is that if you have information in the RewriteCond that you'd like to substitute in the RewriteRule then it can be accessed as %1, %2 etc., whereas matching text within the RewriteRule is accessed as $1, $2 etc.

For example if I had wanted to redirect all the pages to posts (which is not what I want as I am adding new pages), then I could have used:

RewriteCond %{query_string} ^page_id=(59)$
RewriteRule ^/wordpress/ /wordpress/?p=%1 [R,L]

This works fine for a server that I run myself. The only thing now is that I'm wanting to do something similar on a hosted website where I don't have access to the configuration files. The mod_rewrite rules can be added to the .htaccess file if it is setup to allow it, but the provider I use appears to allow mod_alias, but not mod_rewrite.

If anyone knows of any way of doing something similar with the mod_alias (or even a way of just adding a query string on the redirect url using RedirectMatch) then please leave a comment, as I am still looking at how it can be achieved.