seaofinformation
seaofinformation

Reputation: 809

Rewrite extension if file exists, redirect if file does not exist, with htaccess

Using .htaccess, I'd like to redirect files that do not exist to a controller page, and rewrite the extension of .php files that do exist to an .html extension. If a file exists and is an .html page, I'd like it to remain the same. Every time I try to inject the rewrite rule from .php to .html, I seem to mess up the redirect to the controller page. So I'm not sure where to go from here:

Options -Indexes
Options +FollowSymLinks
DirectoryIndex index.php
ErrorDocument 404 /404.php

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ mycontroller.php [L,QSA]
</IfModule>

Any help I'd be most grateful for.

Edit

I seem to have found most of the answer here (but I have to leave out the ReweriteBse or it doesn't work). The biggest issue is that now, my existing .html files don't work, it only serves my .php files with .html extensions and directs all else to the controller. Existing .html files go to my 404 page. I'd like to know how I can keep my existing .html files intact. My new code as follows:

  RewriteEngine on

  RewriteCond %{THE_REQUEST} (.*)\.php  
  RewriteRule ^(.*)\.php $1.html [R=301,L]  

  RewriteCond %{THE_REQUEST} (.*)\.html  
  RewriteRule ^(.*)\.html $1.php [L]  

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ mycontroller.php [L,QSA]

Upvotes: 1

Views: 6213

Answers (3)

seaofinformation
seaofinformation

Reputation: 809

I'm sure there are better ways to do this, but the following works for my needs. The other answers provided didn't seem to work despite my attempts.

Options -Indexes
Options +FollowSymLinks
DirectoryIndex index.php
ErrorDocument 404 /404.php

<IfModule mod_rewrite.c>
  RewriteEngine on

  # Check if .html file already exists -- if so, do nothing
  RewriteCond %{REQUEST_FILENAME} -f
  RewriteCond %{THE_REQUEST} (.*)\.html  
  RewriteRule ^.*$ - [NC,L] 

  # Check if .php file already exists -- if so, rewrite extension to .html
  RewriteCond %{REQUEST_FILENAME} -f
  RewriteCond %{THE_REQUEST} (.*)\.php  
  RewriteRule ^(.*)\.php $1.html [R=301,L]  

  RewriteCond %{THE_REQUEST} (.*)\.html  
  RewriteRule ^(.*)\.html $1.php [L]  

  # All else goes to the controller page
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ mycontroller.php [L,QSA]
</IfModule>

Upvotes: 0

Jon Lin
Jon Lin

Reputation: 143966

Try:

<IfModule mod_rewrite.c>
  RewriteEngine on

  # If a request for a php file is made, check that it's actually a php file then redirect the browser
  RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*?)\.php($|\ )
  RewriteCond %{REQUEST_FILENAME} -f
  RewriteRule ^(.*?)\.php$ /$1.html [L,R=301]

  # If a request for an html file is made, check that it's a php file, and if so, serve the php file:
  RewriteCond %{REQUEST_URI} ^/(.*?)\.html$
  RewriteCond %{DOCUMENT_ROOT}/%1.php -f
  RewriteRule ^ /%1.php [L]

  # Everything else goes to the controller
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ mycontroller.php [L,QSA]
</IfModule>

Upvotes: 1

Oussama Jilal
Oussama Jilal

Reputation: 7739

Try this (I have added a rewrite condition to avoid an infinite loop b yadding the parameter r=0 and testing if it exists) :

  RewriteEngine on

  RewriteCond %{QUERY_STRING} ^(.*&)?r=0(&.*)?$
  RewriteRule ^(.*)\.php$ $1.html [L,R=301,QSA]

  RewriteCond %{REQUEST_FILENAME} ^(.*)\.html$
  RewriteCond %1.php -f
  RewriteRule ^(.*)\.html$ $1.php?r=0 [L,QSA]

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ mycontroller.php [L,QSA]

Upvotes: 0

Related Questions