skip to Main Content

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:wampwwwcollegeotp.php on line
11

Notice: Undefined index: user in C:wampwwwcollegeotp.php on line
11

UPDATE

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?

2

Answers


  1. 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-]+)
    

    enter image description here

    RegEx Descriptive Graph

    This link helps you to visualizes your expressions for the RewriteRule:

    enter image description here

    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.

    Login or Signup to reply.
  2. 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 to http://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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search