When I type www.example.com/username
the GET username is echoed as username.php
Because you have a rewrite earlier in the file:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
that rewrites /username
(any request that does not map to an existing file) to /username.php
before rewriting this to userprofile.php?username=username.php
. Hence why you see the GET param value with a .php
suffix.
Likewise, the following two RewriteRule
directives aren't doing anything currently, since the earlier rule is catching the request.
RewriteRule ^([^\.]+)$ $1index [NC,L]
RewriteRule ^([^\.]+)$ $1login [NC,L]
And these would only conflict with the "username" rewrite, if we modify the preceding rewrite to append the .php
extension. But also, these two rules conflict with each other - you are matching the same URL with both - the first rule would always win. (One input, with two different outputs is just not possible in any scenario.) In fact, this will likely generate a rewrite loop.
These two directives should be removed.
To avoid .php
being appended to username
, you could check that the .php
file exists before rewriting to it. For example:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
However, I would also consider changing your URL structure so you can easily target URLs that are specifically stating a username. For example:
www.example.com/u/username
Then your directive can be written less ambiguously (and wouldn't be so dependent on the ordering of directives in your file):
RewriteRule ^u/(.*)$ userprofile.php?username=$1 [QSA,L]
Also, be more specific in the regex that captures the username. The pattern .*
captures anything. For example, if usernames can only contain the letters a..z then use a regex like ^u/([a-z]+)$
. And if usernames must be 4 or more characters then: ^u/([a-z]{4,})$
.