apache.htaccessmod-rewrite

Apache rewrite engine issue - Removing PHP extension & adding trailing slash


I'm seeking help with configuring the Apache rewrite engine as I'm relatively new to working with it. My goal is to remove the PHP extension from URLs when a file is accessed in the browser, and also to ensure that URLs have a trailing slash if it's missing. Unfortunately, I'm encountering difficulties with the current configuration because it does not remove the PHP extension, but I am able to access the files without the extension.

For example, if the user enters https://example.com/test.php, it should be rewritten to https://example.com/test/. Furthermore, all PHP files should be accessible through URLs in the following formats:

https://example.com/test.php
https://example.com/test
https://example.com/test/

Here is what I have right now:

.htaccess

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]

When I use the configuration above and enter https://example.com/test.php, then it stays like that.


Solution

  • When I use the configuration above and enter https://example.com/test.php, then it stays like that.

    That is because you don't have any redirect rule that removes .php extension and adds a trailing /. Also note that you don't need 2 separate rules for adding .php internally.

    You may use following rules in your root .htaccess:

    RewriteEngine On
    
    # removes .php and adds a trailing /
    # i.e. to externally redirect /path/file.php to /path/file/
    RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
    RewriteRule ^ /%1/ [R=307,NE,L]
    
    # adds a trailing slash to non files 
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=307,NE]
    
    # internally rewrites /path/file/ to /path/file.php
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^(.+)/$ $1.php [L]
    

    Once you verify it is working fine, replace R=307 (temporary redirect) to R=308 (permanent redirect). Avoid using R=308 (Permanent Redirect) while testing your mod_rewrite rules.