Search code examples
php.htaccesshttp-redirectmod-rewriteurl-rewriting

htaccess - how to rewrite all sub pages to one directory except few pages - issue with css, js, image files also rewritten


I am creating a website that will show products

https://example.com/pencil should rewrite like https://example.com/item/index.php?id=pencil

But, I have some other pages like, about, contact ect, that should not rewrite to the sub directory

https://example.com/about -> https://example.com/about.php

here, I am testing it in local, so actual url will be like http://localhost/example.com/about or http://localhost/example.com/pencil So, I added the RewriteBase as /example.com/

RewriteEngine On
ErrorDocument 404 /example.com/404.php

<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteBase /example.com/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^home/ index.php [L,END]
RewriteRule ^home index.php [L,END]

RewriteRule ^about-us/ about.php [L,END]
RewriteRule ^about-us about.php [L,END]

RewriteRule ^contact-us/ contact.php [L,END]
RewriteRule ^contact-us contact.php [L,END]

RewriteRule ^(.*)/$ item/index.php?url=$1 [QSA,L]
RewriteRule ^(.*)$ item/index.php?url=$1 [QSA,L]


</IfModule>

With the above htaccess code, I am able to rewrite both the pages to respective php files. But, the css and js files are not loading.

I am beginner to htaccess. Any help would be much appriciated.


Solution

  • The problem is that the js and css file will be rewritten. RewriteCond only applies to the next RewriteRule so you need to add that to everything. So you should add them before every RewriteRule.

    # Add RewriteCond to avoid matching .css and .js files
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ item/index.php?url=$1 [QSA,L]
    
    # Add RewriteCond to avoid matching .css and .js files
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ item/index.php?url=$1 [QSA,L]
    
    </IfModule>
    

    Or alternatively add the following before the matching so css and js file will be matched earlier

    RewriteEngine On
    ErrorDocument 404 /example.com/404.php
    
    <IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
    RewriteBase /example.com/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    
    RewriteRule ^home/ index.php [L,END]
    RewriteRule ^home index.php [L,END]
    
    RewriteRule ^about-us/ about.php [L,END]
    RewriteRule ^about-us about.php [L,END]
    
    RewriteRule ^contact-us/ contact.php [L,END]
    RewriteRule ^contact-us contact.php [L,END]
    
    # match .css and .js file and add the END flag so no more rules will be applied.
    RewriteRule "^(.*)\.css$" - [END]
    RewriteRule "^(.*)\.js$" - [END]
    
    RewriteRule ^(.*)/$ item/index.php?url=$1 [QSA,L]
    RewriteRule ^(.*)$ item/index.php?url=$1 [QSA,L]
    
    
    </IfModule>
    

    Another solution would be to match all existing files and disable any further matching for those files.

    # Only match file that exists
    RewriteCond "%{REQUEST_FILENAME}" -f
    # Match any files (.*) that matches the RewriteCond. Don't apply changes (-) and apply the END flag.
    RewriteRule .* - [END]