[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 254
  • Last Modified:

mod_rewrite and php. 500 points.

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
geordie007
Asked:
geordie007
  • 8
  • 8
1 Solution
 
glcumminsCommented:
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
 
geordie007Author Commented:

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
 
glcumminsCommented:
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
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
JamesCsslCommented:
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
 
geordie007Author Commented:

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
 
geordie007Author Commented:
>> 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
 
glcumminsCommented:
The rule you posted here looks correct. Are you able to post the portion of the script that displays the $_REQUEST/$_GET superglobals?
0
 
geordie007Author Commented:

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
 
glcumminsCommented:
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
 
geordie007Author Commented:

>> 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
 
glcumminsCommented:
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
 
geordie007Author Commented:

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
 
glcumminsCommented:
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
 
glcumminsCommented:
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
 
geordie007Author Commented:
>> 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
 
glcumminsCommented:
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
 
geordie007Author Commented:

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

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 8
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now