Htaccess novice question

I’ve got a whole bunch of redirects to sort, having redesigned my site to more search friendly urls.

Extract:


RewriteEngine On
RewriteRule ^aboutus.php$ http://www.businessyork.com/aboutus  [R=301,L]
RewriteRule ^contactus.php$ http://www.businessyork.com/contactus [R=301,L]
RewriteRule ^content.php$ http://www.businessyork.com/articles [R=301,L]
RewriteRule ^jobs.php$ http://www.businessyork.com/ [R=301,L]
RewriteRule ^byfeed.php$ http://www.businessyork.com/rss [R=301,L]
RewriteRule ^listings.php?first_letter=A$ http://www.businessyork.com/listings/A/ [R=301,L]

All seem to be working okay except the last entry that contains the first of the old site’s GET variables within the URL. If I type in the old url, I get a broken link warning even though the new path is valid, rather than being redirected as occurs with all the others.

I’d really appreciate anyone taking the time to point out what is hopefully a straightforward error in my file.

Many thanks in advance.

select the gray bar in my previous post with your mouse to find out (it’s gray text on a gray background) :slight_smile:

The first two are quite simple, I’ll give you the needed RewriteCond’s:


RewriteCond %{REQUEST_URI} cat_id=(\\d+)
RewriteCond %{REQUEST_URI} cat_name=([a-zA-Z-_]+)

I’ll leave the RewriteRule as an exercise to you.

Hint: you can include the matched cat_id using %1 and the matched cat_name using %2

As for the second rules, you can’t do that using Apache alone, since Apache has no idea that business_id 1 belongs to Ecado-Ltd, business_id 2 belongs to Niche-Furniture, etc.

To overcome this you need to route these URL’s through a PHP script and let that PHP script redirect to the proper location.


RewriteCond %{REQUEST_URI} business_id=(\\d+)
RewriteRule ^full_listing\\.php$ redirect_full_listing.php?business_id=%1 [L]

redirect_full_listing.php


$businessName=getBusinessNameForBusinessId($_GET['business_id']);
header('Location: http://www.businessyork.com/full_listing/'.$_GET['business_id'].'/'.$businessName, 301, true);

Where of course getBusinessNameForBusinessId is just an example, not an actual PHP function :wink:

Thank you - your much better alternative works a treat.

Sorry to push my luck but how would I tackle the rewrite rules when I have more than one variable to deal with in the query string i.e. also for cat_names, cat_ids as per the following:


RewriteRule ^listings.php?cat_id=1&cat_name=Accountants$ http://www.businessyork.com/listings/1/Accountants [R=301,L]
RewriteRule ^listings.php?cat_id=2&cat_name=Accounting-&-Book-Keeping-Services$ http://www.businessyork.com/listings/2/Accounting-&-Book-Keeping-Services [R=301,L]

And then for business ids and names:


RewriteRule ^full_listing.php?business_id=1$ http://www.businessyork.com/full_listing/1/Ecado-Ltd [R=301,L]
RewriteRule ^full_listing.php?business_id=2$ http://www.businessyork.com/full_listing/2/Niche-Furniture [R=301,L]

As the htaccess file has about 2000 (not working) entries, I’d be massively grateful if there’s a way to condense this all in the same way.

Thanks again Scallio.

Thanks Scallio - your help is getting me close but, due to my inexperience, not quite there .

I’ve succeeded in getting the cat_id in the correct position in the URL for the redirect


RewriteCond %{QUERY_STRING} cat_id=(\\d+)
RewriteRule ^listings.php$ http://www.businessyork.com/listings/%1/? [R=301,L]

However, when I also add the rewrite condition to pick up the cat_name variable (expecting them now to be %1 and %2) cat_name overwrites %1 and I lose the cat_id - there is no %2 i.e.


RewriteCond %{QUERY_STRING} cat_id=(\\d+)
RewriteCond %{QUERY_STRING} cat_name=([a-zA-Z-_]+)
RewriteRule ^listings.php$ http://www.businessyork.com/listings/%1/%2? [R=301,L]

This redirects to listings/Accountants rather than listings/1/Accountants as required.

First of all, you’re using a screwdriver to drive a nail in the wall. Sure it works, but don’t you think a hammer (Redirect in this case) would be better? :slight_smile:


RewriteEngine On
Redirect aboutus.php http://www.businessyork.com/aboutus
Redirect contactus.php http://www.businessyork.com/contactus
Redirect content.php http://www.businessyork.com/articles
Redirect jobs.php http://www.businessyork.com/
Redirect byfeed.php http://www.businessyork.com/rss

As for the last entry, that doesn’t work because you can’t access the get parameters in a RewriteRule (nor in a Redirect), you need a combination of a RewriteCond and RewriteRule, like so:


RewriteEngine On
RewriteCond %{QUERY_STRING} first_letter=([A-Z])
RewriteRule ^listings\\.php$ http://www.businessyork.com/listings/%1? [L,R=301]

Note that this rule automatically works for all characters A through Z, so there is no need to add more rules for those :slight_smile:

The ? at the end of the rule is to prevent Apache from appending the query string to the new URL.

Hope that works for you and let me know if you have any questions :slight_smile:

Sorry for being v slow on this but have been battling away for ages and still getting either internal server errors or broken links still.

Looking at your first reply I can see how the rewrite condition took the query string and the rewrite rule popped it back in with the %1 in the redirect path.

But when you have established additional variables, what is the syntax for controlling this - is it %2 %3 etc.

RewriteCond %{REQUEST_URI} cat_id=(\d+)
RewriteCond %{REQUEST_URI} cat_name=([a-zA-Z-_]+)

Really appreciate your help and your attempts to get me to do some of the work - sorry I’m not doing so well with my end of the bargain!

Cheers guys,

Been battling this for longer than I’d have cared to but a successful outcomes always takes the edge of things!

I’ve redesigned the site quite extensively and one of the purposes of the redesign was to make sure all the currently indexed pages redirect to the equivalent on the new site which is using search friendly urls via trackbacks hence the aboutus.php to /aboutus

Thanks to your assistance, hopefully I won’t lose any (more!) search ranking.

Yeah that’s my bad, apparently Apache only takes the matched of the last RewriteCond into account, so you should merge the two RewriteCond’s into one:


RewriteCond %{QUERY_STRING} cat_id=(\\d+)&cat_name=([a-zA-Z-_]+)

The RewriteRule should then work with %1 and %2

Question for you, what happens if I type cat_name=MyCompany&cat_id=1? Do you know how to solve that? :slight_smile:

Edit:

dklynn beat me to it :slight_smile:

An excellent job thus far from ScallioXTX!

What you’re asking about is something I don’t particularly care for in mod_rewrite: The %n is only from the last statement processed. Therefore, you’ll need to ensure that both your key/value pairs are always present and in the same order (although I don’t understand why you really need both the id and name).

RewriteCond %{QUERY_STRING} cat_id=(\\d+)&cat_name=([-a-zA-Z_]+)

Please note that I’ve moved the hyphen to the first character so the regex engine will not treat it as part of a range definition, i.e., a-z.

IF the cat_id is always required and the cat_name is optional, then

RewriteCond %{QUERY_STRING} cat_id=(\\d+)(&cat_name=([-a-zA-Z_]+))?

Note, though, that the earlier %2 becomes %3 in the RewriteRule.

For others wondering whether you can pick variables from multiple RewriteCond statements, yes, but you’d need to carefully craft the value/regex with the value/variable, i.e., repeat the %n from the previous statement and capture it again.

If I may go back to the top to ask a question, though, what is Apache supposed to serve with

RewriteRule ^aboutus.php$ http://www.businessyork.com/aboutus  [R=301,L]

Are you using an AddType handler for extensionless files or looping back to the php script (unless you’re VERY careful, that’ll cause a loop)?

Regards,

DK