Dynamic Rewritten URL's allow multiple params if exist - .htaccess

We have built a search module for our eCommerce application & attempting to build SEO friendly pages.
The basic concept below works however when adding additional params to our search the rules no longer work correctly.
RewriteRule ^shop/([^/]*)/([^/]*)/([^/]*)/search/([^/]*)$ search.php?controller=$1&lang=$2&name=$3&search_keyword=$4 [L]
Example of search but needs to also work with categories selection when parameter exists.
www.mysite.com/shop/lcd
Currently this is working but only supports 2 category sets as we have 2 rules and not working with the search, the problem is there could be as many as 20 category sets
RewriteRule ^shop/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)$ search.php?controller=$1&lang=$2&name=$3&categories=$4=$5 [L]
RewriteRule ^shop/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)/([^/]*)$ search.php?controller=$1&lang=$2&name=$3&categories=$4=$5|$6=$7 [L]
www.mysite.com/shop/TV/Plasma+3D+Portable/ (TV is the main category with 3 subs)
www.mysite.com/shop/TV/Plasma+3D+Portable/Computers/Mac+PC+Laptops+Tablets/
(Computers is the main category with 4 subs combined with the above)
This needs to also work with additional param sets
www.mysite.com/shop/TV/Plasma+3D+Portable/Computers/Mac+PC+Laptops+Tablets/manufacturers/brandA/brandB/brandC/
Please if someone can suggest a better way to write these rules to support all these additional parameter requests we would really appreciate your input.

This post helped us to solve our problem
.htaccess: GET variables are lost in rewrite
The solution is very simple in our case the controller lang & name our separated from the search parameters then params=/$4 captures the rest the URL which we can now explode & parse via PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^shop/([^/]*)/([^/]*)/([^/]*)$ /search.php?controller=$1&lang=$2&name=$3 [QSA,L]
RewriteRule ^shop/([^/]*)/([^/]*)/([^/]*)/(.*)$ /search.php?controller=$1&lang=$2&name=$3&params=/$4 [QSA,L]

Related

htaccess rewrite url query string with index as base

New poster to this place but long term user.
I have a site which uses index.php and then has a viewpost.php and categorypost.php.
The viewpost is for viewing the main posts and the categorypost is for viewing posts under a category such as "webdesign".
The view post slug is made up of query string such as:
viewpost.php?postType=services&postCategory=webdesign&postTitle=somepost
I then want that to rewrite to
website/services/webdesign/somepost
First question:
Is this the correct way to do this by using 3 files or am I creating more work than needed?
Second question:
If I'm on the correct or at least an ok path, how do I go about redirecting?
I have seen about 30 or so posts around this but finding it hard to get my head around it and have ended up with 500 response or just straight redirecting.
RewriteRule ^(.*)$ viewpost.php?postTag=$1&postCategory=$2&postTitle=$3 [QSA,L]
Any help is greatly appreciated.
If these particular links can all start with the same word, it is the simplest, in this case "website". Because it avoids mistakenly using an existing folder with a missing page.
RewriteRule ^website/([^/]+)/([^/]+)/([^/]+)/?$ viewpost.php?postTag=$1&postCategory=$2&postTitle=$3 [NC,QSA,L]
But if it's not the case, you can use:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ viewpost.php?postTag=$1&postCategory=$2&postTitle=$3 [QSA,L]

What is the proper way to make your url "nicer"?

recently i have tried to build some MVC application without any framework to understand MVC pattern better. Till now i have resolved every problem i have had BUT....
Pretty common thing is to make your URL looks "nicer"
For example www.somesite.com/controller/method
instead of www.somesite.com/index.php?c=1&m=2.
i achieved this simply with htacces by aiming it to a variable.
in htaccess...RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
This works perfectly fine until someone tries to rewrite variable "url".
Basically if someone types www.somesite.com/controller/method?url=1
my Application will pop up an error page because i am parsing everything after / and calling specific controllers and methods by its name (or popping up an error page if that doesnt exists).
So i would like to know if there is a better way to do this or way to avoid this behaviourThanks :)
EDIT
In last few hours i tried to find a better solutions. I thought i could put my url into Enviromental variable instead of into get variable.
So i experimented with commands like
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php [E=URL:$1,QSA]
unfortunately $_SERVER["URL"] is blank......
i would be really happy if someone could help me with this piece of code :) Thanks
EDIT 2
Okay to make it clear i'll add few examples.
My current htacces looks like this
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php?url=$1 [QSA]
So if someone goes to www.somesite.com/foo/bar
i will check $_GET["url"] and then explode it explode("/", filter_var(rtrim($_GET["url"], "/"), FILTER_SANITIZE_URL))
Now i have array which looks like [0=>foo 1=>bar]
That means in my code that i will try to call controller called foo and then method in this class called bar
In case that the user will try to acces www.somesite.com/foo/bar/fee/faa, fee and faa will pass as a parameters to method bar in class foo.
So this was just example how does this work. My problem is as i said when someone tries to acces lets say www.somesite.com/foo?url=0. Then my script will try to handle $_GET["url"] and the result wont be foo but 0 because of ?url=0 rewrites the value of url which was originaly set in my .htacces. So my scripts will try to call controller called 0 and if that doesnt exists itt will popup error404. I have already tried to ignore this specific variable via QUERY_STRING in htacces but this seems to me like a stupid solution. For now i would like to stick with setting evniromental variable instead of get variable or if there is some better way to achieve this :) Thanks
Your current set-up relies on $_GET to obtain core information but, as you've faced, that variable is populated from user input so anyone can mess with your routing, even inadvertently.
A typical Apache configuration for a custom router looks like this (this snippet is from CakePHP/2.x):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
As you can see is doesn't add GET variables of its own, it merely lets existing ones to pass through. Original URL is right there inside $_SERVER, you don't need to instruct Apache to copy it into the redirected URL.
I understand you want $_SERVER['REQUEST_URI'] but you can peek inside the array with the usual methods: print_r($_SERVER), var_dump($_SERVER), phpinfo()...

.htaccess cascading conditions

I'm trying to figure out how to manage potentially conflicting conditions in .htaccess
My setup is the following:
- I have a CMS running on a server that can be accessed through myCMSdomain.com where myCMSdomain.com would be CMS home page and myCMSdomain.com/admin would be the admin interface.
- Sites using this CMS should be pointing to myCMSdomain.com/sites/index.php
- Images for all sites are available somewhere behind myCMSdomain.com/admin/images/sitename/...
So here is how I tried to tackle this problem:
RewriteCond %{HTTP_HOST} !^(www.)?myCMSdomain.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . sites/index.php
With this, all incoming requests coming from other domain names are treated correctly by the index.php file but as images are hosted somewhere else, I'd like to use a rule saying that images should be fetched somewhere else like this:
Visible url format for images is: images-[sitename]/[image_path]
Real location of the images is: admin/site/[sitename]/[image_path]
The following rule works but not in combination with the first rule
RewriteRule images-([a-zA-Z0-9]+)/(.*)$ admin/site/$1/images/$2
Images end up calling index.php instead of using the rule I defined for them.
I have tried to excluse the image directory from the conditions but it doesn't work either:
RewriteCond %{REQUEST_URI} !(images-([a-zA-Z0-9]+)/(.*))
I might have similar issues in the future with other exception so I was wondering if there was a way to handle this.
Thanks!
Laurent
UPDATE 1:
If I use the following rule on top of all other
it works only if I'm using myCMSdomain.com domain name
if I use any other domain like anotherdomain.com, the rule leads to a http 500
RewriteRule images-([a-zA-Z0-9]+)/(.*)$ manager/site/$1/images/$2
So http://www.myCMSdomain.com/images-test/test.jpg leads me to the correct image
But http://www.anotherdomain.com/images-test/test.jpg leads me to a 500 http error code while this domain is pointing correctly to sites/index.php
UPDATE 2:
On Justin's request, here is a view on the physical directory structure on the server
/admin/
/admin/site
/admin/site/site_name/
/admin/site/site_name/images/
/sites/
/sites/js
/sites/css
You can rearrange your conditions logic.
# if www.myCMSdomain.com or myCMSdomain.com -> do nothing
RewriteCond %{HTTP_HOST} ^(?:www\.)?myCMSdomain\.com$ [NC]
RewriteRule ^ - [L]
# if we reach here, this means it's a subdomain/another domain
# images rule
RewriteRule ^images-([^/]+)/(.+)$ /admin/site/$1/images/$2 [L]
# not a file/directory -> sites/index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /sites/index.php [L]
It is also possible the way you did but it would be longer to write.
Also, keep in mind that conditions (RewriteCond) are non-cumulative: they are for next rule (RewriteRule) only.
I've been struggling with this issue for some time now but at last I think I have found the issue. It looks like there was something wrong in the domain name configuration, I don't know exactly what but once I had re-saved the mapping of all domains, the htaccess worked the way it should.
In the end I have used Justin's proposition, it looks more future proof than mine.
Thanks for your help and happy new year to all
Laurent

Can I create a search engine friendly URL from this custom ColdFusion CMS URL?

I have inherited a custom ColdFusion CMS app. The URL's that it creates are horrendous. Not at all suitable for SEO or readability for that matter. An example of a URL in this CMS is:
http://www.mysite.com/Index2.cfm?a=000003,000010,000019,001335
Basically, each level of hierarchy is stored in the database based upon that long string of comma separated values. So in the case of the example I used, that particular page is 4 levels deep in the CMS hierarchy.
Basically what I would like to see is a format similar to this
http://www.mysite.com/level-1/level-2/level-3/level-4
Is this possible? Any help would be greatly appreciated. For what it's worth we are using ColdFusion 6 at present time, but will be upgrading to 8 in the near future.
First of all, are you willing to have the index.cfm in the URL? Like: http://www.mysite.com/index.cfm/level-1/level-2/level-3/level-4 ? If not, then you'll need to be doing a rewrite to remove the index.cfm, but still allow CF to process the page. Your .htaccess would look something like this:
RewriteEngine On
# If it's a real path, just serve it
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]
# Redirect if no trailing slash
RewriteRule ^(.+[^/])$ $1/ [R=301,L]
# Rewrite URL paths
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]
Next step, you'll need to "catch" the URLs and serve up the correct pages based on the SEO-friendly URLs. You can grab the incoming URL from the CGI.path_info variable. It's hard to know what your code should look like without knowing how it currently processes those URL variables, but essentially you'd have some kind of mapping function that grabbed the SEO-friendly names and substituted in the numbers to grab the content.
The third step is rewriting any URLs that are generated by your CMS to output the SEO-friendly URLs. Same mapping happens here, only in reverse.

htaccess - Rewrite rule and/or condition to fix totally different discontinued or incorrect incoming link

Well, I am stuck again. Two days of reading and again, found some close solutions but, nothing fits and all my experiments failed.
This is a continuation of my question:
here at stackoverflow
The 4 rules below take my incoming links:
http://somedomain.com/getme.pl?dothis=display&partnum=1234567
and beatifies it.
Also allows users to use the beatified version right in address bar:
http://somedomain.com/1234567
Here are my working rules:
RewriteRule ^([\s]*)$ /getme.pl [L] ## in case there is a space or nothing.
RewriteRule ^([0-9]*)$ /getme.pl?dothis=display&partnum=$1&rewrite [L]
RewriteCond %{QUERY_STRING} partnum=([0-9]*)$
RewriteRule (.*) /%1? [L,R=301]
Works great but, I discovered there are some old links to the site out there:
http://somedomain.com/oldversion.php?id=123456789
And
http://somedomain.com/oldversion.php?r=86this&id=123456789
I would like to just grab the id=[0-9] and integrate it with my working rules.
I suppose, the rule would be inserted between the second and third rules above.
I tried various attempts (about 100!) like:
RewriteRule ^(oldversion\.php)?([a-z]{1})=([a-z0-9]*)&([a-z]{2})=([0-9]*)$ /$4? [L]
RewriteRule ^(oldversion\.php)?([a-z]{2})=([0-9]*)$ /$3? [L]
As you see, two days of reading and nothing is sinking in for me.
I tried several variations of the working rules I already have as well, to no avail.
Can't I just get the 123456789 off of the outdated .php urls somehow and stick it in my existing rules?
Thanks for your help and explaining down to my level co, I just might be able to understand...
Put this at the end of your .htaccess file:
RewriteCond %{QUERY_STRING} id=([^&]+)(&|$) [NC]
RewriteRule ^oldversion\.php$ /%1? [L,R=301,NC,NE]
For a URI of /oldversion.php?r=86this&id=123456789 it will internally redirect to /123456789
Remember RewriteRule just matches your URI and it cannot match your QUERY_STRING.

Resources