Search code examples
phpapache.htaccessclean-urls

How do I force clean urls with htaccess when mod rewrite enabled?


I'm trying that htaccess redirects all pages from .php to .html when mod rewrite is enabled. But I also want that in behind the scene, the server "serves" the .php files when recieving a .html request.

For example, I go to my website example.com/folder/file.html, so the server should render /folder/file.php and send it. But if I write in my browser example.com/folder/file.php, I want that the server redirects me to example.com/folder/file.html, and then, run the php code.

I want this so when mod_rewrite is enabled, my site will have the .html extensions, but when it is disabled, it will use the .php extensions.

What i tried to do is:

RewriteEngine On

RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)\.html$ $1.php [L]

RewriteRule ^(.*)\.php$ $1.html [R=307]

but it throws an infinite loop.


Solution

  • To achieve the desired behavior, you need to ensure that your rules don't create an infinite loop. Your current rules are causing a loop because both rules can be applied to the same request, resulting in a continuous redirection between .php and .html.

    Here's an updated version of your .htaccess file to avoid the infinite loop:

    
        Options +FollowSymLinks
        RewriteEngine On
        
        # Prevent internal redirect for existing files and directories
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        
        # Rewrite .html to .php internally
        RewriteRule ^(.*)\.html$ $1.php [L]
        
        # Redirect external requests from .php to .html
        RewriteCond %{THE_REQUEST} \.php
        RewriteRule ^(.*)\.php$ $1.html [R=307,L]
    
    

    Explanation:

    1. The first RewriteCond checks if the requested file or directory does not exist as a physical file or directory on the server.

    2. The second RewriteCond checks if the requested file does not exist as a physical file on the server.

    3. The first RewriteRule internally rewrites requests from .html to .php without redirecting the browser. The [L] flag indicates that this is the last rule to be processed if the conditions are met.

    4. The second set of conditions (RewriteCond and RewriteRule) checks if the request contains .php. If so, it redirects the browser to the corresponding .html file. The [R=307,L] flag performs a temporary (307) redirect and stops processing further rules.

    With these rules, you should be able to achieve the desired behavior without causing an infinite loop.