David Passmore David Passmore - 5 months ago 18
PHP Question

.htaccess 301 and PHP query string

I'm wondering if the wonderful world of the SO community can help me with this one.

I have the following URL's that I would like to redirect/rewrite in my

.htaccess
file.

1. Redirect



I am trying to 301 redirect this URL:

http://example.com/staff-view.php?i=ACCOUNT_ID_EXAMPLE


to

http://example.com/staff-view/ACCOUNT_ID_EXAMPLE/


I have attempted the following:

RewriteEngine On

RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+staff-view\.php\?i=([^\s]+) [NC]
RewriteRule ^ /staff-view/%1/? [R=301,L]


however when navigating to the from URL it does not redirect.

2. PHP Query String



I am using the below to rewrite:

RewriteRule ^staff-view/([^/]+)/?$ /staff-view.php?i=$1 [L,QSA,NC]


and accessing through URL

http://example.com/staff-view/ACCOUNT_ID_EXAMPLE/


it correctly directs me to the right page, but when attempting to access
ACCOUNT_ID_EXAMPLE
via the following methods:

<?
var_dump($_REQUEST);
var_dump($_GET);
?>


They both are empty:

array(0) { } array(0) { }


I would appreciate any help, if you need any more info, please let me know.




Update 1



Updated
.htaccess
file:

RewriteEngine On

RewriteRule ^staff/([^/]+)/?$ /staff-view.php?i=$1 [L,QSA,NC]

RewriteBase "/"

RewriteCond %{REQUEST_URI} ^staff-view\.php$
RewriteCond %{QUERY_STRING} ^i=([A-Z0-9_]*)$
RewriteRule ^(.*)$ ^staff/%1/


I have attempted to access the file from:

http://example.com/path/to/site/staff/ACCOUNT_ID


and it DOES NOT work. However, if I access the file from:

http://example2.com/staff/ACCOUNT_ID


it WORKS.

But if I go to
http://example2.com/staff-view.php?i=ACCOUNT_ID
it does not redirect to
http://example2.com/staff/ACCOUNT_ID
- this is not the end of the world, but I would like to fix it, but the deep directory issue as a priority
:)
.

Answer

Trying to parse %{THE_REQUEST} (e.g., "GET /staff-view.php?i=account_id HTTP/1.1") to extract both the path and the query string could work but it's unnecessarily complex. I think it's much simpler to use two rewrite conditions that take advantage of the server variables %{REQUEST_URI} and %{QUERY_STRING} because they are pre-populated with the info you're interested in.

Try the following:

RewriteEngine On

#If you don't have this set in your htaccess, 
#  Apache may prepend the final path with your on disk dir structure
RewriteBase "/"

#Rewrite if the /staff-view.php page is requested
RewriteCond %{REQUEST_URI}  ^/staff-view\.php$

#Rewrite if the query string contains i parameter anywhere
#If account ID can be only digits, use [0-9] instead of [a-zA-Z0-9_]
RewriteCond %{QUERY_STRING} .*\bi=([a-zA-Z0-9_]+)\b

#Rewrite the account ID as part of the path. Append the query string
#  in order to preserve other query parameters (eg: if user asked for
#  /staff-view.php?i=123&x=boo, you want to preserve x=boo.  a 301
#  redirect tells the browser to go to the new path and to remember it
#This will stop processing and cause the browser to make a new request
RewriteRule ^(.*)$  staff-view/%1/ [QSA,R=301,L]

#Finally, we want to silently forward any request matching the last
#  redirect target to the actual file that will serve the request. Notice
#  that this has a filename different from the initial staff-view.php so
#  we don't end up in an endless redirect loop. The account ID should
#  be of the same format as above: ([a-zA-Z0-9_]+).  The [L] flag tells
#  the server to stop looking for new redirect instructions
RewriteRule ^staff-view/([a-zA-Z0-9_]+)/$ final.php?i=$1 [L,QSA]

The logic is easy to follow: If the path requested is /staff-view.php, and if the query string contains the i parameter, tell the user's browser to go instead to /staff-view/ID, preserving the other query params. Finally, when the browser asks for this new path, silently (without telling the browser) forward the request to final.php along with the ID and other query params