Solved

mod_rewrite and php. 500 points.

Posted on 2007-03-27
17
225 Views
Last Modified: 2008-03-06
hi experts

this may be a stupid question, so apologies in advance.

i've never looked at mod_rewrite before, so i'm a little confused. if i get my apache server to rewrite this page:

/products.php?id=10

to:

/products/10/index.php

how does products.php know which item to show? the $_GET or $_REQUEST arrays either no longer exist (in the case of $_GET) or no longer contain the 'id' key. i have a horrible feeling that i'll then have to do something like exploding $_SERVER["PHP_SELF"] and pulling apart the url until i find the number, but i'm hoping it isn't as complicated as this, and i'm doing something wrong. afterall, if you were rewritting:

/index.php?year=07&month=07&day=07&id=07&page=07

to:

/07/07/07/07/07/index.php

ripping apart the url could get really irritating.

any advice would be great.

thanks

0
Comment
Question by:geordie007
  • 8
  • 8
17 Comments
 
LVL 24

Expert Comment

by:glcummins
Comment Utility
mod_rewrite is normally used to make the conversion go the other way. For example, your user would browse to:

http://www.yoursite.com/products/10/index.php

And mod_rewrite would translate that as:

http://www.yoursite.com/products.php?id=10

Then you just use $_REQUEST or $_GET as you normally would.

The reason for this is that 'http://www.yoursite.com/products/10/index.php' is a "search-engine friendly" URL, but 'http://www.yoursite.com/products.php?id=10' is not.
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility

that's what i thought it did. i'm obviously hopelessly confused. and i haven't even had a drink yet.

ok, so mod_rewrite would translate:

http://www.yoursite.com/products/10/index.php

as:

http://www.yoursite.com/products.php?id=10

? so, firstly, what appears in the browser location, the nice one (/10/index.php)? secondly, how do i link to that page, by using the nice one or the bad one. if i use the bad one and mod_rewrite translates it into the good one, my users would still be able to see where the bad one was pointing (in the status bar or source code) so i don't want that.

0
 
LVL 24

Expert Comment

by:glcummins
Comment Utility
The translation is completely invisible to the user so:

1) The 'nice' url would appear in the location bar, and
2) You would create your links to the 'nice' url

Also, depending on how you setup your rewrite function, you will probably want to use:

http://www.yoursite.com/products/10/

as the 'nice' URL. The 'index.php' is not necessary, because the rewrite will end up pointing to 'products.php', not 'index.php'.
0
 
LVL 11

Expert Comment

by:JamesCssl
Comment Utility
Like glcummins said, you seem to have it backwards.  mod_rewrite is usually used to translate the user sending this:

http://www.example.com/07/07/07/07/07/

as if the user requested this:

http://www.example.com/index.php?year=07&month=07&day=07&id=07&page=07

for this specific example, the mod_rewrite code could look like this:

/?(\d{2})/(\d{2})/(\d{2})/(\d{2})/(\d{2})/ /index.php?year=$1&month=$2&day=$3&id=$4&page=$5
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility

well, everything you describe is how i saw mod_rewrite working, but the reality is different. i *must* be doing something wrong.

this is my .htaccess file:

RewriteEngine On
RewriteRule ^products/([0-9]+)/ /products.php?id=$1

it obviously works because when i hit /products/10/ i get my file, and not a 404. however, i'm spitting out the $_REQUEST array and the $_GET array and neither contain anything. when i hit /products.php?id=10, the same file tells me that an id of 10 has been passed. so where am i going wrong?
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility
>> Like glcummins said, you seem to have it backwards.

sorry, i didn't explain very well. i don't have it backwards, i do understand the theory behind it, but thats about it! :)

i just can't seem to get, for example, http://www.example.com/07/07/07/07/07/ to contain my necessary $_GET values.
0
 
LVL 24

Expert Comment

by:glcummins
Comment Utility
The rule you posted here looks correct. Are you able to post the portion of the script that displays the $_REQUEST/$_GET superglobals?
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility

sure, it's just a test file so this is all it is:

<?
print "<p>" . $_SERVER["PHP_SELF"] . "</p>";
print_r($_GET);
print_r($_REQUEST);
?>

thanks for your help so far
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 24

Expert Comment

by:glcummins
Comment Utility
Does the first line print okay? (print "<p>" . $_SERVER["PHP_SELF"] . "</p>";)

If not, your server may have short-open tags (<?) disabled. If that is the case, you should use normal tags (<?php).


Also, just to double check, are you including the trailing slash when you call your 'nice' URLs? For example, '/products/10/' will work with your rewrite rule, but '/products/10' will not.
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility

>> If not, your server may have short-open tags (<?) disabled. If that is the case, you should use normal tags (<?php).

yeah, all fine. i'm new to mod_rewrite, but not php.

>> Also, just to double check, are you including the trailing slash when you call your 'nice' URLs? For example, '/products/10/' will work with your rewrite rule, but '/products/10' will not.

again, all fine. if it wasn't working, i think i would get a 404 rather than the correct page, but no vars.
0
 
LVL 24

Accepted Solution

by:
glcummins earned 500 total points
Comment Utility
Sorry, I don't mean to insult. Just want to make sure all the bases are covered. (I don't know how many times I've had a 'forehead-slap' moment when I miss something that should have been obvious.)

Still pondering this one.

I setup a test on my box, and it works correctly using the following setup:

File: .htaccess
-------------------
RewriteEngine On
RewriteRule ^products/([0-9]+)/([0-9]+)/ /products.php?id=$1&id2=$2

File: products.php
--------------------
<?php

print_r($_REQUEST);

print "<br />";

print_r($_GET);

?>

Access using:
-------------------
http://www.myserver.com/products/10/2/

Output:
--------------
Array ( [id] => 10 [id2] => 2 )
Array ( [id] => 10 [id2] => 2 )
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility

and sorry from me, i didn't take it as an insult, i appreciate your help.

well *that* is the strangest thing. while sitting here i found someone having the same problem on google, which he then fixed. the only difference i could see in the before and after was that he used two arguments. so i tried:

RewriteRule ^([a-z].*)/([0-9]+)/$ products.php?test=$1&id=$2

and it works fine. and that's exactly what you've just posted.

but if you then edit it so it only uses one argument, for example:

RewriteRule ^products/([0-9]+)/$ products.php?id=$1

it doesn't work!

so does that mean that you *must* pass more than one match for mod_rewrite to work? seems strange.
0
 
LVL 24

Expert Comment

by:glcummins
Comment Utility
Can you take a look at your rewrite logs to see how the script is actually being called?

To add logging, you can add the following lines to your httpd.conf file (This won't work in the .htaccess file):

 RewriteLog "/var/log/httpd/rewrite_log"
 RewriteLogLevel 3

After restarting Apache, take a look at /var/log/httpd/rewrite_log to see if the redirect is happening in an appropriate manner (correct variables are being passed).



0
 
LVL 24

Expert Comment

by:glcummins
Comment Utility
Sorry, I posted the last at the same time as you.

Yes, in order for the rule to work, you have to pass the number of arguments the rule expects. However, you can create multiple rules: One for only one argument, one for two arguments, etc.

Would that work in your situation?
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility
>> Yes, in order for the rule to work, you have to pass the number of arguments the rule expects.

but thats where i'm confused. if i write this:

RewriteRule ^products/([0-9]+)/$ products.php?id=$1

surely the rule is only expecting one argument? then is only one reg_ex on the left to match ([0-9]+), there's only one reg_ex container on the right ($1) and there's also only one url argument passed (id=), but it doesn't work. what makes it expect 2 or more in this case?
0
 
LVL 24

Expert Comment

by:glcummins
Comment Utility
I'm no regex expert, so forgive me if this is an obvious answer, but what is the purpose of the trailing '$' in your rule:

  ^products/([0-9]+)/$

I didn't use that in mine, and it seems to work as expected without it.
0
 
LVL 7

Author Comment

by:geordie007
Comment Utility

>> I'm no regex expert, so forgive me if this is an obvious answer, but what is the purpose of the trailing '$'

just an end of string, so if anything else occurs after it, it won't match. it's obviously not necessary in this case, but handy in others.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
If your site has a few sections that need to be secure when data is transmitted between the server and local computer, such as a /order/ section for ordering or /customer/ which contains customer data, etc it would of course be recommended to secure…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now