Reputation: 199
I have a PHP file named as otp.php
.
When URL in the URL bar is
http://localhost/college/otp/MTA=/teacher
It should be treated as
http://localhost/college/otp.php?user=MTA=&role=teacher
For this, I created .htaccess
file in http://localhost/college/:
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^otp/?$ otp.php [NC,L]
RewriteRule ^otp/[A-Za-z-]+/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2 [NC,L]
But, otp.php
file says:
Notice: Undefined index: role in C:\wamp\www\college\otp.php on line 11
Notice: Undefined index: user in C:\wamp\www\college\otp.php on line 11
When URL in the URL bar is
http://localhost/college/otp/MTA/teacher
It should be treated as
http://localhost/college/otp.php?user=MTA&role=teacher
How do I solve this problem?
Upvotes: 1
Views: 1739
Reputation: 45829
URL: /college/otp/MTA=/teacher
Target: /college/otp.php?user=MTA=&role=teacher
.htaccess: /college/.htaccess
RewriteRule ^otp/[A-Za-z-]+/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2 [NC,L]
Your RewriteRule
pattern needs a slight modification to match your example URL, since it will currently fail on the =
in MTA=
. (Although I've just noticed that the "update" to your question does not show a =
in the URL?) This pattern also needs to be capturing in order for the $1
to pick it up.
So, the above directive should read something like:
RewriteRule ^otp/([A-Za-z-]+=)/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2 [NC,L]
This assumes that =
always appears at the end of the path segment, as in your initial example (include it inside the character class if it can occur anywhere - although would be a bit confusing). The NC
flag is probably unnecessary, unless you also need to allow mixed case versions of otp
(unadvisable). You already allow for mixed case in your regex.
UPDATE#1: It seems the second path segment is a base64 encoded string/integer. For this you will need to include digits in the regex and there could be 0, 1 or 2 trailing =
characters. There is also no need to match a hyphen. For example:
RewriteRule ^otp/([A-Za-z0-9]+={0,2})/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2 [NC,L]
However, the other problem you seem to be experiencing (and the one which you are actually "seeing") is a conflict with MultiViews (part of mod_negotiation). This needs to be disabled for the above mod_rewrite directive to work (in fact, to do anything). If you are not enabling this in .htaccess
then disable it by including the following at the top of your .htaccess
file:
Options -MultiViews
If MultiViews is enabled then when you request otp
(where a file with the same basename exists which would also return an appropriate mime-type) mod_negotiation issues an internal subrequest for otp.php
. The problem here is that this occurs before mod_rewrite, so otp.php
ends up being called without any URL parameters.
Aside:
Your code should not be generating these "undefined index" notices. Since this is essentially "user provided data", you should check for it in your script. For example:
$role = isset($_GET['role']) ? $_GET['role'] : null;
RewriteEngine On # Turn on the rewriting engine
Note that Apache does not support line-end comments, so you should remove the # Turn on the rewriting engine
text from the first line. (Line-end comments can appear to "work", however, that is just a coincidence with how Apache directives work in general, other times they will result in a 500 internal server error.)
UPDATE#2:
If the URL bar has
http://localhost/college/otp.php?user=MTA=&role=teacher
, can it be changed tohttp://localhost/college/otp/MTA/teacher
?
Yes this can be done. Although I assume that MTA=
should appear in both places? (You have MTA=
in the source and MTA
in the target, which would presumably corrupt the base64 encoding?) I assume you are already linking to the correct URL internally and this is only to benefit stray requests (search engines, backlinks, etc.?)
You can implement an external redirect before the above rewrite, being careful not to redirect the rewritten URL and triggering a redirect loop. For example:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^user=([A-Za-z0-9]+={0,2})&role=([A-Za-z0-9-]+)
RewriteRule ^(otp)\.php$ /college/$1/%1/%2 [QSD,R=302,L]
This is basically the reverse of the internal rewrite (that appears later in the .htaccess
file). The condition that checks against the REDIRECT_STATUS
environment variable ensures that it only triggers for direct requests and not rewritten requests.
Note that since this is an external redirect, you need to include a root-relative URL-path in the substitution argument. ie. include the /college
subdirectory. (Or, you can use a relative substitution and set the RewriteBase
- although you'd only do this if you have several of these directives.)
$1
is a backreference to the RewriteRule
pattern (ie. always otp
) and %1
and %2
are backreferences to the preceding CondPattern, ie. the value of the user
and role
URL parameters respectively.
The QSD
flag (Apache 2.4+) discards the original query string from the request.
Upvotes: 2
Reputation: 27723
This tool might help you to write correct expressions for your RewriteRules. Maybe, this expression would give you an idea, where the problems may be:
(.*otp)\/([A-Za-z0-9-]+=)\/([A-Za-z0-9-]+)
This link helps you to visualizes your expressions for the RewriteRule:
Then, you can write a RewriteRule, maybe something similar to:
<IfModule mod_rewrite.c>
RewriteEngine On # Turn on the rewriting engine
RewriteCond %{HTTP_HOST} localhost [NC]
RewriteRule (.*otp)\/([A-Za-z0-9-]+=)\/([A-Za-z0-9-]+) $1.php?user=$2&role=$3 [NC,L]
</IfModule>
You might want to clear your browser history, every time that you modify your .htaccess
file.
Upvotes: 0