I am trying to build an online store using dynamic php pages. Currently, .htaccess works with the following:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^online_store/category/(.*)$ category?uri=$1 [QSA,L]
RewriteRule ^(.*)$ index.php?action=$1 [QSA,L]
My index.php is just built with a bunch of includes, so a flat link to browse a category would be:
domain.com/online_store/category/apparel
Index.php is including online_store.htm, which processes the URI properly.
What I'm trying to accomplish next is to add a rule for product URIs, which would tell index.php to include product.htm to process the given URI:
domain.com/online_store/category/apparel/t-shirt1
I thought it would be as easy as adding:
RewriteRule ^online_store/category/(.*)/(.*)$ product?uri=$2 [QSA,L]
But it doesn't work. Even my uneducated mind tells me that the previous rewrite rule for categories preempts this one since L is included - but when I remove it neither work. Can someone educate me on the proper way to process this? Logically, I need this to happen:
domain.com/online_store/category/(URI1)/(URI2)
rewrite domain.com/category?uri=(URI1)
rewrite domain.com/product?uri=(URI2)
Final Edit - I decided to scrap the idea of nesting the product within the respective category, turns out I had issues with the way I was getting the URI using my php script. Here's the .htaccess that is working for me:
RewriteRule ^online_store/category/([^/]+)$ /category?uri=$1 [QSA,L]
RewriteRule ^online_store/product/([^/]+)$ /product?uri=$1 [QSA,L]
You should do:
RewriteRule ^online_store/category/[^/]+/(.*)$ category?uri=$1 [QSA,L]
it has to do with greedy repetition. Basically, the dot matches any character, including the slash(/)
Related
I made a php mvc for a school project, and I've never used htaccess before but I want to make my URLs look pretty...
Right now the URL's are /?controller=posts&action=index but I would like to have them show as posts/index which is Controller/Action.. I also have a folder called "assets" with has my css files and images.
Is this possible to do without breaking my assets folder and site?
Thanks :)
EDIT:
I tried the following code but if I go to /posts/index it shows the homepage & if I go to /?controller=posts&action=index it doesn't change the name or anything
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)$ /?controller=$1&action=$2 [L]
You need 2 rules to accomplish the entire requirements and use conditions to ignore real files and directories.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteCond %{THE_REQUEST} ^GET\ /\?controller=([^\s&]+)&action=([^\s&]+)
RewriteRule ^ /%1/%2? [R=302,L]
RewriteRule ^([^/]+)/([^/]+)/?$ /?controller=$1&action=$2 [L,QSA]
This will also most likely cause css to not load so you also need this in the head section of your html.
<base href="http://www.yoursite.com" />
We have added a paging system inside our layout. When we go to /page/clan, the page about our clan gets displayed. (as its located in pages/clan.php).
To get /page, we used a htaccess script, which rewrites index.php?page=pagename into the /page/pagename I mentioned.
This is our current htaccess code for converting these urls:
RewriteEngine On
RewriteRule ^page/([^/]*)$ index.php?page=$1 [L]
However, We'd like to remove the /page part, so it's possible to just use /clan instead of /page/clan to open the clan page.
How can this be done and with what code?
Thanks!
Try :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)/?$ index.php?page=$1 [L,NC]
Rewrite condions make sure you don't rewrite any existing files or directories on the server.
[NC] flag makes the pattern case insensitive, so in you case example.com/fOo would also work.
I have a site I'm trying to develop and I am having some (probably noob) problems getting my reWrite rules to work correctly.
Basically, I'm using the codeIgniter framework to develop the site and as part of this I have created a RewriteRule to remove the index.php part of the URL with the exception of some folders for images etc.
RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|shop)
RewriteRule ^(.*)$ /TESTSite/index.php/$1 [L]
The site originally has a current page of page/facilities/our-shop which was a very basic page with a few links to paypal to make a very rough shop page as we needed one quickly. However now I have implemented a different (read OpenCart) shop section to make this a bit more professional and allow more features etc. I have placed the openCart in a subdirectory called shop. The shop continues to work correctly as I've excluded the /shop from my original reWrite rule.
However - My problem...
I want the old page page/facilities/our-shop to redirect to the /shop and therefore work as if I navigated directly there..
I have tried the following:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|shop)
RewriteRule ^page/facilities\/our-shop$ /TESTSite/shop/$1 [R,NC,L]
RewriteRule ^(.*)$ /TESTSite/index.php/$1 [L]
And
RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|shop)
RewriteRule ^page/facilities\/our-shop$ /TESTSite/shop/$1 [N]
RewriteRule ^(.*)$ /TESTSite/index.php/$1 [L]
And with a few other variations, but every time I can't get it to work. Can anyone advise please?
Thanks
I think you can try the following rules:
RewriteEngine on
RewriteRule TESTSite/page/facilities/our-shop$ /TESTSite/shop/$1 [R=301]
RewriteCond %{REQUEST_URI} !^(index\.php|images|css|js|robots\.txt|shop)
RewriteRule ^TESTSite/page/(.*)$ /TESTSite/index.php/$1 [L]
Two things:
When you use RewriteCond, it only applies to the following rule. So I re-ordered the two lines.
You do not need \ before a / in a rule.
Check this tool to debug your rules.
I'd like to know if it is possible to add a rule to the htaccess of my ZF app to redirect all the URLs that ends with the segment /index/ (such as http://domain.ext/index/) to the same URL without the /index/ suffix.
I've tried with this simple rule:
RedirectMatch ^(.*)/(index(/)?)$ http://localhost$1
but it doesn't work as expected (with other frameworks such as FuelPHP it works like a charm).
I know that this can be done via PHP using a plugin but I'd like to make the redirect via Apache to improve the performance of the application.
I don't know why nobody jumped in here, it is not that complicated?
A config file is executed from top to bottom and certain rules cause an immediate exit. If the rule defines an external redirect the server will perform that redirect immediately and all following rules are therefore ignored. If the redirect is back to the same server and config file then it is just a new game with the rules! If the redirect rule does not apply anymore it is on to the next rule. If the rule would still apply you get a loop.
Similar thing with a RewriteRule that matches and has [L]. L means "Stop the rewriting process here and don't apply any more rewrite rules". This quote is straight from the manual
Now you simply have to define some logic in what order you want to apply certain rules. Your request about the RedirectMatch for any /index/ path is certainly something you want to have very early to the top of the config. If there is a match your config will end here and perform a redirect! The browser will send a new request and we have a new game.
The RewriteRule to an index.php is something we will add very late at the bottom. It may be our last resort like a if all fails then rule. I does not matter if this is the Zend Framework or any other application you funnel through an index.php or other script for that matter.
The following rules should cover any variation with index, including .php, .htm and .html and finally trigger the index.php file for your ZF application.
RedirectMatch ^(/.*)/(index.(php|html|htm)|index)/?$ $1
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
When testing redirect rules be careful with your browser and use one where you can totally reset all cache and history settings. All current browsers are notorious in "remembering" redirects. If they learned a redirect rule they will perform that redirect internal, i.e. they don't go to the server to see what's new!
Here is your ruleset laid out readably
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RedirectMatch ^(.*)/(index(/)?)$ http://localhost$1
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
RedirectMatch is a mod_alias directive which severs the conds as from their rule. Also it's a lot less fraught not mixing mod_alias and mod_rewrite directives, so try:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(.*?)/index/?$ $1 [R=301,L]
RewriteRule ^.*$ index.php [NC,L]
(updated following posters comments)
More footnotes
I tried this out on my VM which mirrors my hosting service, but having root access I can see the 'production' rewrite logs. This fails because the second rules still falls through to rule (3) which dispatchs to index.php. This then returms the full content but with a 301 status and without issuing a new location. If I change the [R=301] to [R=301,L] then it works fine as the server now issues a 301 with a Location header and the browser now retries with the new location.
The documentation states:
You will almost always want to use [R] in conjunction with [L] (that is, use [R,L]) because on its own, the [R] flag prepends http://thishost[:thisport] to the URI, but then passes this on to the next rule in the ruleset, which can often result in 'Invalid URI in request' warnings.
I resolved my problem with this (horrible) workaround:
- I renamed the "index" action of IndexController to "home"
- I setup a static route for home page (source)
- I changed the htaccess to:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*)home(/)?$ $1 [R=301,L]
RewriteRule ^(.*)index/(.*)$ $1$2 [R=301,L]
RewriteRule ^.*$ index.php [QSA,NC,L]
So now the home page is not duplicated because http://localhost/home/ is redirected to the base domain and for other controllers the index action, if it is called specifying the action name (/controller/index/param/value) is redirected to the desired URL (/controller/param/value/)
RewriteRule ^(.*)/index(?|$)$ $1$2 [R=301,L]
this works with urls
/index => /
/index?page=2 => /?page2
/index/index => /
/index/index?page=2 /?page2
you need remove trailing slash before, for url like /index/, index/index/
RewriteRule ^(.*)/$ /$1 [L,R=301]
url like /index/help will work without changes
I need help configuring my .htaccess file to handle redirects properly.
Here’s what I need to have happen. Stackoverflow's spam filter wouldn't allow me to post the full domain. So where I say "DOMAIN" you can substitue "domain.com". (I also needed to add and extra t to the http.)
Requests for the DOMAIN/page version of the file should be redirected to www.DOMAIN/page.
Requests for the 'friendly' versions of the URLS should be allowed. So a file that is really at www.DOMAIN/index.php?q=37 should be viewable by going to www.DOMAIN/latest-news
I have a big list of 301 redirects. We recently changed the site from an .asp based CMS to one written in PHP.
Example:
redirect 301 /overview.asp http://www.DOMAIN/overview
Items 1 and 2 are working fine.
However for item 3, if I put in a browser request for "http://www.DOMAIN/overview.asp" instead of redirecting to the friendly name of the file ("http://www.DOMAIN/overview") it will redirect to http://www.DOMAIN/index.php?q=overview.asp. This is the problem.
What do I need to change to get this working right?
My configuration is below:
## Fix Apache internal dummy connections from breaking [(site_url)] cache
RewriteCond %{HTTP_USER_AGENT} ^.*internal\ dummy\ connection.*$ [NC]
RewriteRule .* - [F,L]
## Exclude /assets and /manager directories and images from rewrite rules
RewriteRule ^(manager|assets)/*$ - [L]
RewriteRule \.(jpg|jpeg|png|gif|ico)$ - [L]
## For Friendly URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.DOMAIN/$1 [R=301,L]
redirect 301 /overview.asp http://www.DOMAIN/overview
redirect 301 /news.asp http://www.DOMAIN/news
# ETC....
thanks!
Mod_rewrite is doing exactly what you're asking it to do ... (yes :-), that's often the problem with computers).
On the /overview.asp http://www.DOMAIN/overview line you're setting the browser to send out a brand new request from scratch, which starts the whole cycle again from the top and gets catched by the ^(.*)$ index.php?q=$1 directive.
Right before this line you should put another RewriteCond to prevent the ^(.*)$ rule to apply if REQUEST_FILENAME is either overview or news. You might also simply rewrite /overview.asp to overview [L] instead of redirecting.
If you can, set the RewriteLog directive to its highest verbosity and look at the logfile - it usually gives very good insights into what's really going on...
EDIT - if I get it right you shoud be doing this:
RewriteCond %{REQUEST_FILENAME} ! \.asp$
RewriteCond %{REQUEST_FILENAME} ! ^overview$
RewriteCond %{REQUEST_FILENAME} ! ^news$
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
This would prevent any file already ending in .asp, plus those looking for overview and news, to be redirected toward index.php.
I suspect anyway that you got something backwards regarding that SEO stuff. You should indeed start from the structure of the query string that your scripts expect and use that as a base to build a sensible URL addressing schema.
EDIT #2:
There was a space too many between the bang mark ant the regex. The following code doesn't come from memory as the previous - I've tested on my local Apache and it does what's supposed to do (as long as I've understood correctly..)
RewriteCond %{REQUEST_FILENAME} !\.asp$
RewriteCond %{REQUEST_FILENAME} !overview$
RewriteCond %{REQUEST_FILENAME} !news$
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
Hope this helps