rewrite rule for single or multiple folders - php

My htaccess code for URL rewrite:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^compare/(.*)/?$ compare.php?page=$1 [L,QSA]
RewriteRule ^compare/(.*)/(.*)?$ compare.php?page=$1&location=$2 [L,QSA]
This rule works for :
www.example.com/compare/car
But it is not working for:
www.example.com/compare/car/india
I want to modify the rewrite rule which works for these urls:
www.example.com/compare/car
www.example.com/compare/car/india
Is it possible? How can I modify my rewrite rule to achieve this?

There are 2 problems with your code:
.* in first rule is too greedy which matches a / so first rule is also matching /compare/car/india as well as /compare/car
Since your URI is starting with /compare and rule is rewriting to compare.php you need to turn off content negotiation by turning off MultiViews.
Your last rule is without any RewriteCond as that is only applicable to next immediate RewriteRule directive.
You may use this code in your site root .htaccess:
Options -MultiViews
RewriteEngine On
RewriteBase /
# skip all files and directories from rewrite
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# one path element after compare
RewriteRule ^compare/([^/]+)/?$ compare.php?page=$1 [L,QSA,NC]
# two path elements after compare
RewriteRule ^compare/([^/]+)/([^/]+)/?$ compare.php?page=$1&location=$2 [L,QSA,NC]

Related

how do I get rewrite rules working from the apache .htaccess while CSS and javascript files are not rewritten?

Been through other suggested questions but no luck.
These is my .htaccess rewrite rules, mainly being done for SEO and user-friendliness purposes:
Options +SymLinksIfOwnerMatch
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/(images|css|js|scripts/.*)$
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !\.(?:css|js|jpe?g|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^dictionary/(.*) dictionary.php [NC,L]
RewriteRule . /index.php [L]
RewriteRule ^dict/[^/]+/[^/]+/(.+)$ $1 [L]
</IfModule>
If I uncomment the rewrite rule so any requests to www.xyz.com/dictionary and internally rewritten to www.xyz.com/dictionary.php, with any query string added to it, the entire site stops working.
What I would like is that any request to the folders JS, CSS, images and scripts is not rewritten (so I do not get /dictionary.images/xyz.jpg) and php files included in dictionary.php are not rewritten.
Any request to a anexisting directory is not touched, but if a directory that doesn't exist is rewritten to /index.php
How can I get the rewrite 'fake' directories rewritten please? I have about 5 more fake directories that I'd like to re-write, and the CSS, JavaScript and images are loaded from he correct paths?
Rewrite conditions only apply to the very next rule. When you insert the "dictionary" rule inbetween the index.php rule and its rewrite conditions above it, they stop applying to that rule and break your site. You need to add your new rule in some other place.
I would suggest adding new lines to emphasize which conditions go with which rules.
Your dict and dictionary rules need to go near the top so that those paths don't get handled by your front controller (index.php)
Try:
Options +SymLinksIfOwnerMatch
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^dict/[^/]+/[^/]+/(.+)$ $1 [L]
RewriteRule ^dictionary/(.*) dictionary.php [NC,L]
RewriteCond %{REQUEST_URI} !^/(images|css|js|scripts/.*)$
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !\.(?:css|js|jpe?g|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

rewrite all the requests to default.php except the request for sitemap.xml

I am using htaccess to rewrite every request to default.php file.
Options -Indexes
RewriteEngine On
RewriteRule ^ blog/default.php
But I want to submit sitemap file of my website(sitemap.xml).So that request to http://example.com/sitemap.xml rewrites to -> blog/sitemap.xml.
My unsuccessful try->
Options -Indexes
RewriteEngine On
RewriteRule ^sitemap.xml blog/sitemap.xml
RewriteRule ^ blog/default.php
My htaccess rules are obviously not hardened. But I am new to this.Please help.
I think you can use RewriteBase to reduce path to the blog directory. Try something like:
RewriteEngine On # enable rewrite engine
RewriteBase /blog/ # Set path "./blog" as a root
RewriteCond %{REQUEST_FILENAME} !-f # Excludes existed files from rewrite
RewriteCond $1 !^(default\.php|sitemap\.xml) # Setup $1 variable
RewriteRule ^(.*)$ default.php/$1 [L] # Process request params to default.php
The rules are fine so far, although I guess, you get a rewrite loop. To avoid the loop, you can prefix the rules with a rewrite condition, which skips the rule when the requesst is for a real file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^sitemap.xml$ /blog/sitemap.xml [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /blog/default.php [L]

HTAccess ReWrite Rules Conflicting?

I have two re-write rules one as a vanity url so for example domain.com/url and one to edit some a data aka post.
For some reason only the first rule is taking place and not both
Why is that and how can I fix it??
Here's The Code
RewriteEngine On
# Make sure you only match on files/directories that don't actually exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteBase /
# Rewrite the first part after the `/` into a `username` parameter
RewriteRule ^(.+)$ groups/index.php?gname=$1 [L,QSA]
RewriteRule ^edit/id/([0-9]+)/?$ groups/view_update.php?pid=$1 [NC,QSA,L]
RewriteCond is only applicable to very next RewriteRule not to all the RewriteRule. Also change order of your rules.
Change your code to this:
RewriteEngine On
# Make sure you only match on files/directories that don't actually exist
RewriteBase /
# Rewrite the first part after the `/` into a `username` parameter
# skip all rewrite rules for file or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^edit/id/([0-9]+)/?$ groups/view_update.php?pid=$1 [NC,QSA,L]
RewriteRule ^(.+)$ groups/index.php?gname=$1 [L,QSA]

mod_rewrite to make clean URL with multiple patterns

I'm trying to make clean URLs for my application. So I wrote the codes below in a .htaccess file.
RewriteEngine On
Options +FollowSymLinks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)/?$ index.php?p=$1&id=$2 [NC,L]
RewriteRule ^(.*)/?$ index.php?p=$1 [NC,L]
As you can see, I may have at most 2 variable in query string; p and id. If I have just one rule (the rule with 1 variable) in .htaccess file, everything will be fine. But when I add the first rule (the rule with 2 variable), it seems that all css, js, and image files will be go away.
I wrote css, images, and js files in this way :
./directory_name/file_name
Please help me to make clean URLs with multiple rules.
If you're following a Front-Controller Pattern, (i.e. everything goes through index.php) I'd encourage you to use FallbackResource.
FallbackResource /index.php
It's more concise and performant than the mod_rewrite equivalent (as seen in anubhava's answer):
Change your code to:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?p=$1&id=$2 [QSA,L]
RewriteRule ^([^/]+)/?$ /index.php?p=$1 [QSA,L]

How do I resolve the conflict of rules in this .htaccess file?

Each of the rules in the file works well if I comment out the other, but the two of them together do not achieve either purpose but rather renders the site ugly. Any suggestion on how to resolve this? Thanks.
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# If the request is for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
# If the request is for a valid link
RewriteCond %{REQUEST_FILENAME} !-l
# do not do anything
RewriteRule ^ - [L]
# forward /blog/foo to blog.php/foo
RewriteRule ^blog/(.+)$ blog.php/$1 [L,NC]
# forward /john to user_page/profile.php?name=john
RewriteRule ^((?!blog/).+)$ user_page/profile.php?uid=$1 [L,QSA,NC]
Try replace RewriteRule ^((?!blog/).+)$ with RewriteRule ^(.+)$ there is no need to check for blog string again
I've finally figured this out. I modified the second rewrite condition because the second rewrite rule redirects to a url that is not necessary valid i.e www.example.com/username to the intended valid url which looks like this www.example.com/user_page/profile.php?user=username.
I also modified the last/second rewrite rule as Safarov suggested and it worked! Below is the full .htaccess file.
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# If the request is for a valid directory
RewriteCond %{REQUEST_FILENAME} -d [OR]
# OR If the request is for a valid file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# OR If the request is for a valid link
RewriteCond %{REQUEST_FILENAME} -l
# do not do anything
RewriteRule ^ - [L]
# forward /blog/foo to blog.php/foo
RewriteRule ^blog/(.+)$ blog.php/$1 [L,NC]
# forward /john to user_page/profile.php?name=john
RewriteRule ^(.+)$ user_page/profile.php?uid=$1 [L,QSA]

Categories