Solved

mod_rewrite and php. 500 points.

Posted on 2007-03-27
17
244 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 8
17 Comments
 
LVL 24

Expert Comment

by:glcummins
ID: 18800616
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
ID: 18800660

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
ID: 18800721
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
WordPress Tutorial 1: Installation & Setup

WordPress is a very popular option for running your web site and can be used to get your content online quickly for the world to see. This guide will walk you through installing the WordPress server software and the initial setup process.

 
LVL 11

Expert Comment

by:JamesCssl
ID: 18800753
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
ID: 18800874

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
ID: 18800889
>> 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
ID: 18800971
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
ID: 18800993

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

Expert Comment

by:glcummins
ID: 18801045
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
ID: 18801106

>> 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
ID: 18801206
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
ID: 18801326

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
ID: 18801335
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
ID: 18801350
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
ID: 18801407
>> 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
ID: 18801900
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
ID: 18806505

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

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

These days socially coordinated efforts have turned into a critical requirement for enterprises.
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

617 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