htaccess with multiple levels - .htaccess

I saw htaccess guides here but i think im doing it wrong. Here's my sample code.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ page.php?p=$1&c=$2&gc=$3
The issue i am facing here is, there are 3 levels of page that have links to each level. I usually get "Not Found" if i am going to the first parameter, even the 2nd parameter. It shows correct only the 3rd parameter.
What i would like to know here is, how can i configure my htaccess to get the certain page without having the link ended-up to "Not Found".

Your rule only matches if the path contains 3 parts. You need to create 2 more rules for the case where the path contains 2 parts and where the path contains 1 part:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/$ page.php?p=$1&c=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ page.php?p=$1 [L]
I also advice to use the [L] flag on the rule you already have. This will speed up things a little bit and might also prevent weird behaviour, especially when you are using redirects.

Related

Rewrite rules conflicting with existent files

I came across some htaccess url rewrite rules which are conflicting to existing url.
To write my category pages to www.mydomain.com/categoryname.html
I'm using following rule which is working fine but all my other pages like www.mydomain.com/about.html shows 404 not found
RewriteRule ^([^/]*)\.html$ /category_parent.php?ctg=$1 [L]
To write my product pages like www.mydomain.com/25/productname.html
I'm using following code which is also working fine
RewriteRule ^([^/]*)/([^/]*)\.html$ /product.php?id=$1&url=$2 [L]
but the above rewrite rule conflicting with sub category pages for which I'm using following code:
RewriteRule ^([^/]*)/([^/]*)\.html$ /category_child.php?pctg=$1&ctg=$2 [L]
In brief, I want to write to,
www.mydomain.com/categoryname.html
www.mydomain.com/categoryname/subcategoryname.html
www.mydomain.com/25/productname.html
But Some rules messing with each other. I'll appreciate if you can provide me little clue on this.
If your files are colliding the non-existent to existent ones, you should use a condition to verify if a file, directory or symbolic link exists.
For files:
RewriteCond %{REQUEST_FILENAME} !-f
For folders:
RewriteCond %{REQUEST_FILENAME} !-d
For symbolic links:
RewriteCond %{REQUEST_FILENAME} !-l
The exclamation mark ! is used to negate their meaning !-f means if the file does not exist then apply rule if it exists then do not apply rule.
Keep in mind that a RewriteCond should be followed by a RewriteRule and you can have one or more conditions per RewriteRule, for example:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([^/]*)\.html$ /category_parent.php?ctg=$1 [L]
In this case it means if directory does not exist and file does not exist and symbolic link does not exist then we redirect but if any of the previous condition exist then we don't redirect.

Multiple rewrite conditions for multiple parameters

There is an issue with the htaccess rewrite conditions in my setup.
Currently I have the following code.
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://mydom.com/$1.php
This works fine for any base page making them look like this.
http://mydom.com/page
What I want to also be able to do is add parameters from the url if they exist. I have some pages that will be like this.
http://mydom.com/page?param=1&secondParam=2
What I've tried to do is add this.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)/(.*)$ http://mydom/$1/$2/$3 [L]
RewriteRule ^(.*)/(.*)$ http://mydom/$1/$2 [L]
This made sense to me, because I thought if the condition didn't match, it would move on, but this gave me an internal server error.
What I ended up doing was setting up a separate rule for each page that could have multiple parameters like this.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^page/(.)/(.)$ http://mydom.com/page.php?param=$1&secondParam=$2 [L]
RewriteRule ^page/(.*)$ http://mydom.com/page.php?param=$1 [L]
RewriteRule ^(.*)$ http://mydom.com/$1.php
This works, however you need to keep in mind relative links you may have in your site such as style sheets and javascript files. In my case, I had to replace all relative paths with full site paths, depending on the way you set up your site, it could take a while to replace.

Rewrite URL with .htaccess for multiple parameters

This question might be a duplicate. But I did not find any solution worked for me.
I want to rewrite URL, where I have one and two level parameters. first parameter is p and second is sp
www.domain.com/home should point to www.domain.com/index.php?p=home
and
www.domain.com/projects/99 should point to www.domain.com/index.php?p=projects&sp=99
How do I do in .htaccess?
Currently My htaccess is as followes,
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?p=$1
RewriteRule ^([^/]*)/([^/]*)\$ index.php?p=$1&sp=$2 [L]
The problem with this htaccess is that it correctly points one level url. ie., www.domain.com/home. But not the two level url. ie. www.domain.com/projects/99
You have to treat the rules separately. All Conditions preceding rules only apply to a single, immediately following rule. You tried to 'chain' two rules. The second rule never could have matched, since the first one was a catch-all that changed the syntax. Apart from that you have to make sure that the first rule does not catch unwanted requests. Also think about whether you want to use the * or the + operator in the patterns. I suggest you use the + operator, so that you have a clear error message when empty values are requested for a 'page' or a 'subpage'.
So this might come closer to what you are looking for:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?p=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ index.php?p=$1&sp=$2 [L]

htaccess does not work rewrite rule

I've been struggling with my .htaccess file for weeks now, I changed it many times but it just won't work.
I have this in my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^/([^./]+)\.html$ category.php?id=$1
RewriteRule ^/([^./]+)\.html$ tag.php?id=$1
RewriteRule ^/([^./]+)\.html$ play.php?id=$1
but it does not work.
Are you sure that mod_rewrite is turned on in Apache? Do you have access to httpd.conf? It would be better to do redirects there instead of with a .htaccess file.
Your conditions are only being applied to the first rule. Each set of RewriteCond's only get applied to the immediately following RewriteRule. So the conditions only get applied to RewriteRule ^/([^./]+)\.html$ category.php?id=$1 and the last 2 rules have no conditions at all.
Your conditions is to rewrite something that exists to something else, which will cause a rewrite loop. You probably wanted:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Your 2nd and 3rd rules will never be applied because if someone requests /some-page.html the first rule's regex will match it and rewrite the URI to /category.php?id=some-page, then the next to rules will never match because the first rule already rewrote the URI to category.php.
Your regular expressions match a leading slash, URI's being applied in rewrite rules that are inside an htaccess file has the leading slash stripped out, so you want this instead:
RewriteRule ^([^./]+)\.html$ category.php?id=$1
1, 2 and 4 is easy. 3, not so much. You're going to have to figure out a unique way to represent an html page as a category, tag, or play. You can't have all 3 look identical, there's no way to tell which one you want. Take:
/something.html
Is that supposed to be a category? A tag? or a Play? Who knows, your rewrite rules surely don't. But if you preface each with a keyword, then you can differentiate:
/category/something.html
/tag/something.html
/play/something.html
And your rules would look like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^./]+)\.html$ category.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^tag/([^./]+)\.html$ tag.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^play/([^./]+)\.html$ play.php?id=$1

RewriteRule to redirect tp a page for a second subfolder variable

FTR, I'm pretty abysmal at rewrite rules.
We've got a number of users who each have their own projects. Right now we've got the RewriteRules set up so that when someone just types mysite.com/username it goes to the user's profile at, f.e., mysite.com/work/user_name.php?u=000
But what we really need is, when someone types in mysite.com/username/project1 it goes to that project. (we don't have to do anything with the user, really. We just need to find the project. But the username needs to be in there for seo/sanity purposes) I've tried to accomplish this for two days now and I can't seem to get anything but 500 errors no matter what I do, and I'm simply not talented enough to figure it out.
I originally tried to redirect to the user page with a second variable ($2) and if that var was there, do a php header to the appropriate page, but that didn't seem to work and it's still showing the URL as mysite.com/work/project_page?i=999 or whatever, and that's no good either.
Here's the code Ive got for redirecting to the user
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /work/user_page.php?n=$1 [L,QSA]
But I can't seem to figure out how to tell it that if there's 2 vars, (i.e. user/project) then redirect to work/project_page.php?n=$2...
You need to use a more specific pattern like [^/]+ (one or more arbitrary characters except /) instead of .* (an arbitrary number of any character). This enables you to distinguish between one or more path segments:
# one path segment
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /work/user_page.php?n=$1 [L,QSA]
# two path segments
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ /work/user_page.php?n=$1&project=$2 [L,QSA]

Resources