skip to Main Content

I have this .htaccess file and I have no knowledge with mod_rewrite,

RewriteEngine On
RewriteRule ^(.+[^/])/$ http://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{THE_REQUEST} s/([^.]+).php [NC]
RewriteRule ^ /%1 [NE,L,R]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)/?$ /$1.php  [L]

What I want to achieve is to have localhost/viewticket/${id} instead of localhost/viewticket.php?id=123

I have tried many .htaccess rules but none worked except this one that hides .php in my URL.

3

Answers


  1. Make sure you’ve changed your internal URLs so you are linking to /viewticket/<id>. Then add the following at the top of the root .htaccess file:

    # Prevent MutliViews rewriting "viewticket" and omitting the URL parameter
    Options -MultiViews
    
    RewriteEngine On
    
    # Redirect any direct requests to "/viewticket.php?id=<id>" to "/viewticket/<id>"
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond %{QUERY_STRING} ^id=(d*)
    RewriteRule ^(viewticket).php$ /$1/%1 [R=301,L]
    
    # Rewrite "/viewticket/<id>" to "viewticket.php?id=<id>"
    RewriteRule ^(viewticket)/(d*)$ $1.php?id=$2 [QSA,L]
    

    If you are not expecting any query string on your "pretty" /viewticket/<id> URL then remove the QSA (Query String Append) flag in the last rule.

    $1 is a backreference to the first capturing group (parenthesised subpattern) in the RewriteRule pattern. Likewise, %1 is a backreference to the first capturing group in the last matched CondPattern (RewriteCond directive).

    Always test first with 302 (temporary) redirects to avoid potential caching issues and only change to a 301 (permanent) redirect when you are sure everything is working as intended. Clear your browser cache before testing.

    Reference:


    Additional:

    RewriteEngine On
    RewriteRule ^(.+[^/])/$ http://%{HTTP_HOST}/$1 [R=301,L]
    RewriteCond %{THE_REQUEST} s/([^.]+).php [NC]
    RewriteRule ^ /%1 [NE,L,R]
    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^(.*)/?$ /$1.php  [L]
    

    Your existing directives (that remove the trailing slash and .php extension) are not quite correct.

    Your first rule that unconditionally removes the trailing slash will also "try" to remove the trailing slash from directories as well – which will conflict with mod_dir and result in a redirect loop. The negated character class [^/] (to match a non-slash character) in the middle of the regex would seem to be superfluous. This also redirects to HTTP (not HTTPS)?

    The second rule that removes the .php extension would also erroneosuly match .php should it appear in the query string portion of the URL. eg. /foo?bar.php would be redirected to /foo?bar. Although the regex ([^.]+) does avoid the perhaps more common case of /foo.php?bar.php being erroneously redirected.

    The third rule that appends the .php extension via an internal rewrite could potentially result in a rewrite-loop (500 Internal Server Error) if you received a request of the form /foo/bar and /foo.php exists in the root of the filesystem. Also, the (optional) trailing slash is also captured by the capturing subgroup, since the * quantifier is greedy. This would also result in a malformed rewrite, if it wasn’t for the first rule that removes the trailing slash. (But since the trailing slash is removed then the optional trailing slash in this rule is redundant.)

    If you still need these rules to remove the trailing slash and handle extensionless .php URLs then have these rules as follows. Make sure you are already linking to the extensionless URLs internally. These rules should follow the rule block I posted above.

    # Remove trailing slash
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
    
    # Remove ".php" extension if present on the initial request
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule (.+).php$ /$1 [R=301,L]
    
    # Append ".php" extension if request maps to a PHP file
    RewriteCond %{DOCUMENT_ROOT}/$1.php -f
    RewriteRule ^(.*?)/?$ $1.php  [L]
    

    These directives (and your original directives for that matter) do assume the .htaccess file is located in the document root directory.

    Login or Signup to reply.
  2. You can use the following code:

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^([^/]+)/$ $1.php
    RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !(.[a-zA-Z0-9]{1,5}|/)$
    RewriteRule (.*)$ /$1/ [R=301,L
    

    And if it won’t works you can read this PDF file: How to remove PHP or HTML extensions with htaccess

    Login or Signup to reply.
  3. I created this one for you, just erase yours and copy this one enjoy^^

    IndexIgnore */*
    
    Options FollowSymLinks
    AddDefaultCharset utf-8
    
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteBase /
        RewriteRule ^viewticket/([^/]+)/?([^/]*)/?([^/]*)$ viewticket.php?id=$1&param2=$2&param3=$3 [L]
        RewriteCond %{REQUEST_FILENAME}.php -f
        RewriteRule ^(.*)/?$ /$1.php  [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-l
        RewriteRule . index.php [L]
    </IfModule>```
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search