<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5283829804020620688</id><updated>2011-11-27T15:27:19.327-08:00</updated><title type='text'>CakePHP Online Help</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-2695310042535712757</id><published>2008-12-04T10:09:00.000-08:00</published><updated>2008-12-04T10:13:19.917-08:00</updated><title type='text'>Captcha component with PhpCaptcha</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Spout (spout)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PhpCaptcha is a library for generating visual and audio CAPTCHAs (completely automated public Turing test to tell computers and humans apart).&lt;br /&gt;&lt;br /&gt;Supported Features&lt;br /&gt;&lt;br /&gt;    * Multiple random TrueType fonts&lt;br /&gt;    * Character rotation&lt;br /&gt;    * Optional chararacter shadow support&lt;br /&gt;    * Optional site owner display text&lt;br /&gt;    * Random custom background images&lt;br /&gt;    * Font size selection&lt;br /&gt;    * Greyscale or colour lines and characters&lt;br /&gt;    * Character set selection&lt;br /&gt;    * Integration of validation function for checking the user entered code with the generated code&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;NB: The audio CAPTCHA requires the Flite text to speech synthesis engine.&lt;br /&gt;&lt;br /&gt;1.- Download PhpCaptcha &lt;a href="http://www.ejeliot.com/pages/2" target="_blank"&gt;http://www.ejeliot.com/pages/2&lt;/a&gt; and unzip archive in /vendors/phpcaptcha directory&lt;br /&gt;2.- Download Vera font files: &lt;a href="http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.zip"  target="_blank"&gt;http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.zip&lt;/a&gt; and unzip archive in /vendors/phpcaptcha/fonts/&lt;br /&gt;3.- Create Captcha component:&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/captcha-component-with-phpcaptcha" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-2695310042535712757?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/2695310042535712757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=2695310042535712757' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2695310042535712757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2695310042535712757'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/captcha-component-with-phpcaptcha.html' title='Captcha component with PhpCaptcha'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-4344253085188466380</id><published>2008-12-04T10:03:00.000-08:00</published><updated>2008-12-04T10:06:01.571-08:00</updated><title type='text'>Integrate CakePHP with Kcaptcha</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Andrew Stephanoff (stephanoff)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Simple way to integrate CakePHP with Kcaptcha.&lt;br /&gt;&lt;br /&gt;KCAPTCHA is a free and open source PHP solution to generate human validation images (CAPTCHA).&lt;br /&gt;&lt;br /&gt;KCAPTCHA is meant to be a very strong protected one but requires no special hosting featires, only PHP with GD library.&lt;br /&gt;&lt;br /&gt;You can download Kcaptcha from here: &lt;a href="http://captcha.ru/en/kcaptcha/" target="_blank"&gt;http://captcha.ru/en/kcaptcha/&lt;/a&gt;. After this, put kcaptcha folder into vendors directory.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/integrate-cakephp-with-kcaptcha" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-4344253085188466380?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/4344253085188466380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=4344253085188466380' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4344253085188466380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4344253085188466380'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/integrate-cakephp-with-kcaptcha.html' title='Integrate CakePHP with Kcaptcha'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-6799848242924520156</id><published>2008-12-03T10:39:00.000-08:00</published><updated>2008-12-03T10:42:17.961-08:00</updated><title type='text'>PHPMailer with native API for PHP 5.x</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Heiner Gassen (kitten)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tutorial on using PHPMailer with Cake (&lt;a href="http://bakery.cakephp.org/articles/view/94" target="_blank"&gt;http://bakery.cakephp.org/articles/view/94&lt;/a&gt;) has a comment requesting a component that lets you use the native PHPMailer API. This is possible with PHP5's built-in overloading capabilities. &lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/phpmailer-with-native-api-for-php-5-x" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-6799848242924520156?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/6799848242924520156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=6799848242924520156' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6799848242924520156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6799848242924520156'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/phpmailer-with-native-api-for-php-5x.html' title='PHPMailer with native API for PHP 5.x'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-5572198557878260322</id><published>2008-12-03T10:35:00.000-08:00</published><updated>2008-12-03T10:37:48.795-08:00</updated><title type='text'>Setting up Eclipse to work with Cake</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Michael McAndrew (MilkyJoe)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; You’re on the quest for painless PHP development. You’re using Cake and considering the goodness of Eclipse. Two great first steps.&lt;br /&gt;&lt;br /&gt;All you need now is a little help getting to know Eclipse and configuring it for CakePHP. This tutorial gathers information already out there, adds a bit more, and puts in all in one place.&lt;br /&gt;This tutorial is based on a standard setup.&lt;br /&gt;&lt;br /&gt;    * A recent stable build of Eclipse PHP Development Tools (3.2.100)&lt;br /&gt;    * Standard CakePHP install (in C:\\xampp\\htdocs\\cake) 1.1 or 1.2&lt;br /&gt;    * Standard XAMPP install (in C:\\xampp)&lt;br /&gt;    * Windows XP.&lt;br /&gt;&lt;br /&gt;There is a lot more that could be covered. If you can fill the gaps or suggest how it could be improved, that would be great.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/setting-up-eclipse-to-work-with-cake" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-5572198557878260322?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/5572198557878260322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=5572198557878260322' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/5572198557878260322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/5572198557878260322'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/setting-up-eclipse-to-work-with-cake.html' title='Setting up Eclipse to work with Cake'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-7013726680771292854</id><published>2008-12-02T10:52:00.000-08:00</published><updated>2008-12-02T10:54:15.568-08:00</updated><title type='text'>jQuery Helper</title><content type='html'>By Marco Pegoraro (thepeg)&lt;br /&gt;&lt;br /&gt; I wrote an helper that allow you to enjoy jQuery library by helping in script inclusion and plugin management.&lt;br /&gt;I have only wrote an italian documentation yet but code il simply, comments are in english (bad english... but english!)&lt;br /&gt;&lt;br /&gt;Code download and documentation can be found at:&lt;br /&gt;&lt;a href="http://www.consulenza-web.com/cakephp-jquery-helper.dc-28.html" target="_blank"&gt;http://www.consulenza-web.com/cakephp-jquery-helper.dc-28.html&lt;/a&gt;&lt;br /&gt;I hope someone will give me an english translation!&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/jquery-helper" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-7013726680771292854?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/7013726680771292854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=7013726680771292854' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7013726680771292854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7013726680771292854'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/jquery-helper.html' title='jQuery Helper'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-2497083279311296731</id><published>2008-12-02T10:49:00.000-08:00</published><updated>2008-12-02T10:51:35.663-08:00</updated><title type='text'>Pagination</title><content type='html'>By Andy Dawson (AD7six)&lt;br /&gt;&lt;br /&gt; If you have more than a few results it is useful, if not vital, to provide a means of presenting the results a few at a time.&lt;br /&gt;This tutorial will demonstrate how easy it is to present your data using pagination.&lt;br /&gt;If part of your application includes displaying lots of results, it's a good idea to give the user the possibility to view the results in digestable chunks and possibly to be able to sort the presented data. This tutorial will explain how, after copying a few files into your application, you can achieve this in very few lines of code.&lt;br /&gt;You need almost no knowledge of cake to be able to make use of this tutorial :).&lt;br /&gt;&lt;br /&gt;If you already have a table in mind that you want to add pagination to, read on; otherwise run through &lt;a href="http://manual.cakephp.org/appendix/blog_tutorial" target="_blank"&gt;http://manual.cakephp.org/appendix/blog_tutorial&lt;/a&gt; to have some code to play with.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/pagination" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-2497083279311296731?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/2497083279311296731/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=2497083279311296731' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2497083279311296731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2497083279311296731'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/pagination.html' title='Pagination'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-7655194010682131587</id><published>2008-12-02T10:46:00.000-08:00</published><updated>2008-12-02T10:48:11.979-08:00</updated><title type='text'>Wildflower realease</title><content type='html'>Content management system and application platform build on CakePHP framework and jQuery Javascript library.&lt;br /&gt;&lt;br /&gt;Download from &lt;a href="http://wf.klevo.sk/" target="_blank"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-7655194010682131587?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/7655194010682131587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=7655194010682131587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7655194010682131587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7655194010682131587'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/wildflower-realease.html' title='Wildflower realease'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-8727182285896903110</id><published>2008-12-02T10:29:00.000-08:00</published><updated>2008-12-02T10:33:00.275-08:00</updated><title type='text'>jQuery is new Kind of javascript Library</title><content type='html'>jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://jquery.com" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-8727182285896903110?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/8727182285896903110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=8727182285896903110' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8727182285896903110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8727182285896903110'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/12/jquery-is-new-kind-of-javascript.html' title='jQuery is new Kind of javascript Library'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-3264037905471791095</id><published>2008-11-30T07:54:00.000-08:00</published><updated>2008-11-30T07:57:16.050-08:00</updated><title type='text'>Extended beforeFilter() snippet</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Nate Constant (Natcon67)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; This is a simple addition to app_controller.php to allow a more customized beforeFilter() callback.&lt;br /&gt;&lt;br /&gt;    Updated: 3/27/2007 - added isset call before calling callback with args&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I set out to get a little more functionality out of the controller callback beforeFilter(). I had 2 requirements for this extended functionality:&lt;br /&gt;&lt;br /&gt;   1. Specify which actions to apply the callback to.&lt;br /&gt;   2. Ability to specify multiple methods beforeFilter would call.&lt;br /&gt;&lt;br /&gt;Let me give a very simple example of how to use this snippet:&lt;br /&gt;in your controller define $beforeFilter which is an array of methods to call and the parameters.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/extended-beforefilter-snippet#comment-3061" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-3264037905471791095?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/3264037905471791095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=3264037905471791095' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3264037905471791095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3264037905471791095'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/extended-beforefilter-snippet.html' title='Extended beforeFilter() snippet'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-4700801086481764871</id><published>2008-11-28T11:15:00.000-08:00</published><updated>2008-11-28T11:16:48.577-08:00</updated><title type='text'>Reading OpenDocuments with CakePHP</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Tobias Funke&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;On my quest to find a simple way to read the contents of an *.odt OpenDocument Text file, better known as OpenOffice Writer files, I stumbled over a simple class that, in combination with a xsl template, converts an *.odt file to XHTML.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/reading-opendocuments-with-cakephp" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-4700801086481764871?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/4700801086481764871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=4700801086481764871' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4700801086481764871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4700801086481764871'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/reading-opendocuments-with-cakephp_28.html' title='Reading OpenDocuments with CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-5566522425095569131</id><published>2008-11-28T11:13:00.000-08:00</published><updated>2008-11-28T11:14:51.195-08:00</updated><title type='text'>Simply storing config values in the DB</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Cameron Perry&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There are many situations in web apps where site-wide configurations need to be accessible to users through admin interfaces, rather than configuration files residing on the server. It is a practical method of storing configuration values that may need changing from time to time, but without access to the core configuration file.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/simply-storing-config-values-in-the-db" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-5566522425095569131?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/5566522425095569131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=5566522425095569131' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/5566522425095569131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/5566522425095569131'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/simply-storing-config-values-in-db_28.html' title='Simply storing config values in the DB'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-5375778437169076266</id><published>2008-11-28T09:46:00.000-08:00</published><updated>2008-11-28T09:47:19.922-08:00</updated><title type='text'>Parsing XML files with CakePHP</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Fahad Ibnay Heylaal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Simple tutorial for parsing xml files quickly using the core XML class of cakephp.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/parsing-xml-files-with-cakephp" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-5375778437169076266?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/5375778437169076266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=5375778437169076266' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/5375778437169076266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/5375778437169076266'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/parsing-xml-files-with-cakephp.html' title='Parsing XML files with CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-8237129735258405880</id><published>2008-11-28T09:43:00.000-08:00</published><updated>2008-11-28T09:44:50.313-08:00</updated><title type='text'>Reading OpenDocuments with CakePHP</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Tobias Funke&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;On my quest to find a simple way to read the contents of an *.odt OpenDocument Text file, better known as OpenOffice Writer files, I stumbled over a simple class that, in combination with a xsl template, converts an *.odt file to XHTML.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/reading-opendocuments-with-cakephp" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-8237129735258405880?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/8237129735258405880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=8237129735258405880' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8237129735258405880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8237129735258405880'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/reading-opendocuments-with-cakephp.html' title='Reading OpenDocuments with CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-105751689988585871</id><published>2008-11-28T09:39:00.000-08:00</published><updated>2008-11-28T09:41:51.033-08:00</updated><title type='text'>Simply storing config values in the DB</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Cameron Perry&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are many situations in web apps where site-wide configurations need to be accessible to users through admin interfaces, rather than configuration files residing on the server. It is a practical method of storing configuration values that may need changing from time to time, but without access to the core configuration file.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/simply-storing-config-values-in-the-db" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-105751689988585871?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/105751689988585871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=105751689988585871' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/105751689988585871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/105751689988585871'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/simply-storing-config-values-in-db.html' title='Simply storing config values in the DB'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-8714879590704269863</id><published>2008-11-28T09:29:00.000-08:00</published><updated>2008-11-28T09:30:47.174-08:00</updated><title type='text'>Multiple Display Field</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Daniel Albert (resshin)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; The behavior allows us to use multiple display field (such as "first_name" and "last_name") as a display field for generating list from a model.&lt;br /&gt;This is really one of common issues: using multiple fields as display field when using the find('list') function.&lt;br /&gt;&lt;br /&gt;Strangely enough, there's only little hint out there about how to do it "elegantly" in CakePHP. tclineks already make a great article in http://bin.cakephp.org/saved/19252#modify, but the code just won't works. I think it's happened because CakePHP now handles find function differently than the previous versions.&lt;br /&gt;&lt;br /&gt;So then I wrote the code below to help anyone who need to use multiple fields in their display field.&lt;br /&gt;Note: The afterFind function is taken without any change from tclineks' bin.&lt;br /&gt;&lt;br /&gt;Using it is as simple as this:&lt;br /&gt;&lt;br /&gt;   1. In your model, define that the model is acting as MultipleDisplayFieldBehavior. For example, see Figure 1.&lt;br /&gt;   2. To generate a list, simply use the find('list') function. For example, see Figure 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note: you must define the "displayField" property. This field (which can be a virtual/non-existent field) will then holds the concatenation of display fields that you defined.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://bakery.cakephp.org/articles/view/multiple-display-field-3" target="_blank"&gt;Read More&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-8714879590704269863?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/8714879590704269863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=8714879590704269863' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8714879590704269863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8714879590704269863'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/multiple-display-field.html' title='Multiple Display Field'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-6777179458587543386</id><published>2008-11-28T09:22:00.000-08:00</published><updated>2008-11-28T09:24:35.217-08:00</updated><title type='text'>How to create an XML-RPC server with CakePHP</title><content type='html'>&lt;span style="font-weight:bold;"&gt;By Filippo Toso (filippo.toso)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; This tutorial describes a method to create an XML-RPC server that goes a bit against Cake’s logic and conventions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I like the way the framework “distributes” the logic of the web application between different controllers (i.e. Posts, Comments, and so on). But when I want to develop an XML-RPC server, I prefer to place all the code into a single controller so I can maintain consistency and have a single place to look for errors. The other advantage of this solution is that you don’t need to add logic in the single controllers to handle XML-RPC calls.&lt;br /&gt;&lt;br /&gt;For the implementation of the XML-RPC protocol I decided to go with the Inutio XML-RPC Library (http://scripts.incutio.com/xmlrpc/). This library is completely object oriented, easy to use and works with both PHP 4 and PHP 5.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;You can download a little modified version from the following URL:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.creativepark.it/downloads/xmlrpc.zip" target="_blank"&gt;http://www.creativepark.it/downloads/xmlrpc.zip &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bakery.cakephp.org/articles/view/how-to-create-an-xml-rpc-server-with-cakephp" target="_blank"&gt;More&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-6777179458587543386?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/6777179458587543386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=6777179458587543386' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6777179458587543386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6777179458587543386'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/how-to-create-xml-rpc-server-with.html' title='How to create an XML-RPC server with CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-3190031254703946123</id><published>2008-11-28T07:58:00.000-08:00</published><updated>2008-11-28T08:01:04.204-08:00</updated><title type='text'>Cakephp Downloads</title><content type='html'>CakePHP: the rapid development php framework. &lt;a href="http://cakephp.org/downloads" target="_blank"&gt;Downloads&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-3190031254703946123?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/3190031254703946123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=3190031254703946123' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3190031254703946123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3190031254703946123'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/cakephp-downloads.html' title='Cakephp Downloads'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-4902296725520313552</id><published>2008-11-28T07:53:00.000-08:00</published><updated>2008-11-28T07:55:24.460-08:00</updated><title type='text'>CakePHP Install: Multiple Subdirectories &amp; 500 Error</title><content type='html'>So, the last few weeks, I started learning how to use the CakePHP framework. It’s been a little slow going, but it’s been pretty good. I’ve been developing on my local machine, which, for some reason, mod_rewrite just refuses to work. So, I decided to make a dev site on the server. Oh, what a disaster.&lt;br /&gt;&lt;br /&gt;I created the directory and ftp’d all the files on to the server. When I went to test it, I kept on getting a bunch of 500 errors. I tried moving the files around, looking at the “manual”, but nothing was solving the problem. I spent all afternoon, and narrowed it down to a problem with the .htaccess file.&lt;br /&gt;&lt;br /&gt;When I came back from dinner, I found the solution.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The Problem:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   1. Installing CakePHP in a subdirectory;&lt;br /&gt;   2. Resolving the 500 errors.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ninjavspenguin.com/blog/2007/01/21/cakephp-install-multiple-subdirectories-500-error/" target="_blank"&gt;More&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-4902296725520313552?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/4902296725520313552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=4902296725520313552' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4902296725520313552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4902296725520313552'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/cakephp-install-multiple-subdirectories.html' title='CakePHP Install: Multiple Subdirectories &amp; 500 Error'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-2071609268001866853</id><published>2008-11-23T08:01:00.000-08:00</published><updated>2008-11-23T08:05:03.791-08:00</updated><title type='text'>Building a blog with CakePHP</title><content type='html'>CakePHP is a rapid development framework for PHP that provides an extensible architecture for developing, maintaining, and deploying applications. Using commonly known design patterns like MVC and ORM within the convention over configuration paradigm, CakePHP reduces development costs and helps developers write less code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This tutorial will give you a good start in the world of CakePHP, just to learn the basics of the framework. The &lt;a href="http://book.cakephp.org/view/326/The-Cake-Blog-Tutorial" target="_blank"&gt;official CakePHP Blog tutorial &lt;/a&gt;(For Cake 1.1) gives you a good idea, but this tutorial will take it a couple of steps further (and in the next parts way beyond the official tutorial). Don't worry: This article will perfectly guide to making your first steps on baking some code.&lt;br /&gt;&lt;br /&gt;For More details you can view the below link:&lt;br /&gt;&lt;a href="http://www.marcofolio.net/webdesign/building_a_blog_with_cakephp_part_1_getting_started.html" target="_blank"&gt;&lt;br /&gt;http://www.marcofolio.net/webdesign/building_a_blog_with_cakephp_part_1_getting_started.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-2071609268001866853?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/2071609268001866853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=2071609268001866853' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2071609268001866853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2071609268001866853'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/building-blog-with-cakephp.html' title='Building a blog with CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-1075375002185854434</id><published>2008-11-23T07:55:00.000-08:00</published><updated>2008-11-23T07:57:18.186-08:00</updated><title type='text'>Get Started With AJAX in CakePHP</title><content type='html'>Some links are available from the below link: &lt;br /&gt;&lt;br /&gt;&lt;a href="http://ahsanity.wordpress.com/2007/02/23/get-started-with-ajax-in-cakephp/" target="_blank"&gt;http://ahsanity.wordpress.com/2007/02/23/get-started-with-ajax-in-cakephp/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-1075375002185854434?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/1075375002185854434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=1075375002185854434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/1075375002185854434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/1075375002185854434'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/get-started-with-ajax-in-cakephp.html' title='Get Started With AJAX in CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-3739900250374908994</id><published>2008-11-23T07:39:00.000-08:00</published><updated>2008-11-23T07:47:09.020-08:00</updated><title type='text'>CakePHP Ajax Chat Plugin</title><content type='html'>CakePHP Ajax Chat Demo (Uses jQuery)&lt;br /&gt;&lt;br /&gt;Download the helper from there &lt;br /&gt;&lt;br /&gt;&lt;a href="http://sandbox2.pseudocoder.com/demo/chat" target="_blank"&gt;http://sandbox2.pseudocoder.com/demo/chat&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-3739900250374908994?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/3739900250374908994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=3739900250374908994' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3739900250374908994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3739900250374908994'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/cakephp-ajax-chat-plugin.html' title='CakePHP Ajax Chat Plugin'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-9137992771897471215</id><published>2008-11-21T12:29:00.000-08:00</published><updated>2008-11-21T12:34:39.758-08:00</updated><title type='text'>Bake ROT13 Encoded "mailto:" Link</title><content type='html'>By Debugged Interactive Designs (debuggeddesigns)&lt;br /&gt;&lt;br /&gt;Why would I want to use encoded "mailto:" anchor tags? To obfuscate e-mail addresses from spam harvesters. The helper lets you easily encode an entire anchor tag using ROT13 Encryption. The ROT13 encoding simply shifts every letter by 13 places in the alphabet while leaving non-alpha characters untouched. At run-time, javascript is used to decode the ROT13 encryption. If javascript is disabled, then the e-mail address is safely shown by reversing the e-mail address using PHP and re-reversing (versing?) it at run-time using CSS.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Step 1: Create the Mailto helper&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This helper's function accepts an e-mail address and link content as it's parameters and returns javascript code containing the encrypted anchor tag.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Filename: /app/views/helpers/mailto.php&lt;br /&gt;Helper Class:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;class MailtoHelper extends Helper {&lt;br /&gt;    &lt;br /&gt;    function createLink($addr, $link_content) {&lt;br /&gt;&lt;br /&gt;        //build the mailto link&lt;br /&gt;        $unencrypted_link = '&lt;a href="mailto:'.$addr.'"&gt;'.$link_content.'&lt;/a&gt;';&lt;br /&gt;        //build this for people with js turned off&lt;br /&gt;        $noscript_link = '&lt;noscript&gt;&lt;span style="unicode-bidi:bidi-override;direction:rtl;"&gt;'.strrev($link_content.' &gt; '.$addr.' &lt;').'&lt;/span&gt;&lt;/noscript&gt;';&lt;br /&gt;        //put them together and encrypt&lt;br /&gt;        $encrypted_link = '&lt;script type="text/javascript"&gt;Rot13.write(\''.str_rot13($unencrypted_link).'\');&lt;/script&gt;'.$noscript_link;&lt;br /&gt;&lt;br /&gt;        return $encrypted_link;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Step 2: Include the helper inside your controller&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Filename: /app/controllers/tests_controller.php&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Controller Class:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;class TestsController extends AppController {&lt;br /&gt;    var $name = 'Tests';&lt;br /&gt;    var $helpers = array('Mailto');&lt;br /&gt;&lt;br /&gt;    function mailto() { }&lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Step 3: Create the javascript&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The javascript decodes the anchor tag that was encoded in the helper above.&lt;br /&gt;&lt;br /&gt;Download this file: http://scott.yang.id.au/file/js/rot13.js&lt;br /&gt;Save the file here: /app/webroot/js/rot13.js&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Step 4: Include rot13.js in your layout view&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Filename: /app/views/layouts/default.thtml&lt;br /&gt;View Template:&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript" src="&lt;?php echo $this-&gt;webroot; ?&gt;js/rot13.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Step 5: Use the helper inside a view&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Filename: /app/views/tests/mailto.thtml&lt;br /&gt;View Template:&lt;br /&gt;&lt;br /&gt;&lt;?php echo $mailto-&gt;createLink('spam@debuggeddesigns.com','Debugged Interactive Designs'); ?&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Step 6: View the source and be amazed&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To test it out, visit the page www.yourdomain.com/tests/mailto&lt;br /&gt;&lt;br /&gt;This is the ROT13 encoded anchor tag found in the source code:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;Rot13.write('&lt;n uers="znvygb:fcnz@qrohttrqqrfvtaf.pbz"&gt;Qrohttrq Vagrenpgvir Qrfvtaf&lt;/n&gt;');&lt;/script&gt;&lt;noscript&gt;&lt;span style="unicode-bidi:bidi-override;direction:rtl;"&gt;&lt; moc.sngiseddeggubed@maps &gt; sngiseD evitcaretnI deggubeD&lt;/span&gt;&lt;/noscript&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I got this idea from a presentation by Mark Rosenthal at a BostonPHP meeting that explained this technique. He admitted that there are many different techniques for tricking spam bots, and he might not be the first to think of this one. Well, after some google searching, he wasn't: http://scott.yang.id.au/2003/06/obfuscate-email-address-with-javascript-rot13/. Believe it or not, that javascript file above was written by Scott Yang in 2003 for this exact purpose. Please leave any alternate techniques you might use in the comments below.&lt;br /&gt;&lt;br /&gt;Update: Since creating this helper, I found the article "Nine Ways To Obfuscate E-mail Addresses Compared" at http://techblog.tilllate.com/2008/07/20/ten-methods-to-obfuscate-e-mail-addresses-compared/, which says ROT13 encoding and changing the code direction with css "...are absolutely rock-solid and keep your addresses safe from the harvesters."&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-9137992771897471215?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/9137992771897471215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=9137992771897471215' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/9137992771897471215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/9137992771897471215'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/bake-rot13-encoded-mailto-link.html' title='Bake ROT13 Encoded &quot;mailto:&quot; Link'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-6663221428015566158</id><published>2008-11-21T12:25:00.000-08:00</published><updated>2008-11-21T12:27:54.195-08:00</updated><title type='text'>Brita component with HTML Purifier</title><content type='html'>By Debugged Interactive Designs (debuggeddesigns)&lt;br /&gt;Brita is a CakePHP Component wrapper class created to take advantage of the functionality provided by HTML Purifier. HTML Purifier is a standards-compliant HTML filter library written in PHP. HTML Purifier will not only remove all malicious code (better known as XSS) with a thoroughly audited, secure yet permissive whitelist, it will also make sure your documents are standards compliant, something only achievable with a comprehensive knowledge of W3C's specifications. &lt;br /&gt;&lt;br /&gt;Step 1: Download and unzip archive&lt;br /&gt;&lt;br /&gt;Download an HTMLPurifier archive (either .zip or .tar.gz) at http://htmlpurifier.org/download.html and unzip the archive into the directory /app/vendors/htmlpurifier/&lt;br /&gt;&lt;br /&gt;Note: Only the contents in the /app/vendors/htmlpurifier/library/ folder are necessary, so you can remove everything else when using HTML Purifier in a production environment.&lt;br /&gt;&lt;br /&gt;Note 2: The folder /app/vendors/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer must be writeable by the webserver.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Step 2: Create brita component&lt;br /&gt;Filename: /app/controllers/components/brita.php&lt;br /&gt;Component Class:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;//cake's version of a require_once() call&lt;br /&gt;vendor('htmlpurifier'.DS.'library'.DS.'HTMLPurifier.auto'); //use this with the 1.1 core&lt;br /&gt;//App::import('Vendor','HTMLPurifier' ,array('file'=&gt;'htmlpurifier'.DS.'library'.DS.'HTMLPurifier.auto.php')); //use this with the 1.2 core&lt;br /&gt;&lt;br /&gt;class BritaComponent extends Object {&lt;br /&gt;&lt;br /&gt;    var $controller;&lt;br /&gt;&lt;br /&gt;    function startup( &amp;$controller ) {&lt;br /&gt;&lt;br /&gt;        //the next few lines allow the config settings to be cached&lt;br /&gt;        $config = HTMLPurifier_Config::createDefault();&lt;br /&gt;        $config-&gt;set('HTML', 'DefinitionID', 'made by debugged interactive designs');&lt;br /&gt;        $config-&gt;set('HTML', 'DefinitionRev', 1);&lt;br /&gt;        //levels describe how aggressive the Tidy module should be when cleaning up html&lt;br /&gt;        //four levels: none, light, medium, heavy&lt;br /&gt;        $config-&gt;set('HTML', 'TidyLevel', 'heavy');&lt;br /&gt;        //check the top of your html file for the next two&lt;br /&gt;        $config-&gt;set('HTML', 'Doctype', 'XHTML 1.0 Transitional');&lt;br /&gt;        $config-&gt;set('Core', 'Encoding', 'ISO-8859-1');&lt;br /&gt;        &lt;br /&gt;        //BritaComponent instance of controller is replaced by a htmlpurifier instance&lt;br /&gt;        $controller-&gt;brita =&amp; new HTMLPurifier($config);&lt;br /&gt;        $controller-&gt;set('brita',$controller-&gt;brita);&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;Step 3: Use the brita component inside a controller&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Filename: /app/controllers/tests_controller.php&lt;br /&gt;Controller Class:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;class TestsController extends AppController {&lt;br /&gt;    var $name = 'Tests';&lt;br /&gt;    var $components = array('Brita'); //import the Brita Component&lt;br /&gt;       &lt;br /&gt;    function brita() {&lt;br /&gt;        //fake user input that we will purify (for testing)&lt;br /&gt;        $dirty_html = '&lt;br&gt;&lt;br&gt;&lt;center&gt;&lt;font size="2"&gt;testing&lt;/font&gt;&lt;/center&gt;';&lt;br /&gt;        //this one line of code does all the purifying&lt;br /&gt;        $clean_html = $this-&gt;brita-&gt;purify( $dirty_html );&lt;br /&gt;        //set the before and after html for the test view&lt;br /&gt;        $this-&gt;set('clean_html',$clean_html);&lt;br /&gt;        $this-&gt;set('dirty_html',$dirty_html);&lt;br /&gt;    }   &lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;Step 4: Create a test view&lt;br /&gt;Filename: /app/views/tests/brita.thtml &lt;br /&gt;&lt;br /&gt;&lt;div&gt;DIRTY HTML = &lt;?php echo htmlentities($dirty_html);?&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="border:1px solid black;"&gt;&lt;?php echo $dirty_html;?&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;CLEAN HTML = &lt;?php echo htmlentities($clean_html);?&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="border:1px solid black;"&gt;&lt;?php echo $clean_html;?&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-6663221428015566158?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/6663221428015566158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=6663221428015566158' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6663221428015566158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6663221428015566158'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/brita-component-with-html-purifier.html' title='Brita component with HTML Purifier'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-442582711699552000</id><published>2008-11-21T11:57:00.000-08:00</published><updated>2008-11-21T12:09:13.812-08:00</updated><title type='text'>Migrating a real-world application to CakePHP 1.2</title><content type='html'>By Martin Westin (eimermusic)&lt;br /&gt;&lt;br /&gt;I thought I'd chronicle my work migrating my fist CakePHP application to CakePHP 1.2 (rc3 at the time of writing). The application was originally written for CakePHP 1.0 (= the good old days). It has been updated to work with the latest versions 1.1 but has not really been rewritten much.&lt;br /&gt;&lt;br /&gt;Considering how much CakePHP has evolved and also how many beginner-mistakes I have put into this application, this migration will also describe some pretty huge optimizations that was possible because of new features and my improved knowledge of CakePHP.&lt;br /&gt;&lt;br /&gt;About The Application&lt;br /&gt;&lt;br /&gt;The application if called Fileshifter and it is a simple file manager and file sharing application. The original purpose was to complement an ftp server. Fileshifter is generally more simple to manage and easier for "average people" to handle. You have projects and upload files into them or download files from them. As admin you can manage user accounts and project permissions.&lt;br /&gt;&lt;br /&gt;The English pages on the application-website are horribly out of date. Sorry. There are a few screen-casts in the Swedish section that might give some context to what I am writing about, though.&lt;br /&gt;http://www.fileshifter.se/ &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;First attempt. Aka: Oh crap, nothing works&lt;br /&gt;Just dropping my old application into CakePHP 1.2 clearly didn't work. :)&lt;br /&gt;I just got two errors. The second one was a fatal error which halted further execution in config/routes.php&lt;br /&gt;&lt;br /&gt;I went through all files in the config directory. This took a little while but I wanted to get the configurations identical to those I had before. One bonus for my application is the new configuration directive to not check the userAgent. This will be very useful for my upload actions that will be used by the java applet the application uses. In earlier versions I manually hacked the core to make this possible.&lt;br /&gt;&lt;br /&gt;core.php&lt;br /&gt;Starting with a clean file from CakePHP 1.2 I changed the following things for my application. Not all as strictly necessary to get an application running.&lt;br /&gt;Session.cookie - set to the same name as in the old application.&lt;br /&gt;Session.checkAgent - set to false globally for the time being. I will check if I can set this just in the relevant controller without causing problems.&lt;br /&gt;Security.salt - should always be altered. I kept part of the original string, moved things around and inserted some swedish words here and there just for fun.&lt;br /&gt;&lt;br /&gt;bootstrap.php&lt;br /&gt;My old file set a few constants used to configure the application. A few of these I switched over to the new Configure class. Most, I left as constants since they are nothing you would ever change at runtime. For example the path to the root of the file area.&lt;br /&gt;The current language was one of the ones I switched over. See below about i18n.&lt;br /&gt;&lt;br /&gt;database.php&lt;br /&gt;Not a big problem here. The could have been left as is but I did copy over the login parameters to a fresh file. I noticed that the connect parameter does not need to be set for MySQL. I am not sure about before but now it is enough to set persistent to true.&lt;br /&gt;&lt;br /&gt;routes.php&lt;br /&gt;The few routes I had defined only needed to call the method statically to continue to work. For example:&lt;br /&gt;Download code&lt;br /&gt;$Route-&gt;connect ('/', array('controller'=&gt;'efs', 'action'=&gt;'index'));&lt;br /&gt;became:&lt;br /&gt;Download code&lt;br /&gt;Router::connect('/', array('controller' =&gt; 'efs', 'action' =&gt; 'index'));&lt;br /&gt;&lt;br /&gt;I also replaced all default files (index.php, .htaccess ...). I did not bother to check which had changed. It was simpler to just replace them all with the new 1.2 versions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;File model clashes with the File class&lt;br /&gt;Since my application is a file manager I had a model called File. It actually took me a good while before I figured out that my File model clashes with the File class in the core. Time for some search and replace. All references to File was replaced with EfsFile (did not think of anything better). Most of it could be changed this simply, but I had to make a few manual adjustments. Cakes $useTable came in good use here. I did not have to alter the database just because I renamed the class.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Replacing authentication&lt;br /&gt;Next big problem is authentication. Since all data the user can interact with flows from the authenticated user account, this basically stops my application completely until I get the new authentication up and running. Lucky enough I was using an Auth component that works kind-of similar to the current Auth component in the core. There was still a lot of work but it could have been worse.&lt;br /&gt;&lt;br /&gt;I didn't keep any of the code from the old authentication. What I did was take copy a lot of it over from another application where I first tried some basic 1.2 authentication. The code is pretty much straight out of the tutorials available all over the web.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Permissions&lt;br /&gt;In the original version I intentionally kept permissions to a minimum. Simplicity was the key and increased complexity and granularity in permissions will increase the workload for the administrator. This was of-course no bad thing when it came to updating the authentication. The old Component used a User model and a Permission model. I saw no reason to even have a model for permissions anymore since all I needed was "normal user" and "admin user". I mapped this to a simple integer field in the users table. I can imagine that trying to migrate a role-based system can be a lot more work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Transitioning old passwords&lt;br /&gt;I have managed to keep all the old passwords. They were md5 hashed without a salt so I was able to get it working by defining an authenticate object for Auth. I chose to make the User model the authenticate object. It feels natural to have password hashing there.&lt;br /&gt;In AppController::beforeFilter:&lt;br /&gt;Download code&lt;br /&gt;$this-&gt;Auth-&gt;authenticate =&amp; $this-&gt;Auth-&gt;getModel();&lt;br /&gt;And in models/user.php I added:&lt;br /&gt;Download code&lt;br /&gt;function hashPasswords($data) {&lt;br /&gt;    if (is_array($data) &amp;&amp; isset($data[$this-&gt;alias])) {&lt;br /&gt;        if (isset($data[$this-&gt;alias]['email']) &amp;&amp; isset($data[$this-&gt;alias]['pass'])) {&lt;br /&gt;            $data[$this-&gt;alias]['pass'] = Security::hash($data[$this-&gt;alias]['pass'], 'md5', false);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return $data;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;One thing still on the todo-list is that I would rather try to manage a transitional system for the first release after this migration. Something where the password can be checked against both the old and new hash. Any login where the stored password matches the old hash will be replaced by the given password hashed using the new (more secure) system using a salt. If I can't get that to work I have to make a judgement call wether to keep the old less safe passwords or require all users in all installations to renew their passwords. We'll see...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Changing the code convention of the entire application&lt;br /&gt;This can be tedious if you plan to do it in one big pass. I decided to use this as an indicator of what code I had looked over and changed. Any method I altered or examined and decided not to alter was given a change in coding style to indicate that it was "approved" 1.2 code. If I had been happy with my old style I would not have done this, but since I planed to change it, this was a good way to do it.&lt;br /&gt;&lt;br /&gt;Loading classes and other external code&lt;br /&gt;All the old methods of loading files have changed. No more uses(), no more vendor(). This is now all taken care of by App::import(). For example when I load a PEAR class to archive a whole folder:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;vendor('Archive/Tar'); &lt;br /&gt;&lt;br /&gt;now reads:&lt;br /&gt;&lt;br /&gt;App::import('Vendor','Archive/Tar'); &lt;br /&gt;&lt;br /&gt;The component dealing with syncing with the filesystem nor loads the needed models in a single call, like this:&lt;br /&gt;&lt;br /&gt;App::import('Model',array('Project','EfsFile')); &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Removing requestAction()&lt;br /&gt;Like so many starting out, I was seduced by requestAction(). Looking at my old code I remember believing that only the UsersController should manipulate the User model. That is partly why I turned to requestAction when one controller needed access to "another model".&lt;br /&gt;&lt;br /&gt;My primary requestAction() was to call "/files/viewedBy/1/1" whenever a user selected a new file. This would log that the user has seen the file. By moving this code into the EfsFile model I was abel to take the request-time for these down quite a bit. With my test-data this went down to 0.15s from well over a second before. Partly because of the overhead of a request and partly because of Containable helping to optimize the data retrieval.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hey, where did my data go?&lt;br /&gt;One new behavior introduced in CakePHP 1.2 RC3 may delete some data by accident. If an association has conditions, you should use the new array notation for conditions. If you delete a record and dependent is true, you expect the related record(s) to be deleted as well. If conditions is not an array you can delete delete all records of the related model, not just related ones. I have had this happen to my data for hasOne associations. I have not done extensive test to see if this affects other associations.&lt;br /&gt;This is straight out of manual as it was a while ago:&lt;br /&gt;Model Class:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;class User extends AppModel {&lt;br /&gt;    var $name = 'User';&lt;br /&gt;    var $hasMany = array(&lt;br /&gt;        'Comment' =&gt; array(&lt;br /&gt;            'className'    =&gt; 'Comment',&lt;br /&gt;            'foreignKey' =&gt; 'user_id',&lt;br /&gt;            'conditions' =&gt; 'Comment.status = 1',&lt;br /&gt;            'order' =&gt; 'Comment.created DESC',&lt;br /&gt;            'limit' =&gt; '5',&lt;br /&gt;            'dependent'=&gt; true&lt;br /&gt;        )&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;And this is the small but important change:&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;class User extends AppModel {&lt;br /&gt;    var $name = 'User';&lt;br /&gt;    var $hasMany = array(&lt;br /&gt;        'Comment' =&gt; array(&lt;br /&gt;            'className'    =&gt; 'Comment',&lt;br /&gt;            'foreignKey' =&gt; 'user_id',&lt;br /&gt;            'conditions' =&gt; array('Comment.status' =&gt; '1'),&lt;br /&gt;            'order' =&gt; 'Comment.created DESC',&lt;br /&gt;            'limit' =&gt; '5',&lt;br /&gt;            'dependent'=&gt; true&lt;br /&gt;        )&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;I believe even empty conditions can cause you problems:&lt;br /&gt;&lt;br /&gt;'conditions' =&gt; '', &lt;br /&gt;&lt;br /&gt;it should be:&lt;br /&gt;&lt;br /&gt;'conditions' =&gt; array(), &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I am not certain about that last bit but better safe than sorry, right?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hey, where did my data go? part 2&lt;br /&gt;There was a bug introduced in CakePHP 1.2 rc3 that anyone updating should be aware of. Cake can accidentally delete data in the join tables of your HABTM associations. This happens if the association is two-sided and you remove the "link" between two records. Any other record the associated record is linked to is also unlinked. I found this out the hard way. I then discovered a bug report in trac. The fix described there has worked for me in two applications for a few weeks now. See the ticket for details and example-code.&lt;br /&gt;https://trac.cakephp.org/ticket/5579&lt;br /&gt;&lt;br /&gt;Finding new data&lt;br /&gt;The Model methods find(), findAll() and so on have changed a lot. This required a lot of manual work, but since I could optimize thing at the same time and speed up the application noticeably I didn't really mind the work. I also thing this new syntax is a lot easier to use.&lt;br /&gt;&lt;br /&gt;$allProj = $this-&gt;Project-&gt;findAll(null,null,'Project.title ASC'); &lt;br /&gt;&lt;br /&gt;should now read:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$allProj = $this-&gt;Project-&gt;find('all',array(&lt;br /&gt;    'order' =&gt; 'Project.title ASC'&lt;br /&gt;));&lt;br /&gt;&lt;br /&gt;or better yet:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$allProj = $this-&gt;Project-&gt;find('all',array(&lt;br /&gt;    'order' =&gt; array('Project.title' =&gt; 'ASC')&lt;br /&gt;));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note: Keeping "ASC" in my example is not necessary but I like to have it there so I know at a glance what is going on.&lt;br /&gt;OK, all find operations are now taken care of by find. The first parameter indicates the type of find to perform. Setting it to "first" will find a single record for example. The second parameter is an array, like in so many places in CakePHP 1.2. This should contain the additions you want to make to the query. As you can see order is one thing. Conditions is another. Fields is a third. I could never remember if order was parameter number 3,4 or 5. Now I don't have to. I just add a key called order and a value with the ordering field and direction I want. It does not have to come before or after the conditions... all very nice.&lt;br /&gt;&lt;br /&gt;All of these parameters can be broken down into arrays themselves. This adds another layer of protection against sql injections. The conditions can even be broken down into ands and ors in a deep structure. Cake will construct a nice where-clause of them for you and keep track of all the parenthesis. See the manual for many examples of this. The same goes for deleteAll() and any other conditions throughout the application.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$result = $this-&gt;deleteAll( array(&lt;br /&gt;    $this-&gt;alias.'.created &lt;' =&gt; $deadline&lt;br /&gt;)); &lt;br /&gt;&lt;br /&gt;Notice that the comparison operator is on the left side. This is new since CakePHP 1.2 RC2, I think.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I can hardly contain myself&lt;br /&gt;Am am bursting with joy! Containable behavior is one of my favorite features in CakePHP 1.2. Containable is like find() on steroids. It is like associations on acid. It is like... ok enough! The basic first step is to simple add this to the relevant models.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;var $actsAs = array('Containable'); &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Containable is a behavior that helps you optimize your queries. Perviously all I could do was to set recursive and unbind a model. Containable sort-of does this for you, in a very intuitive way. Parts of the application has been sped up by a factor of 8. That is 8x the original request time, largely because of Containable.&lt;br /&gt;&lt;br /&gt;It may sound like magic, but imagine this:&lt;br /&gt;&lt;br /&gt;User: habtm Project, habtm File&lt;br /&gt;Project: hasMany File, habtm User&lt;br /&gt;File: habtm User, belongsTo Project&lt;br /&gt;&lt;br /&gt;These three models can easily cause a lot of unnecessary data to be loaded since they relate to each-other in several ways. By taking advantage of some simple functionality in containable I was abel to eliminate most of the unused data from my queries. For example, loading a single file:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$data = $this-&gt;User-&gt;find('first', array(&lt;br /&gt;    'conditions' =&gt; array('User.id'=&gt;$this-&gt;userData['User']['id']),&lt;br /&gt;    'contain' =&gt; array(&lt;br /&gt;        'Project'=&gt;array(&lt;br /&gt;            'EfsFile'=&gt;array(&lt;br /&gt;                'conditions'=&gt;array('EfsFile.id'=&gt;$this-&gt;params['id'])&lt;br /&gt;            )&lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;)); &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In english: Find the currently logged in User. Contain the results to also include any related Project and to the project related File if the id of the file is the one we want.&lt;br /&gt;&lt;br /&gt;This may look like a backwards way of loading a file. However this is quite effective since I only want the file to load is it is in a project that the current user has access to. Using the Set class (another great new feature in 1.2) it is no big problem picking out the file from the results. Just imagine the mess returned if I had set recursive to 2 instead... I would have loaded all files in all projects related to the user and I would have had to loop through the results to locate the one with the right id (making it a condition would not have worked). OK, that was an example from hell but I hope the point was made. Containable is your friend. Please check the manual for more complete details on how to use Containable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;New validation system&lt;br /&gt;I must admit, I did not have a lot of validation before. The validation I had was mostly custom validation code. Some of it even in the controller (ick!). One thing I did validate before was, naturally, login data. For example, validating uniqueness is a lot better in 1.2. And there is also support for multiple validation rules per field. Apart from changing the validation I had I also added a few rules for the files and projects. I still have to change my controller code to make better use of the validation errors and messages, though.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;var $validate = array(&lt;br /&gt;    'name'=&gt;VALID_NOT_EMPTY,&lt;br /&gt;    'login'=&gt;VALID_NOT_EMPTY,&lt;br /&gt;    'email'=&gt;VALID_EMAIL&lt;br /&gt;); &lt;br /&gt;&lt;br /&gt;var $validate = array(&lt;br /&gt;    'name' =&gt; array(&lt;br /&gt;        'rule' =&gt; 'notEmpty',&lt;br /&gt;        'message' =&gt; 'The name can not be left blank'&lt;br /&gt;    ),&lt;br /&gt;    'email' =&gt; array(&lt;br /&gt;        'email' =&gt; array(&lt;br /&gt;            'rule' =&gt; 'email',&lt;br /&gt;            'message' =&gt; 'This is not a valid email.'&lt;br /&gt;        ),&lt;br /&gt;        'unique' =&gt; array(&lt;br /&gt;            'rule' =&gt; 'isUnique',&lt;br /&gt;            'message' =&gt; 'This email already used for another user.'&lt;br /&gt;        )&lt;br /&gt;    )&lt;br /&gt;); &lt;br /&gt;&lt;br /&gt;The error messages above have been replaced to make them more readable. They are in the form of translation keys in the real code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Synchronizing with the filesystem&lt;br /&gt;The application keeps its files and folders in the database. To enable admins to expose the files on their local network or a traditional ftp, there is a component that checks the filesystem for changes. I was able to optimize this comparison quite a bit.&lt;br /&gt;&lt;br /&gt;My original code fetched all files and folders, queried the database and then compared the two using foreach loops. These become exponentially slower as the number of files grow. Comparing 100 files would result in 100*100 comparisons just to determine that nothing new has been added.&lt;br /&gt;&lt;br /&gt;foreach ( $system as $sysFile ) {&lt;br /&gt;    foreach ( $data as $dataFile ) {&lt;br /&gt;        if ( $sysFile['EfsFile']['filename'] == $dataFile['EfsFile']['filename'] ) {&lt;br /&gt;            // OK, this file exists already&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;The goal was to remove at least one of the foreach loops to keep the speed increase in check. Since these are Cake-style multi-dimensional arrays simple comparisons like array_diff() don't work. The Set class was of-course a little slower than the foreach loops since it does basically the same thing, only a bit more advanced.&lt;br /&gt;&lt;br /&gt;Once again I found that putting more responsibility on MySQL was the answer. My new code fetches all files and folders, loops through that data and queries the database to see if a known file can be found. Testing with about 3'000 files, I measured this code to be twice as fast as the original code. Checking 3'000 files in 14 folders now takes 4.5sec instead of 8.6sec.&lt;br /&gt;&lt;br /&gt;foreach ( $system as $sysFile ) {&lt;br /&gt;    $this-&gt;EfsFile-&gt;contain();&lt;br /&gt;    $found = $this-&gt;EfsFile-&gt;find('first', array(&lt;br /&gt;        'conditions' =&gt; array(&lt;br /&gt;            'EfsFile.filename'=&gt; $sysFile['filename'],&lt;br /&gt;            'EfsFile.project_id'=&gt; $current_project_id&lt;br /&gt;        )&lt;br /&gt;    ));&lt;br /&gt;    if ( $found ) {&lt;br /&gt;        // OK, this file exists already&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Filesystem case sensitivity&lt;br /&gt;I got this strange error while testing. Each sync with the filesystem would result in duplicate files in a certain project. Turned out the problem was one of case sensitivity. Some filesystems are case sensitive, some are not. PHP definitely is case sensitive when doing simple comparisons like $filename1 == $filename2. This can cause problems when files and folders are added and renamed outside of my application. Renaming a folder test =&gt; Test will still find the same folder when on a case insensitive system but it will not be considered the same folder by the sync code discussed above. I needed a way to handle this problem. Here is what I came up with:&lt;br /&gt;in config/bootstrap.php&lt;br /&gt;&lt;br /&gt;define('EFS_FILESYSTEM_TYPE', 'ci'); // filesystem is set to case insensitive &lt;br /&gt;&lt;br /&gt;in vendors/basics.php (my file of small handy global functions)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// returns a filename or foldername in the correct case for comparison&lt;br /&gt;function file_case($str) {&lt;br /&gt;    if ( EFS_FILESYSTEM_TYPE == 'ci' ) {&lt;br /&gt;        return low($str); // Filesystem in case insensitive&lt;br /&gt;    } else {&lt;br /&gt;        return $str; // Filesystem in case sensitive&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That is ok and it works. But how many of my customers actually know what filesystem they are running? These are people who choose this app for its simplicity. Can't I use some function to find the filesystem type automatically? Well, yes I can. I looked for some internal php mechanism but found none. There may be plento of smarter ways to do this but here is what I did:&lt;br /&gt;in vendors/basics.php (my file of small handy global functions)&lt;br /&gt;&lt;br /&gt;// returns a filename or foldername in the correct case for comparison&lt;br /&gt;function file_case($str) {&lt;br /&gt;    if ( !defined('EFS_FILESYSTEM_TYPE') ) {&lt;br /&gt;        $file_name = 'CaseTest.txt';&lt;br /&gt;        if ( is_file(dirname(__FILE__).DS.$file_name) &amp;&amp; is_file(dirname(__FILE__).DS.low($file_name)) ) {&lt;br /&gt;            define('EFS_FILESYSTEM_TYPE', 'ci'); // Filesystem in case insensitive&lt;br /&gt;        } else {&lt;br /&gt;            define('EFS_FILESYSTEM_TYPE', 'cs'); // Filesystem in case sensitive&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    if ( EFS_FILESYSTEM_TYPE == 'ci' ) {&lt;br /&gt;        return low($str); // Filesystem in case insensitive&lt;br /&gt;    } else {&lt;br /&gt;        return $str; // Filesystem in case sensitive&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I checks "the same file" twise. Once with the filename capitalized and once in all lowercase. If they both exist then the filesystem should be case insensitive. This works when tested on HFS+ volumes of both types.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Re-factoring stupid noob code&lt;br /&gt;A post on the CakePHP Google group got me thinking about a component I coded for this application. It is (or was) a Ticket component for maintaining temporary tickets of the type many websites use for password resets and registration activations.&lt;br /&gt;&lt;br /&gt;When I started looking at this old component I realized that the only reason this was a component at all was vanity. I thought a component would be "kewl" and really wanted to create a component. This was of-course horribly wrong. The component may still be published here:&lt;br /&gt;http://bakery.cakephp.org/articles/view/ticket-component-resetting-user-passwords&lt;br /&gt;The component is really just a proxy to the Ticket model storing the tickets. I re-factored the code in the component into the model and included the model in the controllers that previously included the component.&lt;br /&gt;&lt;br /&gt;Unfortunately I had to rename most of the methods from the component since they clashed with internal Model methods like set() and del(). What took the most time was finding new names for these methods. Out of frustration I (temporarily) just called them setTicket() and drop(). Ugly, yes. I hate putting the class name in the method name... totally useless but my English vocabulary doesn't include a good synonym.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;l10n and i18n&lt;br /&gt;The original application used my own code for language management. I had a php-file for each language. All labels were defined in an associative array in those files. Like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$labels = array();&lt;br /&gt;&lt;br /&gt;//--  login page&lt;br /&gt;$labels['login_username']  = 'Login Id';&lt;br /&gt;$labels['login_password']  = 'Password';&lt;br /&gt;$labels['login_login']     = 'Login'; &lt;br /&gt;&lt;br /&gt;The first step was to convert these files into gettext po-files. It was a matter of search and replace for 90% of it. Some comments had to be moved and changed manually and things of this nature. The results looked something like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# login page&lt;br /&gt;msgid "login_username"&lt;br /&gt;msgstr "Login Id"&lt;br /&gt;&lt;br /&gt;msgid "login_password"&lt;br /&gt;msgstr "Password"&lt;br /&gt;&lt;br /&gt;msgid "login_login"&lt;br /&gt;msgstr "Login" &lt;br /&gt;&lt;br /&gt;These files were put into the relevant folders. E.g. locale/eng/LC_MESSAGES/default.po&lt;br /&gt;&lt;br /&gt;The second step was to replace my own translation function with the built-in __(). I have never used that function directly. This is mainly since I prefer to have my strings returned and not output. I put a proxy function into my bootstrap which alters the default of the second argument.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;function ___($singular, $return = true) {&lt;br /&gt;    return __($singular, $return);&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I managed to change all the calls to $lang-&gt;show('some_string') to ___('some_string') in one glorious find and replace. That's my kind of migration.&lt;br /&gt;&lt;br /&gt;The third and final change was to alter the language switching. I kept this in my bootstrap and only change it to write the configuration for the selected language. The old code is the commented lines. I kept the rest of my old code. As you can see it still uses cookies and it works just as well as before.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if (isset($_COOKIE['EFS_LANG'])) {&lt;br /&gt;    //define('EFS_LANG', $_COOKIE['EFS_LANG']);&lt;br /&gt;    Configure::write('Config.language', $_COOKIE['EFS_LANG']);&lt;br /&gt;} else {&lt;br /&gt;    //define('EFS_LANG', 'sv');&lt;br /&gt;    Configure::write('Config.language', 'sv');&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Changing all view-files to use .ctp extension&lt;br /&gt;This takes all of 5 minutes and has absolutely no effect on the functionality of the application. It just feels better and considering the work involved why not? I just ran everything in the views folder through a filename changer (NameChanger for Mac OS X) and I was done.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Changes to form and html helpers&lt;br /&gt;Any previous call to html helper to generate a form element needs to be switched over to use the form helper. This did not affect my application much. Most html did not make use of either helper. I remember feeling it was less intuitive to make php calls to generate html instead of just writing the html directly. The application does not have a lot of forms either.&lt;br /&gt;&lt;br /&gt;With the login form as an example here is some of the things to look out for in views.&lt;br /&gt;&lt;br /&gt;&lt;label for="UserLogin"&gt;&lt;?php echo $lang-&gt;show('login_username'); ?&gt;&lt;/label&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;$html-&gt;input('User/login',array(&lt;br /&gt;    'style'=&gt;"width:150px;"&lt;br /&gt;));&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;now reads:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$form-&gt;input('User.email',array(&lt;br /&gt;    'label'=&gt;___('login_username'), &lt;br /&gt;    'div' =&gt; false, &lt;br /&gt;    'style'=&gt;'width:150px;'&lt;br /&gt;)); &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This is one area where the new helpers really shine. Just setting the label property IS simpler than writing the whole tag manually. since my layout did not have divs before I simply set that key to false to avoid the default div around my text field.&lt;br /&gt;&lt;br /&gt;Also notice that $html is replaced by $form and that the reference to the model field uses the new dot-notation.&lt;br /&gt;&lt;br /&gt;I also switched to email logins, but that has nothing to do with the migration. I started out using usernames. When I created the feature to reset passwords a valid email address was necessary and the last big update changed to prefer email logins but still allowed old usernames during a transitional period. This version will deprecate the old logins once and for all.&lt;br /&gt;&lt;br /&gt;Don't render your elements&lt;br /&gt;Don't get me wrong. Keep on using your elements. It is just the name of the method has changed from renderElement() to just element(). The application was full of these but this was another one of those things that a quick find and replace could solve in minutes. I did not find any problems afterwards. The parameters appear to work the same.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Cleaning up my urls&lt;br /&gt;Besides cleaning up some of my mess in config/routes.php I did some spring-cleaning of the urls in my views and controllers. This is not strictly necessary but it may come in handy if, or when, I want to create some new custom routes. Changing all urls to arrays instead of simple strings does look like a lot of complexity with little benefit.&lt;br /&gt;&lt;br /&gt;'/users/edit' &lt;br /&gt;&lt;br /&gt;becomes:&lt;br /&gt;&lt;br /&gt;array('controller'=&gt;'users', 'action'=&gt;'edit') &lt;br /&gt;&lt;br /&gt;Clearly harder to read, right? The benefit is that I can now decide to create an "alias" in routes.php so that links to /profile should go to the edit action of the users controller. As if by magic, all links and redirects to that editing screen will change from /users/edit to /profile. Cool!&lt;br /&gt;&lt;br /&gt;Another little nice (new?) feature I found was for the classic "logo links back to start-page". Every website in the world has this and it can be done very nicely. This mess:&lt;br /&gt;&lt;br /&gt;&lt;a href="&lt;?php echo $html-&gt;url('/'); ?&gt;"&gt;&lt;?php echo $html-&gt;image('fileshifter_logo_bar.gif',array('alt'=&gt;'Fileshifter logo'))?&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;could be written like this:&lt;br /&gt;&lt;br /&gt;&lt;?php echo $html-&gt;image('fileshifter_logo_bar.gif',array('alt'=&gt;'Fileshifter logo', 'url'=&gt;'/')); ?&gt; &lt;br /&gt;&lt;br /&gt;The image method accepts an url parameter and creates a link around the image for you. It does look nice and clean. If you need some attributes set for the link you can also use the link method and just put a call to the image method where the "text label" for the link is set. See the manual, it has a clear example of it. It is a lot simpler than I make it sound.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Consolidating layouts and views.&lt;br /&gt;Some of my old view code was duplicated because I did not know all the tricks back then. For example, my layouts (three of them) were almost identical but they has a few things that set them apart.&lt;br /&gt;&lt;br /&gt;Since data for the current user is always available to the view, one simple fix was to add an if-clause that would output the correct menu-items for each situation.&lt;br /&gt;&lt;br /&gt;The other problem I had was that $content_for_layout had to be wrapped and accompanied by different code for different sections of the application. The fix is simple but not one I knew about two years ago. I made a common base-layout:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--base.ctp--&lt;br /&gt;...lots of html for menu and header...&lt;br /&gt;&lt;br /&gt;&lt;?php echo $content_for_layout; ?&gt;&lt;br /&gt;&lt;br /&gt;...some more html for the footer...&lt;br /&gt;&lt;br /&gt;And then I created two other layouts of this kind (this is the most simple one):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--default.ctp--&lt;br /&gt;&lt;?php&lt;br /&gt;echo $this-&gt;renderLayout('&lt;div id="container"&gt;'.$content_for_layout.'&lt;/div&gt;','base');&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;This layout simply wraps the content in a container div and passes it along to the base layout. The other layout had a lot more html around the content but that would be less clear to display like this.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Onwards and upwards&lt;br /&gt;Those were the steps I took to migrate and improve my application this time around. Not all of them are necessary but all of them help the application improve and conform to new conventions. For example, old string conditions still work but using the new array notation lets Cake protect you from SQL injection, makes it easier to modify conditions in behaviors and beforeFind() and other advantages big and small.&lt;br /&gt;&lt;br /&gt;If you find that any aspect of the migration is lacking in detail or plain missing, please don't hesitate to drop me a line in the comments. Hopefully I will be able to cover such requests in future updates.&lt;br /&gt;&lt;br /&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-442582711699552000?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/442582711699552000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=442582711699552000' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/442582711699552000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/442582711699552000'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/migrating-real-world-application-to.html' title='Migrating a real-world application to CakePHP 1.2'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-7087138619731093606</id><published>2008-11-21T11:54:00.000-08:00</published><updated>2008-11-21T11:56:36.772-08:00</updated><title type='text'>Debugging with FirePHP</title><content type='html'>By Heath Nail (HeathNail)&lt;br /&gt;This is a quick hack to have the debugger use FirePHP for debugging.&lt;br /&gt;&lt;br /&gt;You may have read the other article on FirePHP which deals with the query log, if not check it out here:&lt;br /&gt;http://bakery.cakephp.org/articles/view/baking-cakes-with-firephp&lt;br /&gt;&lt;br /&gt;With a little massaging of Cake's Debugger class you can have all errors logged to the Firebug console instead of having them displayed on your site.&lt;br /&gt;&lt;br /&gt;Things you'll need for this to work:&lt;br /&gt;&lt;br /&gt;    * Firefox 3 (if ya haven't already, its time to upgrade :p) http://getfirefox.com&lt;br /&gt;    * FireBug http://getfirebug.com&lt;br /&gt;    * FirePHP (the FireFox extension and the PHP class) http://firephp.org&lt;br /&gt;    * And yeah I'm assuming you already have CakePHP otherwise you wouldn't be here right?&lt;br /&gt;&lt;br /&gt;You'll need to download the FirePHP.class.php file and save it to vendors. I saved it to vendors/FirePHP/FirePHP.class.php&lt;br /&gt;&lt;br /&gt;Then save the following file to vendors/FirePHP/FirePHP.debugger.php:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;/**&lt;br /&gt; * The majority of code in this file is based on CakePHP's Debugger.&lt;br /&gt; * This code is designed to work with CakePHP 1.2RC2 and no warranty is given nor implied.&lt;br /&gt; * @link http://www.cakephp.org&lt;br /&gt; * @link http://www.firephp.org&lt;br /&gt; * @license    http://www.opensource.org/licenses/mit-license.php The MIT License&lt;br /&gt; */&lt;br /&gt;if(!class_exists('Debugger')) {&lt;br /&gt;    App::import('Core', 'Debugger');&lt;br /&gt;}&lt;br /&gt;if(!class_exists('FirePHP')) {&lt;br /&gt;    App::import('Vendor', 'FirePHP', array ( 'file' =&gt; 'FirePHP.class.php'));&lt;br /&gt;}&lt;br /&gt;if(!function_exists('fb')) {&lt;br /&gt;    function fb() {&lt;br /&gt;        $instance = FirePHP::getInstance(true);&lt;br /&gt;        $args = func_get_args();&lt;br /&gt;        return call_user_func_array(array($instance,'fb'),$args);&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;class FirePHPDebugger extends Debugger {&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * holds current output format&lt;br /&gt; *&lt;br /&gt; * @var string&lt;br /&gt; * @access private&lt;br /&gt; */&lt;br /&gt;    var $__outputFormat = 'fb';&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * FirePHP error level&lt;br /&gt; *&lt;br /&gt; * @var string&lt;br /&gt; * @access public&lt;br /&gt; */&lt;br /&gt;    var $FirePHPLevel = '';&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Gets a reference to the Debugger object instance&lt;br /&gt; *&lt;br /&gt; * @return object&lt;br /&gt; * @access public&lt;br /&gt; */&lt;br /&gt;    function &amp;getInstance() {&lt;br /&gt;        static $instance = array();&lt;br /&gt;&lt;br /&gt;        if (!isset($instance[0]) || !$instance[0]) {&lt;br /&gt;            $instance[0] =&amp; new FirePHPDebugger();&lt;br /&gt;            if (Configure::read() &gt; 0) {&lt;br /&gt;                Configure::version(); // Make sure the core config is loaded&lt;br /&gt;                $instance[0]-&gt;helpPath = Configure::read('Cake.Debugger.HelpPath');&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return $instance[0];&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Overrides PHP's default error handling&lt;br /&gt; *&lt;br /&gt; * @param integer $code Code of error&lt;br /&gt; * @param string $description Error description&lt;br /&gt; * @param string $file File on which error occurred&lt;br /&gt; * @param integer $line Line that triggered the error&lt;br /&gt; * @param array $context Context&lt;br /&gt; * @return boolean true if error was handled&lt;br /&gt; * @access public&lt;br /&gt; */&lt;br /&gt;    function handleError($code, $description, $file = null, $line = null, $context = null) {&lt;br /&gt;        if (error_reporting() == 0 || $code === 2048) {&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        $_this = FirePHPDebugger::getInstance();&lt;br /&gt;&lt;br /&gt;        if (empty($file)) {&lt;br /&gt;            $file = '[internal]';&lt;br /&gt;        }&lt;br /&gt;        if (empty($line)) {&lt;br /&gt;            $line = '??';&lt;br /&gt;        }&lt;br /&gt;        $file = $_this-&gt;trimPath($file);&lt;br /&gt;&lt;br /&gt;        $info = compact('code', 'description', 'file', 'line');&lt;br /&gt;        if (!in_array($info, $_this-&gt;errors)) {&lt;br /&gt;            $_this-&gt;errors[] = $info;&lt;br /&gt;        } else {&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        $level = LOG_DEBUG;&lt;br /&gt;        switch ($code) {&lt;br /&gt;            case E_PARSE:&lt;br /&gt;            case E_ERROR:&lt;br /&gt;            case E_CORE_ERROR:&lt;br /&gt;            case E_COMPILE_ERROR:&lt;br /&gt;            case E_USER_ERROR:&lt;br /&gt;                $error = 'Fatal Error';&lt;br /&gt;                $level = LOG_ERROR;&lt;br /&gt;                $this-&gt;FirePHPLevel = FirePHP::ERROR;&lt;br /&gt;            break;&lt;br /&gt;            case E_WARNING:&lt;br /&gt;            case E_USER_WARNING:&lt;br /&gt;            case E_COMPILE_WARNING:&lt;br /&gt;            case E_RECOVERABLE_ERROR:&lt;br /&gt;                $error = 'Warning';&lt;br /&gt;                $level = LOG_WARNING;&lt;br /&gt;                $this-&gt;FirePHPLevel = FirePHP::WARN;&lt;br /&gt;            break;&lt;br /&gt;            case E_NOTICE:&lt;br /&gt;            case E_USER_NOTICE:&lt;br /&gt;                $error = 'Notice';&lt;br /&gt;                $level = LOG_NOTICE;&lt;br /&gt;                $this-&gt;FirePHPLevel = FirePHP::INFO;&lt;br /&gt;            break;&lt;br /&gt;            default:&lt;br /&gt;                return false;&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        $helpCode = null;&lt;br /&gt;        if (!empty($_this-&gt;helpPath) &amp;&amp; preg_match('/.*\[([0-9]+)\]$/', $description, $codes)) {&lt;br /&gt;            if (isset($codes[1])) {&lt;br /&gt;                $helpCode = $codes[1];&lt;br /&gt;                $description = trim(preg_replace('/\[[0-9]+\]$/', '', $description));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        echo $_this-&gt;__output($level, $error, $code, $helpCode, $description, $file, $line, $context);&lt;br /&gt;&lt;br /&gt;        if (Configure::read('log')) {&lt;br /&gt;            CakeLog::write($level, "{$error} ({$code}): {$description} in [{$file}, line {$line}]");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if ($error == 'Fatal Error') {&lt;br /&gt;            die();&lt;br /&gt;        }&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Handles object conversion to debug string&lt;br /&gt; *&lt;br /&gt; * @param string $var Object to convert&lt;br /&gt; * @access private&lt;br /&gt; */&lt;br /&gt;    function __output($level, $error, $code, $helpCode, $description, $file, $line, $kontext) {&lt;br /&gt;        $_this = FirePHPDebugger::getInstance();&lt;br /&gt;        if($_this-&gt;__outputFormat !== 'fb') {&lt;br /&gt;            return Debugger::__output($level, $error, $code, $helpCode, $description, $file, $line, $kontext);&lt;br /&gt;        }&lt;br /&gt;        $files = $_this-&gt;trace(array('start' =&gt; 2, 'format' =&gt; 'points'));&lt;br /&gt;        $listing = $_this-&gt;fbFormat($_this-&gt;excerpt($files[0]['file'], $files[0]['line'] - 1, 1));&lt;br /&gt;        $trace = $_this-&gt;fbFormat($_this-&gt;trace(array('start' =&gt; 2, 'depth' =&gt; '20')));&lt;br /&gt;        $context = '&lt;br /&gt;';&lt;br /&gt;        foreach ((array)$kontext as $var =&gt; $value) {&lt;br /&gt;            $context.= "\${$var} = " . $_this-&gt;exportVar($value, 1)."\n";&lt;br /&gt;        }&lt;br /&gt;        $context = $_this-&gt;fbFormat($context);&lt;br /&gt;        $instance = FirePHP::getInstance(true);&lt;br /&gt;        $message = "{$error} ({$code}): {$description} [{$file}, line {$line}";&lt;br /&gt;        $out = array(&lt;br /&gt;            'trace' =&gt; $trace,&lt;br /&gt;            'code' =&gt; $listing,&lt;br /&gt;            'context' =&gt; $context,&lt;br /&gt;        );&lt;br /&gt;        call_user_func_array(array($instance,'fb'),array($out, $message,  $this-&gt;FirePHPLevel));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Function to format data to look purdy in FireBug&lt;br /&gt; *&lt;br /&gt; * @param mixed $data Data to be formatted for FireBug&lt;br /&gt; * @return string Formatted FireBug data&lt;br /&gt; */&lt;br /&gt;    function fbFormat($data = '') {&lt;br /&gt;        if(is_array($data)) {&lt;br /&gt;            $data = join($data);&lt;br /&gt;        }&lt;br /&gt;        $data = strip_tags($data);&lt;br /&gt;        $data = '&lt;br /&gt; ' . str_ireplace("\t", '&amp;nbsp;&amp;nbsp;', str_ireplace("\n", '&lt;br /&gt;', $data)) . '&lt;br /&gt;';&lt;br /&gt;        return $data;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) {&lt;br /&gt;    FirePHPDebugger::invoke(FirePHPDebugger::getInstance());&lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;Now add the following line to app/config/bootstrap.php:&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;App::import('Vendor', 'FirePHPDebugger', array('file' =&gt; 'FirePHP' . DS . 'FirePHP.debugger.php'));&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;When an error occurs (and debug &gt; 0) you'll see something like this in your FireBug console:&lt;br /&gt;&lt;br /&gt;http://yoursite.com&lt;br /&gt;["Notice (1024): Foo [APP\config\bootstrap.php, line 46", Array(3)] &lt;br /&gt;&lt;br /&gt;Hover over the "Array(3)" and you'll see a new window open with the Trace, Code, and Context info.&lt;br /&gt;&lt;br /&gt;I haven't tested this code thoroughly, so if you have an issue leave a comment here and we can work it out.&lt;br /&gt;&lt;br /&gt;Happy Baking!&lt;br /&gt;Heath&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-7087138619731093606?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/7087138619731093606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=7087138619731093606' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7087138619731093606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7087138619731093606'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/11/debugging-with-firephp.html' title='Debugging with FirePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-6317700887150938791</id><published>2008-04-11T18:55:00.001-07:00</published><updated>2008-09-08T06:15:58.192-07:00</updated><title type='text'>Mem Cached Component</title><content type='html'>&lt;strong&gt;Mem Cached Component&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Component:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is mem cached component for cakePHP. Please create a component as mem_cache.php in the componet folder .&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;/**&lt;br /&gt; * Wrapper for Memcache, v. 0.1&lt;br /&gt; *&lt;br /&gt; * By Jiri Kupiainen (http://jirikupiainen.com/)&lt;br /&gt; *&lt;br /&gt; * You are free to do whatever you please with this code. Enjoy.&lt;br /&gt; */&lt;br /&gt;define('CACHE_LITE_ERROR_RETURN', 1);&lt;br /&gt;define('CACHE_LITE_ERROR_DIE', 8);&lt;br /&gt;//$memcache_obj = memcache_connect(array('XX.XXX.XX.XX','XX.XXX.XX.XX'), 11211);&lt;br /&gt;class MemCacheComponent extends Object {&lt;br /&gt;      // --- Private properties ---&lt;br /&gt;    /**&lt;br /&gt;    * Directory where to put the cache files&lt;br /&gt;    * (make sure to add a trailing slash)&lt;br /&gt;    *&lt;br /&gt;    * @var string $_cacheDir&lt;br /&gt;    */&lt;br /&gt;    var $_cacheDir = '/tmp/';&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Enable / disable caching&lt;br /&gt;    *&lt;br /&gt;    * (can be very usefull for the debug of cached scripts)&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_caching&lt;br /&gt;    */&lt;br /&gt;    var $_caching = true;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Cache lifetime (in seconds)&lt;br /&gt;    *&lt;br /&gt;    * If null, the cache is valid forever.&lt;br /&gt;    *&lt;br /&gt;    * @var int $_lifeTime&lt;br /&gt;    */&lt;br /&gt;    var $_lifeTime = 3600;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Enable / disable fileLocking&lt;br /&gt;    *&lt;br /&gt;    * (can avoid cache corruption under bad circumstances)&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_fileLocking&lt;br /&gt;    */&lt;br /&gt;    var $_fileLocking = true;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Timestamp of the last valid cache&lt;br /&gt;    *&lt;br /&gt;    * @var int $_refreshTime&lt;br /&gt;    */&lt;br /&gt;    var $_refreshTime;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * File name (with path)&lt;br /&gt;    *&lt;br /&gt;    * @var string $_file&lt;br /&gt;    */&lt;br /&gt;    var $_file;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * File name (without path)&lt;br /&gt;    *&lt;br /&gt;    * @var string $_fileName&lt;br /&gt;    */&lt;br /&gt;    var $_fileName;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Enable / disable write control (the cache is read just after writing to detect corrupt entries)&lt;br /&gt;    *&lt;br /&gt;    * Enable write control will lightly slow the cache writing but not the cache reading&lt;br /&gt;    * Write control can detect some corrupt cache files but maybe it's not a perfect control&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_writeControl&lt;br /&gt;    */&lt;br /&gt;    var $_writeControl = true;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Enable / disable read control&lt;br /&gt;    *&lt;br /&gt;    * If enabled, a control key is embeded in cache file and this key is compared with the one&lt;br /&gt;    * calculated after the reading.&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_writeControl&lt;br /&gt;    */&lt;br /&gt;    var $_readControl = true;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Type of read control (only if read control is enabled)&lt;br /&gt;    *&lt;br /&gt;    * Available values are :&lt;br /&gt;    * 'md5' for a md5 hash control (best but slowest)&lt;br /&gt;    * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)&lt;br /&gt;    * 'strlen' for a length only test (fastest)&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_readControlType&lt;br /&gt;    */&lt;br /&gt;    var $_readControlType = 'crc32';&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Pear error mode (when raiseError is called)&lt;br /&gt;    *&lt;br /&gt;    * (see PEAR doc)&lt;br /&gt;    *&lt;br /&gt;    * @see setToDebug()&lt;br /&gt;    * @var int $_pearErrorMode&lt;br /&gt;    */&lt;br /&gt;    var $_pearErrorMode = CACHE_LITE_ERROR_RETURN;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Current cache id&lt;br /&gt;    *&lt;br /&gt;    * @var string $_id&lt;br /&gt;    */&lt;br /&gt;    var $_id;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Current cache group&lt;br /&gt;    *&lt;br /&gt;    * @var string $_group&lt;br /&gt;    */&lt;br /&gt;    var $_group;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Enable / Disable "Memory Caching"&lt;br /&gt;    *&lt;br /&gt;    * NB : There is no lifetime for memory caching ! &lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_memoryCaching&lt;br /&gt;    */&lt;br /&gt;    var $_memoryCaching = false;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Enable / Disable "Only Memory Caching"&lt;br /&gt;    * (be carefull, memory caching is "beta quality")&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_onlyMemoryCaching&lt;br /&gt;    */&lt;br /&gt;    var $_onlyMemoryCaching = false;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Memory caching array&lt;br /&gt;    *&lt;br /&gt;    * @var array $_memoryCachingArray&lt;br /&gt;    */&lt;br /&gt;    var $_memoryCachingArray = array();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Memory caching counter&lt;br /&gt;    *&lt;br /&gt;    * @var int $memoryCachingCounter&lt;br /&gt;    */&lt;br /&gt;    var $_memoryCachingCounter = 0;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Memory caching limit&lt;br /&gt;    *&lt;br /&gt;    * @var int $memoryCachingLimit&lt;br /&gt;    */&lt;br /&gt;    var $_memoryCachingLimit = 1000;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * File Name protection&lt;br /&gt;    *&lt;br /&gt;    * if set to true, you can use any cache id or group name&lt;br /&gt;    * if set to false, it can be faster but cache ids and group names&lt;br /&gt;    * will be used directly in cache file names so be carefull with&lt;br /&gt;    * special characters...&lt;br /&gt;    *&lt;br /&gt;    * @var boolean $fileNameProtection&lt;br /&gt;    */&lt;br /&gt;    var $_fileNameProtection = true;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Enable / disable automatic serialization&lt;br /&gt;    *&lt;br /&gt;    * it can be used to save directly datas which aren't strings&lt;br /&gt;    * (but it's slower)    &lt;br /&gt;    *&lt;br /&gt;    * @var boolean $_serialize&lt;br /&gt;    */&lt;br /&gt;    var $_automaticSerialization = false;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Disable / Tune the automatic cleaning process&lt;br /&gt;    *&lt;br /&gt;    * The automatic cleaning process destroy too old (for the given life time)&lt;br /&gt;    * cache files when a new cache file is written.&lt;br /&gt;    * 0               =&gt; no automatic cache cleaning&lt;br /&gt;    * 1               =&gt; systematic cache cleaning&lt;br /&gt;    * x (integer) &gt; 1 =&gt; automatic cleaning randomly 1 times on x cache write&lt;br /&gt;    *&lt;br /&gt;    * @var int $_automaticCleaning&lt;br /&gt;    */&lt;br /&gt;    var $_automaticCleaningFactor = 0;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Nested directory level&lt;br /&gt;    *&lt;br /&gt;    * Set the hashed directory structure level. 0 means "no hashed directory &lt;br /&gt;    * structure", 1 means "one level of directory", 2 means "two levels"... &lt;br /&gt;    * This option can speed up Cache_Lite only when you have many thousands of &lt;br /&gt;    * cache file. Only specific benchs can help you to choose the perfect value &lt;br /&gt;    * for you. Maybe, 1 or 2 is a good start.&lt;br /&gt;    *&lt;br /&gt;    * @var int $_hashedDirectoryLevel&lt;br /&gt;    */&lt;br /&gt;    var $_hashedDirectoryLevel = 0;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Umask for hashed directory structure&lt;br /&gt;    *&lt;br /&gt;    * @var int $_hashedDirectoryUmask&lt;br /&gt;    */&lt;br /&gt;    var $_hashedDirectoryUmask = 0700;&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * API break for error handling in CACHE_LITE_ERROR_RETURN mode&lt;br /&gt;     * &lt;br /&gt;     * In CACHE_LITE_ERROR_RETURN mode, error handling was not good because&lt;br /&gt;     * for example save() method always returned a boolean (a PEAR_Error object&lt;br /&gt;     * would be better in CACHE_LITE_ERROR_RETURN mode). To correct this without&lt;br /&gt;     * breaking the API, this option (false by default) can change this handling.&lt;br /&gt;     * &lt;br /&gt;     * @var boolean&lt;br /&gt;     */&lt;br /&gt;    var $_errorHandlingAPIBreak = false;&lt;br /&gt;    &lt;br /&gt;    // --- Public methods ---&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Constructor&lt;br /&gt;    *&lt;br /&gt;    * $options is an assoc. Available options are :&lt;br /&gt;    * $options = array(&lt;br /&gt;    *     'cacheDir' =&gt; directory where to put the cache files (string),&lt;br /&gt;    *     'caching' =&gt; enable / disable caching (boolean),&lt;br /&gt;    *     'lifeTime' =&gt; cache lifetime in seconds (int),&lt;br /&gt;    *     'fileLocking' =&gt; enable / disable fileLocking (boolean),&lt;br /&gt;    *     'writeControl' =&gt; enable / disable write control (boolean),&lt;br /&gt;    *     'readControl' =&gt; enable / disable read control (boolean),&lt;br /&gt;    *     'readControlType' =&gt; type of read control 'crc32', 'md5', 'strlen' (string),&lt;br /&gt;    *     'pearErrorMode' =&gt; pear error mode (when raiseError is called) (cf PEAR doc) (int),&lt;br /&gt;    *     'memoryCaching' =&gt; enable / disable memory caching (boolean),&lt;br /&gt;    *     'onlyMemoryCaching' =&gt; enable / disable only memory caching (boolean),&lt;br /&gt;    *     'memoryCachingLimit' =&gt; max nbr of records to store into memory caching (int),&lt;br /&gt;    *     'fileNameProtection' =&gt; enable / disable automatic file name protection (boolean),&lt;br /&gt;    *     'automaticSerialization' =&gt; enable / disable automatic serialization (boolean),&lt;br /&gt;    *     'automaticCleaningFactor' =&gt; distable / tune automatic cleaning process (int),&lt;br /&gt;    *     'hashedDirectoryLevel' =&gt; level of the hashed directory system (int),&lt;br /&gt;    *     'hashedDirectoryUmask' =&gt; umask for hashed directory structure (int),&lt;br /&gt;    *     'errorHandlingAPIBreak' =&gt; API break for better error handling ? (boolean)&lt;br /&gt;    * );&lt;br /&gt;    *&lt;br /&gt;    * @param array $options options&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function Cache_Lite($options = array(NULL))&lt;br /&gt;    {&lt;br /&gt;        foreach($options as $key =&gt; $value) {&lt;br /&gt;             $this-&gt;setOption($key, $value);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    /**&lt;br /&gt;    * Generic way to set a Cache_Lite option&lt;br /&gt;    *&lt;br /&gt;    * see Cache_Lite constructor for available options&lt;br /&gt;    *&lt;br /&gt;    * @var string $name name of the option&lt;br /&gt;    * @var mixed $value value of the option&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function setOption($name, $value) &lt;br /&gt;    {&lt;br /&gt;        $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode');&lt;br /&gt;        if (in_array($name, $availableOptions)) {&lt;br /&gt;            $property = '_'.$name;&lt;br /&gt;            $this-&gt;$property = $value;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    /**&lt;br /&gt;    * Test if a cache is available and (if yes) return it&lt;br /&gt;    *&lt;br /&gt;    * @param string $id cache id&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested&lt;br /&gt;    * @return string data of the cache (else : false)&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function get($id, $group = 'default', $doNotTestCacheValidity = false)&lt;br /&gt;    {&lt;br /&gt;        $this-&gt;_id = $id;&lt;br /&gt;        $this-&gt;_group = $group;&lt;br /&gt;        $data = false;&lt;br /&gt;        if ($this-&gt;_caching) {&lt;br /&gt;            $this-&gt;_setRefreshTime();&lt;br /&gt;            $this-&gt;_setFileName($id, $group);&lt;br /&gt;            clearstatcache();&lt;br /&gt;            if ($this-&gt;_memoryCaching) {&lt;br /&gt;                if (isset($this-&gt;_memoryCachingArray[$this-&gt;_file])) {&lt;br /&gt;                    if ($this-&gt;_automaticSerialization) {&lt;br /&gt;                        return unserialize($this-&gt;_memoryCachingArray[$this-&gt;_file]);&lt;br /&gt;                    }&lt;br /&gt;                    return $this-&gt;_memoryCachingArray[$this-&gt;_file];&lt;br /&gt;                }&lt;br /&gt;                if ($this-&gt;_onlyMemoryCaching) {&lt;br /&gt;                    return false;&lt;br /&gt;                }                &lt;br /&gt;            }&lt;br /&gt;            if(($doNotTestCacheValidity) || (is_null($this-&gt;_refreshTime))) {&lt;br /&gt;                if (file_exists($this-&gt;_file)) {&lt;br /&gt;                    $data = $this-&gt;_read();&lt;br /&gt;      }&lt;br /&gt;            } else {&lt;br /&gt;                if ((file_exists($this-&gt;_file)) &amp;&amp; (@filemtime($this-&gt;_file) &gt; $this-&gt;_refreshTime)) {&lt;br /&gt;                    $data = $this-&gt;_read();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            if (($data) and ($this-&gt;_memoryCaching)) {&lt;br /&gt;                $this-&gt;_memoryCacheAdd($data);&lt;br /&gt;            }&lt;br /&gt;            if (($this-&gt;_automaticSerialization) and (is_string($data))) {&lt;br /&gt;                $data = unserialize($data);&lt;br /&gt;            }&lt;br /&gt;   return $data;&lt;br /&gt;        }&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;    /**&lt;br /&gt;    * Save some data in a cache file&lt;br /&gt;    *&lt;br /&gt;    * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on)&lt;br /&gt;    * @param string $id cache id&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @return boolean true if no problem (else : false or a PEAR_Error object)&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function save($data, $id = NULL, $group = 'default')&lt;br /&gt;    {&lt;br /&gt;        if ($this-&gt;_caching) {&lt;br /&gt;            if ($this-&gt;_automaticSerialization) {&lt;br /&gt;                $data = serialize($data);&lt;br /&gt;            }&lt;br /&gt;            if (isset($id)) {&lt;br /&gt;                $this-&gt;_setFileName($id, $group);&lt;br /&gt;            }&lt;br /&gt;            if ($this-&gt;_memoryCaching) {&lt;br /&gt;                $this-&gt;_memoryCacheAdd($data);&lt;br /&gt;                if ($this-&gt;_onlyMemoryCaching) {&lt;br /&gt;                    return true;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            if ($this-&gt;_automaticCleaningFactor&gt;0) {&lt;br /&gt;                $rand = rand(1, $this-&gt;_automaticCleaningFactor);&lt;br /&gt;                if ($rand==1) {&lt;br /&gt;                    $this-&gt;clean(false, 'old');&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            if ($this-&gt;_writeControl) {&lt;br /&gt;                $res = $this-&gt;_writeAndControl($data);&lt;br /&gt;                if (is_bool($res)) {&lt;br /&gt;                    if ($res) {&lt;br /&gt;                        return true;  &lt;br /&gt;                    }&lt;br /&gt;                    // if $res if false, we need to invalidate the cache&lt;br /&gt;                    @touch($this-&gt;_file, time() - 2*abs($this-&gt;_lifeTime));&lt;br /&gt;                    return false;&lt;br /&gt;                }            &lt;br /&gt;            } else {&lt;br /&gt;                $res = $this-&gt;_write($data);&lt;br /&gt;            }&lt;br /&gt;            if (is_object($res)) {&lt;br /&gt;          // $res is a PEAR_Error object &lt;br /&gt;                if (!($this-&gt;_errorHandlingAPIBreak)) {   &lt;br /&gt;                 return false; // we return false (old API)&lt;br /&gt;             }&lt;br /&gt;         }&lt;br /&gt;            return $res;&lt;br /&gt;        }&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Remove a cache file&lt;br /&gt;    *&lt;br /&gt;    * @param string $id cache id&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @return boolean true if no problem&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function remove($id, $group = 'default')&lt;br /&gt;    {&lt;br /&gt;        $this-&gt;_setFileName($id, $group);&lt;br /&gt;        if ($this-&gt;_memoryCaching) {&lt;br /&gt;            if (isset($this-&gt;_memoryCachingArray[$this-&gt;_file])) {&lt;br /&gt;                unset($this-&gt;_memoryCachingArray[$this-&gt;_file]);&lt;br /&gt;                $this-&gt;_memoryCachingCounter = $this-&gt;_memoryCachingCounter - 1;&lt;br /&gt;            }&lt;br /&gt;            if ($this-&gt;_onlyMemoryCaching) {&lt;br /&gt;                return true;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return $this-&gt;_unlink($this-&gt;_file);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Clean the cache&lt;br /&gt;    *&lt;br /&gt;    * if no group is specified all cache files will be destroyed&lt;br /&gt;    * else only cache files of the specified group will be destroyed&lt;br /&gt;    *&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', &lt;br /&gt;    *                                        'callback_myFunction'&lt;br /&gt;    * @return boolean true if no problem&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function clean($group = false, $mode = 'ingroup')&lt;br /&gt;    {&lt;br /&gt;        return $this-&gt;_cleanDir($this-&gt;_cacheDir, $group, $mode);&lt;br /&gt;    }&lt;br /&gt;       &lt;br /&gt;    /**&lt;br /&gt;    * Set to debug mode&lt;br /&gt;    *&lt;br /&gt;    * When an error is found, the script will stop and the message will be displayed&lt;br /&gt;    * (in debug mode only). &lt;br /&gt;    *&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function setToDebug()&lt;br /&gt;    {&lt;br /&gt;        $this-&gt;setOption('pearErrorMode', CACHE_LITE_ERROR_DIE);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Set a new life time&lt;br /&gt;    *&lt;br /&gt;    * @param int $newLifeTime new life time (in seconds)&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function setLifeTime($newLifeTime)&lt;br /&gt;    {&lt;br /&gt;        $this-&gt;_lifeTime = $newLifeTime;&lt;br /&gt;        $this-&gt;_setRefreshTime();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Save the state of the caching memory array into a cache file cache&lt;br /&gt;    *&lt;br /&gt;    * @param string $id cache id&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function saveMemoryCachingState($id, $group = 'default')&lt;br /&gt;    {&lt;br /&gt;        if ($this-&gt;_caching) {&lt;br /&gt;            $array = array(&lt;br /&gt;                'counter' =&gt; $this-&gt;_memoryCachingCounter,&lt;br /&gt;                'array' =&gt; $this-&gt;_memoryCachingState&lt;br /&gt;            );&lt;br /&gt;            $data = serialize($array);&lt;br /&gt;            $this-&gt;save($data, $id, $group);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Load the state of the caching memory array from a given cache file cache&lt;br /&gt;    *&lt;br /&gt;    * @param string $id cache id&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false)&lt;br /&gt;    {&lt;br /&gt;        if ($this-&gt;_caching) {&lt;br /&gt;            if ($data = $this-&gt;get($id, $group, $doNotTestCacheValidity)) {&lt;br /&gt;                $array = unserialize($data);&lt;br /&gt;                $this-&gt;_memoryCachingCounter = $array['counter'];&lt;br /&gt;                $this-&gt;_memoryCachingArray = $array['array'];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Return the cache last modification time&lt;br /&gt;    *&lt;br /&gt;    * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !&lt;br /&gt;    *&lt;br /&gt;    * @return int last modification time&lt;br /&gt;    */&lt;br /&gt;    function lastModified() &lt;br /&gt;    {&lt;br /&gt;        return @filemtime($this-&gt;_file);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Trigger a PEAR error&lt;br /&gt;    *&lt;br /&gt;    * To improve performances, the PEAR.php file is included dynamically.&lt;br /&gt;    * The file is so included only when an error is triggered. So, in most&lt;br /&gt;    * cases, the file isn't included and perfs are much better.&lt;br /&gt;    *&lt;br /&gt;    * @param string $msg error message&lt;br /&gt;    * @param int $code error code&lt;br /&gt;    * @access public&lt;br /&gt;    */&lt;br /&gt;    function raiseError($msg, $code)&lt;br /&gt;    {&lt;br /&gt;        include_once('PEAR.php');&lt;br /&gt;        return PEAR::raiseError($msg, $code, $this-&gt;_pearErrorMode);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * Extend the life of a valid cache file&lt;br /&gt;     * &lt;br /&gt;     * see http://pear.php.net/bugs/bug.php?id=6681&lt;br /&gt;     * &lt;br /&gt;     * @access public&lt;br /&gt;     */&lt;br /&gt;    function extendLife()&lt;br /&gt;    {&lt;br /&gt;        @touch($this-&gt;_file);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // --- Private methods ---&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Compute &amp; set the refresh time&lt;br /&gt;    *&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _setRefreshTime() &lt;br /&gt;    {&lt;br /&gt;        if (is_null($this-&gt;_lifeTime)) {&lt;br /&gt;            $this-&gt;_refreshTime = null;&lt;br /&gt;        } else {&lt;br /&gt;            $this-&gt;_refreshTime = time() - $this-&gt;_lifeTime;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Remove a file&lt;br /&gt;    * &lt;br /&gt;    * @param string $file complete file path and name&lt;br /&gt;    * @return boolean true if no problem&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _unlink($file)&lt;br /&gt;    {&lt;br /&gt;        if (!@unlink($file)) {&lt;br /&gt;            return $this-&gt;raiseError('Cache_Lite : Unable to remove cache !', -3);&lt;br /&gt;        }&lt;br /&gt;        return true;        &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Recursive function for cleaning cache file in the given directory&lt;br /&gt;    *&lt;br /&gt;    * @param string $dir directory complete path (with a trailing slash)&lt;br /&gt;    * @param string $group name of the cache group&lt;br /&gt;    * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup',&lt;br /&gt;                                             'callback_myFunction'&lt;br /&gt;    * @return boolean true if no problem&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _cleanDir($dir, $group = false, $mode = 'ingroup')     &lt;br /&gt;    {&lt;br /&gt;        if ($this-&gt;_fileNameProtection) {&lt;br /&gt;            $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_';&lt;br /&gt;        } else {&lt;br /&gt;            $motif = ($group) ? 'cache_'.$group.'_' : 'cache_';&lt;br /&gt;        }&lt;br /&gt;        if ($this-&gt;_memoryCaching) {&lt;br /&gt;            while (list($key, ) = each($this-&gt;_memoryCachingArray)) {&lt;br /&gt;                if (strpos($key, $motif, 0)) {&lt;br /&gt;                    unset($this-&gt;_memoryCachingArray[$key]);&lt;br /&gt;                    $this-&gt;_memoryCachingCounter = $this-&gt;_memoryCachingCounter - 1;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            if ($this-&gt;_onlyMemoryCaching) {&lt;br /&gt;                return true;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        if (!($dh = opendir($dir))) {&lt;br /&gt;            return $this-&gt;raiseError('Cache_Lite : Unable to open cache directory !', -4);&lt;br /&gt;        }&lt;br /&gt;        $result = true;&lt;br /&gt;        while ($file = readdir($dh)) {&lt;br /&gt;            if (($file != '.') &amp;&amp; ($file != '..')) {&lt;br /&gt;                if (substr($file, 0, 6)=='cache_') {&lt;br /&gt;                    $file2 = $dir . $file;&lt;br /&gt;                    if (is_file($file2)) {&lt;br /&gt;                        switch (substr($mode, 0, 9)) {&lt;br /&gt;                            case 'old':&lt;br /&gt;                                // files older than lifeTime get deleted from cache&lt;br /&gt;                                if (!is_null($this-&gt;_lifeTime)) {&lt;br /&gt;                                    if ((mktime() - @filemtime($file2)) &gt; $this-&gt;_lifeTime) {&lt;br /&gt;                                        $result = ($result and ($this-&gt;_unlink($file2)));&lt;br /&gt;                                    }&lt;br /&gt;                                }&lt;br /&gt;                                break;&lt;br /&gt;                            case 'notingrou':&lt;br /&gt;                                if (!strpos($file2, $motif, 0)) {&lt;br /&gt;                                    $result = ($result and ($this-&gt;_unlink($file2)));&lt;br /&gt;                                }&lt;br /&gt;                                break;&lt;br /&gt;                            case 'callback_':&lt;br /&gt;                                $func = substr($mode, 9, strlen($mode) - 9);&lt;br /&gt;                                if ($func($file2, $group)) {&lt;br /&gt;                                    $result = ($result and ($this-&gt;_unlink($file2)));&lt;br /&gt;                                }&lt;br /&gt;                                break;&lt;br /&gt;                            case 'ingroup':&lt;br /&gt;                            default:&lt;br /&gt;                                if (strpos($file2, $motif, 0)) {&lt;br /&gt;                                    $result = ($result and ($this-&gt;_unlink($file2)));&lt;br /&gt;                                }&lt;br /&gt;                                break;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                    if((is_dir($file2)) and ($this-&gt;_hashedDirectoryLevel&gt;0)) {&lt;br /&gt;                        $result = ($result and ($this-&gt;_cleanDir($file2 . '/', $group, $mode)));&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return $result;&lt;br /&gt;    }&lt;br /&gt;      &lt;br /&gt;    /**&lt;br /&gt;    * Add some date in the memory caching array&lt;br /&gt;    *&lt;br /&gt;    * @param string $data data to cache&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _memoryCacheAdd($data)&lt;br /&gt;    {&lt;br /&gt;        $this-&gt;_memoryCachingArray[$this-&gt;_file] = $data;&lt;br /&gt;        if ($this-&gt;_memoryCachingCounter &gt;= $this-&gt;_memoryCachingLimit) {&lt;br /&gt;            list($key, ) = each($this-&gt;_memoryCachingArray);&lt;br /&gt;            unset($this-&gt;_memoryCachingArray[$key]);&lt;br /&gt;        } else {&lt;br /&gt;            $this-&gt;_memoryCachingCounter = $this-&gt;_memoryCachingCounter + 1;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;    * Make a file name (with path)&lt;br /&gt;    *&lt;br /&gt;    * @param string $id cache id&lt;br /&gt;    * @param string $group name of the group&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _setFileName($id, $group)&lt;br /&gt;    {&lt;br /&gt;        &lt;br /&gt;        if ($this-&gt;_fileNameProtection) {&lt;br /&gt;            $suffix = 'cache_'.md5($group).'_'.md5($id);&lt;br /&gt;        } else {&lt;br /&gt;            $suffix = 'cache_'.$group.'_'.$id;&lt;br /&gt;        }&lt;br /&gt;        $root = $this-&gt;_cacheDir;&lt;br /&gt;        if ($this-&gt;_hashedDirectoryLevel&gt;0) {&lt;br /&gt;            $hash = md5($suffix);&lt;br /&gt;            for ($i=0 ; $i&lt;$this-&gt;_hashedDirectoryLevel ; $i++) {&lt;br /&gt;                $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';&lt;br /&gt;            }   &lt;br /&gt;        }&lt;br /&gt;        $this-&gt;_fileName = $suffix;&lt;br /&gt;        $this-&gt;_file = $root.$suffix;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Read the cache file and return the content&lt;br /&gt;    *&lt;br /&gt;    * @return string content of the cache file (else : false or a PEAR_Error object)&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _read()&lt;br /&gt;    {&lt;br /&gt;        $fp = @fopen($this-&gt;_file, "rb");&lt;br /&gt;        if ($this-&gt;_fileLocking) @flock($fp, LOCK_SH);&lt;br /&gt;        if ($fp) {&lt;br /&gt;            clearstatcache();&lt;br /&gt;            $length = @filesize($this-&gt;_file);&lt;br /&gt;            $mqr = get_magic_quotes_runtime();&lt;br /&gt;            set_magic_quotes_runtime(0);&lt;br /&gt;            if ($this-&gt;_readControl) {&lt;br /&gt;                $hashControl = @fread($fp, 32);&lt;br /&gt;                $length = $length - 32;&lt;br /&gt;            } &lt;br /&gt;            if ($length) {&lt;br /&gt;                $data = @fread($fp, $length);&lt;br /&gt;            } else {&lt;br /&gt;                $data = '';&lt;br /&gt;            }&lt;br /&gt;            set_magic_quotes_runtime($mqr);&lt;br /&gt;            if ($this-&gt;_fileLocking) @flock($fp, LOCK_UN);&lt;br /&gt;            @fclose($fp);&lt;br /&gt;            if ($this-&gt;_readControl) {&lt;br /&gt;                $hashData = $this-&gt;_hash($data, $this-&gt;_readControlType);&lt;br /&gt;                if ($hashData != $hashControl) {&lt;br /&gt;                    if (!(is_null($this-&gt;_lifeTime))) {&lt;br /&gt;                        @touch($this-&gt;_file, time() - 2*abs($this-&gt;_lifeTime)); &lt;br /&gt;                    } else {&lt;br /&gt;                        @unlink($this-&gt;_file);&lt;br /&gt;                    }&lt;br /&gt;                    return false;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            return $data;&lt;br /&gt;        }&lt;br /&gt;        return $this-&gt;raiseError('Cache_Lite : Unable to read cache !', -2); &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Write the given data in the cache file&lt;br /&gt;    *&lt;br /&gt;    * @param string $data data to put in cache&lt;br /&gt;    * @return boolean true if ok (a PEAR_Error object else)&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _write($data)&lt;br /&gt;    {&lt;br /&gt;        if ($this-&gt;_hashedDirectoryLevel &gt; 0) {&lt;br /&gt;            $hash = md5($this-&gt;_fileName);&lt;br /&gt;            $root = $this-&gt;_cacheDir;&lt;br /&gt;            for ($i=0 ; $i&lt;$this-&gt;_hashedDirectoryLevel ; $i++) {&lt;br /&gt;                $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';&lt;br /&gt;                if (!(@is_dir($root))) {&lt;br /&gt;                    @mkdir($root, $this-&gt;_hashedDirectoryUmask);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        $fp = @fopen($this-&gt;_file, "wb");&lt;br /&gt;        if ($fp) {&lt;br /&gt;            if ($this-&gt;_fileLocking) @flock($fp, LOCK_EX);&lt;br /&gt;            if ($this-&gt;_readControl) {&lt;br /&gt;                @fwrite($fp, $this-&gt;_hash($data, $this-&gt;_readControlType), 32);&lt;br /&gt;            }&lt;br /&gt;            $len = strlen($data);&lt;br /&gt;            @fwrite($fp, $data, $len);&lt;br /&gt;            if ($this-&gt;_fileLocking) @flock($fp, LOCK_UN);&lt;br /&gt;            @fclose($fp);&lt;br /&gt;            return true;&lt;br /&gt;        }      &lt;br /&gt;        return $this-&gt;raiseError('Cache_Lite : Unable to write cache file : '.$this-&gt;_file, -1);&lt;br /&gt;    }&lt;br /&gt;       &lt;br /&gt;    /**&lt;br /&gt;    * Write the given data in the cache file and control it just after to avoir corrupted cache entries&lt;br /&gt;    *&lt;br /&gt;    * @param string $data data to put in cache&lt;br /&gt;    * @return boolean true if the test is ok (else : false or a PEAR_Error object)&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _writeAndControl($data)&lt;br /&gt;    {&lt;br /&gt;        $result = $this-&gt;_write($data);&lt;br /&gt;        if (is_object($result)) {&lt;br /&gt;            return $result; # We return the PEAR_Error object&lt;br /&gt;        }&lt;br /&gt;        $dataRead = $this-&gt;_read();&lt;br /&gt;        if (is_object($dataRead)) {&lt;br /&gt;            return $result; # We return the PEAR_Error object&lt;br /&gt;        }&lt;br /&gt;        if ((is_bool($dataRead)) &amp;&amp; (!$dataRead)) {&lt;br /&gt;            return false; &lt;br /&gt;        }&lt;br /&gt;        return ($dataRead==$data);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;    * Make a control key with the string containing datas&lt;br /&gt;    *&lt;br /&gt;    * @param string $data data&lt;br /&gt;    * @param string $controlType type of control 'md5', 'crc32' or 'strlen'&lt;br /&gt;    * @return string control key&lt;br /&gt;    * @access private&lt;br /&gt;    */&lt;br /&gt;    function _hash($data, $controlType)&lt;br /&gt;    {&lt;br /&gt;        switch ($controlType) {&lt;br /&gt;        case 'md5':&lt;br /&gt;            return md5($data);&lt;br /&gt;        case 'crc32':&lt;br /&gt;            return sprintf('% 32d', crc32($data));&lt;br /&gt;        case 'strlen':&lt;br /&gt;            return sprintf('% 32d', strlen($data));&lt;br /&gt;        default:&lt;br /&gt;            return $this-&gt;raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Controller : &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;var $components = array ('MemCache');&lt;br /&gt;var $ENABLE_CACHE =1;&lt;br /&gt;var $ENABLE_CACHE_LOGGING =0;&lt;br /&gt;function name()&lt;br /&gt;{&lt;br /&gt;  $memcache = new Memcache; &lt;br /&gt;  $memcache-&gt;connect('localhost', 11211) or die ("Could not connect");&lt;br /&gt;  $memcache-&gt;addServer('64.237.62.50', 11211);&lt;br /&gt;  $memcache-&gt;addServer('64.237.62.51', 11211);&lt;br /&gt;  $this-&gt;Cache_Lite = array('cacheDir'=&gt;$_SERVER['DOCUMENT_ROOT'].'/app/tmp', 'lifeTime'=&gt;3600,'caching'=&gt;'enable');&lt;br /&gt;&lt;br /&gt;// code here&lt;br /&gt;$cache_id = "_videolisting";&lt;br /&gt;$this-&gt;MemCache-&gt;save(serialize($Userinfo),$cache_id,'Video');&lt;br /&gt;if($this-&gt;ENABLE_CACHE==1)&lt;br /&gt;{&lt;br /&gt; if($cdat = $this-&gt;MemCache-&gt;get($cache_id,'Video'))&lt;br /&gt; {&lt;br /&gt;  $cdat = unserialize($cdat);&lt;br /&gt;  $this-&gt;set('list',$list);&lt;br /&gt; }&lt;br /&gt;}else{&lt;br /&gt;   $this-&gt;set('list',$list);&lt;br /&gt; }&lt;br /&gt;  &lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-6317700887150938791?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/6317700887150938791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=6317700887150938791' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6317700887150938791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6317700887150938791'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/04/mem-cached-component.html' title='Mem Cached Component'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-7902258434086838635</id><published>2008-04-05T00:14:00.001-07:00</published><updated>2008-04-05T00:18:15.904-07:00</updated><title type='text'>cakePHP Download Beta Version 1.2.0.6311-beta</title><content type='html'>&lt;a target="_blank" href="http://cakeforge.org/frs/download.php/593/cake_1.2.0.6311-beta.zip/donation=complete"&gt; Download Latest Release&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-7902258434086838635?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/7902258434086838635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=7902258434086838635' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7902258434086838635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7902258434086838635'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/04/cakephp-download-beta-version-1206311.html' title='cakePHP Download Beta Version 1.2.0.6311-beta'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-7027124524342209587</id><published>2008-04-05T00:10:00.000-07:00</published><updated>2008-04-05T00:13:33.912-07:00</updated><title type='text'>cakePHP Download Stable Version 1.1.19.6305</title><content type='html'>&lt;a href="http://cakeforge.org/frs/download.php/590/cake_1.1.19.6305.zip/donation=complete" target="_blank"&gt;Download Stable Version of cakePHP Version&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-7027124524342209587?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/7027124524342209587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=7027124524342209587' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7027124524342209587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/7027124524342209587'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/04/cakephp-download-stable-version.html' title='cakePHP Download Stable Version 1.1.19.6305'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-2663342026196161591</id><published>2008-04-03T17:39:00.000-07:00</published><updated>2008-04-03T17:44:34.725-07:00</updated><title type='text'>cakePHP : Pagination</title><content type='html'>If part of your application includes displaying lots of results, it's a good idea to give the user the possibility to view the results in digestable chunks and possibly to be able to sort the presented data. This tutorial will explain how, after copying a few files into your application, you can achieve this in very few lines of code.&lt;br /&gt;You need almost no knowledge of cake to be able to make use of this tutorial :).&lt;br /&gt;&lt;br /&gt;If you already have a table in mind that you want to add pagination to, read on; otherwise run through http://manual.cakephp.org/appendix/blog_tutorial to have some code to play with.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Setting Up&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All of the files necessary are available here in the bakery.&lt;br /&gt;&lt;br /&gt;Save this file http://bakery.cakephp.org/articles/view/67 as /app/controllers/components/pagination.php&lt;br /&gt;&lt;br /&gt;Save this file http://bakery.cakephp.org/articles/view/68 as /app/views/helpers/pagination.php&lt;br /&gt;&lt;br /&gt;Save this file http://bakery.cakephp.org/articles/view/69 as /app/views/elements/pagination.thtml&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Create/modify the Controller&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The only change necessary to use pagination is to include the component, the helper and call the component method "init" before the relavent find.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Controller Class:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;class PostsController extends AppController&lt;br /&gt;{&lt;br /&gt;    var $name = 'Posts'; // for PHP4 installs&lt;br /&gt;    var $components = array ('Pagination'); // Added&lt;br /&gt;    var $helpers = array('Pagination'); // Added&lt;br /&gt;&lt;br /&gt;    function index() {    &lt;br /&gt;        $criteria=NULL;&lt;br /&gt;        list($order,$limit,$page) = $this-&gt;Pagination-&gt;init($criteria); // Added&lt;br /&gt;        $data = $this-&gt;Post-&gt;findAll($criteria, NULL, $order, $limit, $page); // Extra parameters added&lt;br /&gt;        &lt;br /&gt;        $this-&gt;set('data',$data);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;?&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Create/modify the View&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To make use of pagination, include the element, and optionally modify your table headers to allow changing the sort order of results:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;View Template:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Paginated Posts Index&lt;/h1&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;$pagination-&gt;setPaging($paging); // Initialize the pagination variables&lt;br /&gt;$th = array (&lt;br /&gt;            $pagination-&gt;sortBy('id'),&lt;br /&gt;            $pagination-&gt;sortBy('title'),&lt;br /&gt;            $pagination-&gt;sortBy('created')&lt;br /&gt;); // Generate the pagination sort links&lt;br /&gt;echo $html-&gt;tableHeaders($th); // Create the table headers with sort links if desired&lt;br /&gt;&lt;br /&gt;foreach ($data as $output)&lt;br /&gt;{&lt;br /&gt;    $tr = array (&lt;br /&gt;        $output['Post']['id'],&lt;br /&gt;        $html-&gt;link($output['Post']['title'], "/Posts/View/{$output['Post']['id']}"),&lt;br /&gt;        $output['Post']['created']&lt;br /&gt;        );&lt;br /&gt;    echo $html-&gt;tableCells($tr,array('class'=&gt;'altRow'),array('class'=&gt;'evenRow'));&lt;br /&gt;}&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;? echo $this-&gt;renderElement('pagination'); // Render the pagination element ?&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Adding Ajax updates&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you include the RequestHandler component, the AJAX helper in your controller and the prototype js file is loaded in your view - you get your updates by ajax. Yes, it's that simple. The div that will be updated by default is the "content" div, you can change this by specifying in the component (either directly, or at run time) which div to update. And yes, you can disable this automatic behaviour if required.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;How to add Prototype&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So how do you add the prototype library..? Well...&lt;br /&gt;Modify your layout&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PHP Snippet:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The Prototype JavaScript library is availble at http://prototype.conio.net/&lt;br /&gt;put prototype.js in /app/webroot/js/&lt;br /&gt;Add the JavaScript code inside the head tag&lt;br /&gt;&lt;br /&gt;&lt;?php &lt;br /&gt;if(isset($javascript)):&lt;br /&gt;    echo $javascript-&gt;link('prototype.js');&lt;br /&gt;endif;          &lt;br /&gt;?&gt; &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-2663342026196161591?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/2663342026196161591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=2663342026196161591' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2663342026196161591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/2663342026196161591'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/04/cakephp-pagination.html' title='cakePHP : Pagination'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-1530487197417918305</id><published>2008-04-02T04:08:00.001-07:00</published><updated>2008-04-05T02:10:27.422-07:00</updated><title type='text'>Download the cakePHP Manual</title><content type='html'>&lt;a href="http://arafat.wordpress.com/files/2007/01/cakephp-manual-28jan07.pdf" title="CakePHP Manual in PDF Format" target="_blank"&gt;CakePHP Manual in PDF Format&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-1530487197417918305?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/1530487197417918305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=1530487197417918305' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/1530487197417918305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/1530487197417918305'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/04/download-cakephp-manual.html' title='Download the cakePHP Manual'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-4275221543477754844</id><published>2008-03-29T09:36:00.000-07:00</published><updated>2008-03-29T09:42:09.375-07:00</updated><title type='text'>Simple Problem for add/edit in cakephp with data base</title><content type='html'>&lt;span style="font-weight:bold;"&gt;First You can create the user table in your database :&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For example :&lt;br /&gt;&lt;br /&gt;CREATE TABLE `users` (&lt;br /&gt;  `id` int(11) NOT NULL auto_increment,&lt;br /&gt;  `login` varchar(20) NOT NULL,&lt;br /&gt;  `password` varchar(255) NOT NULL,&lt;br /&gt;  PRIMARY KEY  (`id`)&lt;br /&gt;)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Second you can create the thtml file in the view folder the path is /view/users/register.thtml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;form name="form" method="post"&gt;&lt;br /&gt;&lt;table border="1" &gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;User Name&lt;/td&gt;&lt;br /&gt;  &lt;TD&gt;&lt;?php echo $html-&gt;input('User/login',array('value' =&gt; $data['User']['login']));?&gt;&lt;/TD&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;Pass word&lt;/td&gt;&lt;br /&gt; &lt;td&gt;&lt;?php e($html-&gt;input('User/password',array('value' =&gt; $data['User']['password'])));?&gt;&lt;/td&gt;&lt;br /&gt;  &lt;?php e($html-&gt;hidden('User/id',array('value' =&gt; $data['User']['id'])));?&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;TD colspan="2"&gt;&lt;br /&gt;  &lt;input type="submit" value="submit"&gt;&lt;br /&gt; &lt;/TD&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/form&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Third you can create the users_controller.php  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Path is /controllers/users_controller.php &lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;class UsersController extends AppController&lt;br /&gt;{&lt;br /&gt; var $name= 'Users';&lt;br /&gt; var $helpers = array('Html','Javascript');&lt;br /&gt; function register()&lt;br /&gt; {&lt;br /&gt;  $this-&gt;set('data',NULL);&lt;br /&gt;  if(isset($this-&gt;data)){&lt;br /&gt;   $this-&gt;User-&gt;save($this-&gt;data);&lt;br /&gt;   $this-&gt;redirect('users/register');&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; function edituser($id=NULL)&lt;br /&gt; {&lt;br /&gt;  $data = $this-&gt;User-&gt;findById($id);&lt;br /&gt;  $this-&gt;set('data',$data);&lt;br /&gt;  if(isset($this-&gt;data)){&lt;br /&gt;   if($this-&gt;User-&gt;save($this-&gt;data))&lt;br /&gt;    $this-&gt;redirect('users/edituser/'.$id);&lt;br /&gt;  }&lt;br /&gt;  $this-&gt;render('register');&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Finally You can create the model user.php&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;path is /models/user.php&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt; Class User extends AppModel{&lt;br /&gt;  var $name = 'User';&lt;br /&gt; }&lt;br /&gt;?&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-4275221543477754844?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/4275221543477754844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=4275221543477754844' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4275221543477754844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4275221543477754844'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/03/simple-problem-for-addedit-in-cakephp.html' title='Simple Problem for add/edit in cakephp with data base'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-8550900754412461071</id><published>2008-03-02T18:54:00.000-08:00</published><updated>2008-03-02T19:02:29.514-08:00</updated><title type='text'>cakePHP : Configuration</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Chapter. Configuration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Table of Contents&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Database Configuration&lt;br /&gt;Global Configuration&lt;br /&gt;Routes Configuration&lt;br /&gt;Advanced Routing Configuration: Admin Routing and Webservices&lt;br /&gt;(Optional) Custom Inflections Configuration&lt;br /&gt;Database Configuration&lt;br /&gt;Your app/config/database.php file is where your database configuration all takes place. A fresh install doesn't have a database.php, so you'll need to make a copy of database.php.default. Once you've made a copy and renamed it you'll see the following:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.1. app/config/database.php&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;var $default = array('driver'   =&gt; 'mysql',&lt;br /&gt;                     'connect'  =&gt; 'mysql_connect',&lt;br /&gt;                     'host'     =&gt; 'localhost',&lt;br /&gt;                     'login'    =&gt; 'user',&lt;br /&gt;                     'password' =&gt; 'password',&lt;br /&gt;                     'database' =&gt; 'project_name',&lt;br /&gt;                     'prefix'   =&gt; '');&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Replace the information provided by default with the database connection information for your application.&lt;br /&gt;&lt;br /&gt;One note about the prefix key: the string you enter there will be prepended to any SQL call that Cake makes to your database when working with tables. You define it here once so you don't have to specify it in other places. It also allows you to follow Cake's table naming conventions if you're on a host that only gives you a single database. Note: for HABTM join tables, you only add the prefix once: prefix_apples_bananas, not prefix_apples_prefix_bananas.&lt;br /&gt;&lt;br /&gt;CakePHP supports the following database drivers:&lt;br /&gt;&lt;br /&gt;mysql&lt;br /&gt;&lt;br /&gt;postgres&lt;br /&gt;&lt;br /&gt;sqlite&lt;br /&gt;&lt;br /&gt;pear-drivername (so you might enter pear-mysql, for example)&lt;br /&gt;&lt;br /&gt;adodb-drivername&lt;br /&gt;&lt;br /&gt;The 'connect' key in the $default connection allows you to specify whether or not the database connection will be treated as persistent or not. Read the comments in the database.php.default file for help on specifying connection types for your database setup.&lt;br /&gt;&lt;br /&gt;Your database tables should also follow the following conventions:&lt;br /&gt;&lt;br /&gt;Table names used by Cake should consist of English words in plural, like "users", "authors" or "articles". Note that corresponding models have singular names.&lt;br /&gt;&lt;br /&gt;Your tables must have a primary key named 'id'.&lt;br /&gt;&lt;br /&gt;If you plan to relate tables, use foreign keys that look like: 'article_id'. The table name is singular, followed by an underscore, followed by 'id'.&lt;br /&gt;&lt;br /&gt;If you include a 'created' and/or 'modified' column in your table, Cake will automatically populate the field when appropriate.&lt;br /&gt;&lt;br /&gt;You'll also notice that there is a $test connection setting included in the database.php file. Fill out this configuration (or add other similarly formatted configurations) and use it in your application by placing something like:&lt;br /&gt;&lt;br /&gt;var $useDbConfig = 'test';&lt;br /&gt;Inside one of your models. You can add any number of additional connection settings in this manner.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Global Configuration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CakePHP's global configuration can be found in app/config/core.php. While we really dislike configuration files, it just had to be done. There are a few things you can change here, and the notes on each of these settings can be found within the comments of the core.php file.&lt;br /&gt;&lt;br /&gt;DEBUG: Set this to different values to help you debug your application as you build it. Specifying this setting to a non-zero value will force Cake to print out the results of pr( ) and debug( ) function calls, and stop flash messages from forwarding automatically. Setting it to 2 or higher will result in SQL statements being printed at the bottom of the page.&lt;br /&gt;&lt;br /&gt;Also when in debug mode (where DEBUG is set to 1 or higher), Cake will render certain generated error pages, i.e. "Missing Controller," "Missing Action," etc. In production mode, however (where DEBUG is set to 0), Cake renders the "Not Found" page, which can be overridden in app/views/errors/error404.thtml.&lt;br /&gt;&lt;br /&gt;CAKE_SESSION_COOKIE: Change this value to the name of the cookie you'd like to use for user sessions in your Cake app.&lt;br /&gt;&lt;br /&gt;CAKE_SECURITY: Change this value to indicate your preferred level of sessions checking. Cake will timeout sessions, generate new session ids, and delete old session files based on the settings you provide here. The possible values are:&lt;br /&gt;&lt;br /&gt;high: sessions time out after 10 minutes of inactivity, and session id's are regenerated on each request&lt;br /&gt;&lt;br /&gt;medium: sessions time out after 20 minutes of inactivity&lt;br /&gt;&lt;br /&gt;low: sessions time out after 30 minutes of inactivity&lt;br /&gt;&lt;br /&gt;CAKE_SESSION_SAVE: Specify how you'd like session data saved. Possible values are:&lt;br /&gt;&lt;br /&gt;cake: Session data is saved in tmp/ inside your Cake installation&lt;br /&gt;&lt;br /&gt;php: Session data saved as defined in php.ini&lt;br /&gt;&lt;br /&gt;database: Session data saved to database connection defined by the 'default' key.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Routes Configuration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;"Routing" is a pared-down pure-PHP mod_rewrite-alike that can map URLs to controller/action/params and back. It was added to Cake to make pretty URLs more configurable and to divorce us from the mod_rewrite requirement. Using mod_rewrite, however, will make your address bar look much more tidy.&lt;br /&gt;&lt;br /&gt;Routes are individual rules that map matching URLs to specific controllers and actions. Routes are configured in the app/config/routes.php file. They are set-up like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.2. Route Pattern&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;$Route-&gt;connect (&lt;br /&gt;    'URL',&lt;br /&gt;    array('controller'=&gt;'controllername',&lt;br /&gt;    'action'=&gt;'actionname', 'firstparam')&lt;br /&gt;);&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Where:&lt;br /&gt;&lt;br /&gt;URL is the regular expression Cake URL you wish to map,&lt;br /&gt;&lt;br /&gt;controllername is the name of the controller you wish to invoke,&lt;br /&gt;&lt;br /&gt;actionname is the name of the controller's action you wish to invoke,&lt;br /&gt;&lt;br /&gt;and firstparam is the value of the first parameter of the action you've specified.&lt;br /&gt;&lt;br /&gt;Any parameters following firstparam will also be passed as parameters to the controller action.&lt;br /&gt;&lt;br /&gt;The following example joins all the urls in /blog to the BlogController. The default action will be BlogController::index(). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.3. Route Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;$Route-&gt;connect ('/blog/:action/*', array('controller'=&gt;'Blog', 'action'=&gt;'index'));&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;A URL like /blog/history/05/june can then be handled like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.4. Route Handling in a Controller&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;class BlogController extends AppController&lt;br /&gt;{&lt;br /&gt; function history ($year, $month=null)&lt;br /&gt; {&lt;br /&gt;   // .. Display appropriate content&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The 'history' from the URL was matched by :action from the Blog's route. URL elements matched by * are passed to the active controller's handling method as parameters, hence the $year and $month. Called with URL /blog/history/05, history() would only be passed one parameter, 05.&lt;br /&gt;&lt;br /&gt;The following example is a default CakePHP route used to set up a route for PagesController::display('home'). Home is a view which can be overridden by creating the file /app/views/pages/home.thtml.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.5. Setting the Default Route&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;$Route-&gt;connect ('/', array('controller'=&gt;'Pages', 'action'=&gt;'display', 'home'));&lt;br /&gt;?&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Advanced Routing Configuration: Admin Routing and Webservices&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are some settings in /app/config/core.php you can take advantage of in order to organize your application and craft URLs that make the most sense to you and your users.&lt;br /&gt;&lt;br /&gt;The first of these is admin routing. If your application has a ProductsController as well as a NewsController, you might want to set up some special URLs so users with administrative privileges can access special actions in those controllers. To keep the URLs nice and easy to read, some people prefer /admin/products/add and /admin/news/post to something like /products/adminAdd and /news/adminPost.&lt;br /&gt;&lt;br /&gt;To enable this, first, uncomment the CAKE_ADMIN line in your /app/config/core.php file. The default value of CAKE_ADMIN is 'admin', but you can change it to whatever you like. Remember this string, because you'll need to prepend it to your administrative actions in your controller. So, admin actions in this case would be named admin_actionName(). Here's some examples of desired URLs and possible CAKE_ADMIN and controller action settings:&lt;br /&gt;&lt;br /&gt;/admin/products/add          CAKE_ADMIN = 'admin'&lt;br /&gt;                             name of action in ProductsController = 'admin_add()'&lt;br /&gt;&lt;br /&gt;/superuser/news/post         CAKE_ADMIN = 'superuser'&lt;br /&gt;                             name of action in NewsController = 'superuser_post()'&lt;br /&gt;&lt;br /&gt;/admin/posts/delete          CAKE_ADMIN = 'admin'&lt;br /&gt;                             name of action in PostsController = 'admin_delete()'&lt;br /&gt; &lt;br /&gt;Using admin routes allows you to keep your logic organized while making the routing very easy to accomplish.&lt;br /&gt;&lt;br /&gt; Note &lt;br /&gt;Please note that enabling admin routes or using them does not enable any sort of authentication or security. You'll need implement those yourself.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Similarly, you can enable Cake's webservices routing to make easier there as well. Have a controller action you'd like to expose as a webservice? First, set WEBSERVICES in /app/config/core.php to 'on'. This enables some automatic routing somewhat similar to admin routing, except that a certain set of route prefixes are enabled:&lt;br /&gt;&lt;br /&gt;rss&lt;br /&gt;&lt;br /&gt;xml&lt;br /&gt;&lt;br /&gt;rest&lt;br /&gt;&lt;br /&gt;soap&lt;br /&gt;&lt;br /&gt;xmlrpc&lt;br /&gt;&lt;br /&gt;What this does is allows you to provide an alternate views that will automatically be available at /rss/controllerName/actionName or /soap/controllerName/actionName. This allows you to create a single action that can have two views: one for normal HTML viewiers, and another for webservices users. By doing this, you can easily allow much of the functionality of your application to be available via webservices.&lt;br /&gt;&lt;br /&gt;For example, let's say I have some logic in my application that tells users who is on the phone in my office. I already have a HTML view for this data, but I want to offer it in XML so it can be used in a desktop widget or handheld application. First I need to enable Cake's webservice routing:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.6. /app/config/core.php (partial)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; *  The define below is used to turn cake built webservices&lt;br /&gt; *  on or off. Default setting is off.&lt;br /&gt; */&lt;br /&gt; define('WEBSERVICES', 'on');&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Next, I can structure the logic in my controller just as I normally would:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example 4.7. messages_controller.php&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;class PhonesController extends AppController&lt;br /&gt;{&lt;br /&gt;    function doWhosOnline()&lt;br /&gt;    {&lt;br /&gt;        // this action is where we do all the work of seeing who's on the phone...&lt;br /&gt;&lt;br /&gt;        // If I wanted this action to be available via Cake's xml webservices route,&lt;br /&gt;        // I'd need to include a view at /app/views/posts/xml/do_whos_online.thtml.&lt;br /&gt;        // Note: the default view used here is at /app/views/layouts/xml/default.thtml.&lt;br /&gt;&lt;br /&gt;        // If a user requests /phones/doWhosOnline, they will get an HTML version.&lt;br /&gt;        // If a user requests /xml/phones/doWhosOnline, they will get the XML version.&lt;br /&gt;    } &lt;br /&gt;}&lt;br /&gt;?&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;(Optional) Custom Inflections Configuration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Cake's naming conventions can be really nice - you can name your model Box, your controller Boxes, and everything just works out. There are occasions (especially for our non-english speaking friends) where you may run into situations where Cake's inflector (the class that pluralizes, singularizes, camelCases, and under_scores) might not work as you'd like. If Cake won't recognize your Foci or Fish, editing the custom inflections configuration file is where you'll need to go.&lt;br /&gt;&lt;br /&gt;Found at /app/config/inflections.php is a list of Cake variables you can use to adjust the pluralization, singularization of classnames in Cake, along with definining terms that shouldn't be inflected at all (like Fish and Deer, for you outdoorsman cakers) along with irregularities.&lt;br /&gt;&lt;br /&gt;Follow the notes inside the file to make adjustments, or use the examples in the file by uncommenting them. You may need to know a little regex before diving in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-8550900754412461071?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/8550900754412461071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=8550900754412461071' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8550900754412461071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/8550900754412461071'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/03/cakephp-configuration.html' title='cakePHP : Configuration'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-6804555697230688183</id><published>2008-03-02T18:44:00.000-08:00</published><updated>2008-03-02T18:48:28.232-08:00</updated><title type='text'>cakePHP : Installing CakePHP</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Chapter 3. Installing CakePHP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Table of Contents&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Introduction&lt;br /&gt;Requirements&lt;br /&gt;Server Requirements&lt;br /&gt;Installing CakePHP&lt;br /&gt;Getting the most recent stable version&lt;br /&gt;Unpacking&lt;br /&gt;Setting Up CakePHP&lt;br /&gt;Development Setup&lt;br /&gt;Production Setup&lt;br /&gt;Advanced Setup: Alternative Installation Options&lt;br /&gt;Configuring Apache and mod_rewrite&lt;br /&gt;Make Sure It's Working&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So now you know everything there is to know about the structure and purpose of all the CakePHP libraries, or you have skipped to this part because you don't care about that stuff and just want to start playing. Either way, you're ready to get your hands dirty.&lt;br /&gt;&lt;br /&gt;This chapter will describe what must be installed on the server, different ways to configure your server, downloading and installing CakePHP, bringing up the default CakePHP page, and some troubleshooting tips just in case everything does not go as planned.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Requirements&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In order use CakePHP you must first have a server that has all the required libraries and programs to run CakePHP:&lt;br /&gt;&lt;br /&gt;Server Requirements&lt;br /&gt;Here are the requirements for setting up a server to run CakePHP:&lt;br /&gt;&lt;br /&gt;An HTTP server (like Apache) with the following enabled: sessions, mod_rewrite (not absolutely necessary but preferred)&lt;br /&gt;&lt;br /&gt;PHP 4.3.2 or greater. Yes, CakePHP works great in either PHP 4 or 5.&lt;br /&gt;&lt;br /&gt;A database engine (right now, there is support for MySQL, PostgreSQL and a wrapper for ADODB).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Installing CakePHP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Getting the most recent stable version&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are a few ways you can secure a copy of CakePHP: getting a stable release from CakeForge, grabbing a nightly build, or getting a fresh version of code from SVN.&lt;br /&gt;&lt;br /&gt;To download a stable version of code, check out the files section of the CakePHP project at CakeForge by going to http://cakeforge.org/projects/cakephp/.&lt;br /&gt;&lt;br /&gt;To grab a nightly, download one from http://cakephp.org/downloads/index/nightly. These nightly releases are stable, and often include the bug fixes between stable releases.&lt;br /&gt;&lt;br /&gt;To grab a fresh copy from our SVN repository, use your favorite SVN client and connect to https://svn.cakephp.org/repo/trunk/cake/ and choose the version you're after.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Unpacking&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now that you've downloaded the most recent release, place that compressed package on your web server in the webroot. Now you need to unpack the CakePHP package. There are two ways to do this, using a development setup, which allows you to easily view many CakePHP applications under a single domain, or using the production setup, which allows for a single CakePHP application on the domain.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Configuring Apache and mod_rewrite&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While CakePHP is built to work with mod_rewrite out of the box, we've noticed that a few users struggle with getting everything to play nicely on their systems. Here are a few things you might try to get it running correctly:&lt;br /&gt;&lt;br /&gt;Make sure that an .htaccess override is allowed: in your httpd.conf, you should have a section that defines a section for each Directory on your server. Make sure the AllowOverride is set to All for the correct Directory.&lt;br /&gt;&lt;br /&gt;Make sure you are editing the system httpd.conf rather than a user- or site-specific httpd.conf.&lt;br /&gt;&lt;br /&gt;For some reason or another, you might have obtained a copy of CakePHP without the needed .htaccess files. This sometimes happens because some operating systems treat files that start with '.' as hidden, and don't copy them. Make sure your copy of CakePHP is from the downloads section of the site or our SVN repository.&lt;br /&gt;&lt;br /&gt;Make sure you are loading up mod_rewrite correctly! You should see something like LoadModule rewrite_module libexec/httpd/mod_rewrite.so and AddModule mod_rewrite.c in your httpd.conf.&lt;br /&gt;&lt;br /&gt;If you are installing Cake into a user directory (http://example.com/~myusername/), you'll need to modify the .htaccess file in the base directory of your Cake installation. Just add the line "RewriteBase /~myusername/".&lt;br /&gt;&lt;br /&gt;If for some reason your URLS are suffixed with a long, annoying session ID (http://example.com/posts/?CAKEPHP=4kgj577sgabvnmhjgkdiuy1956if6ska), you might also add "php_flag session.trans_id off" to the .htaccess file at the root of your installation as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Make Sure It's Working&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Alright, lets see this baby in action. Depending on which setup you used, you should point your browser to http://www.example.com or http://www.example.com/cake. At this point, you'll be presented with CakePHP's default home, and a message that tells you the status of your current database connection.&lt;br /&gt;&lt;br /&gt;Congratulations! You are ready to create your first Cake-based application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-6804555697230688183?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/6804555697230688183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=6804555697230688183' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6804555697230688183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/6804555697230688183'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/03/cakephp-installing-cakephp.html' title='cakePHP : Installing CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-4959022228440109722</id><published>2008-03-02T18:31:00.000-08:00</published><updated>2008-03-02T18:34:26.427-08:00</updated><title type='text'>cakePHP:Basic Concepts</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Chapter 2. Basic Concepts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Table of Contents&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The MVC Pattern&lt;br /&gt;Overview of the Cake File Layout&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;This chapter is a short, casual introduction to MVC concepts as they are implemented in Cake. If you're new to MVC (Model View Controller) patterns, this chapter is definitely for you. We begin with a discussion of general MVC concepts, work our way into the specific application of MVC in CakePHP, and show some simple examples of CakePHP using the MVC pattern.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The MVC Pattern&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Model-View-Controller is a software design pattern that helps you logically separate your code, make it more reusable, maintainable, and generally better. Model View Controller was first described by the author group Gang of Four. Dean Helman wrote (an extract from Objective Toolkit Pro white paper):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"The MVC paradigm is a way of breaking an application, or even just a piece of an application's interface, into three parts: the model, the view, and the controller. MVC was originally developed to map the traditional input, processing, output roles into the GUI realm.&lt;br /&gt;&lt;br /&gt;Input -&gt; Processing -&gt; Output&lt;br /&gt;&lt;br /&gt;Controller -&gt; Model -&gt; View&lt;br /&gt;&lt;br /&gt;"The user input, the modeling of the external world, and the visual feedback to the user are separated and handled by model, view port and controller objects. The controller interprets mouse and keyboard inputs from the user and maps these user actions into commands that are sent to the model and/or view port to effect the appropriate change. The model manages one or more data elements, responds to queries about its state, and responds to instructions to change state. The view port manages a rectangular area of the display and is responsible for presenting data to the user through a combination of graphics and text."&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In Cake terms, the Model represents a particular database table/record, and it's relationships to other tables and records. Models also contain data validation rules, which are applied when model data is inserted or updated. The View represents Cake's view files, which are regular HTML files embedded with PHP code. Cake's Controller handles requests from the server. It takes user input (URL and POST data), applies business logic, uses Models to read and write data to and from databases and other sources, and lastly, sends output data to the appropriate view file.&lt;br /&gt;&lt;br /&gt;To make it as easy as possible to organize your application, Cake uses this pattern not only to manage how objects interact within your application, but also how files are stored, which is detailed next.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Overview of the Cake File Layout&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you unpack Cake on your server you will find three main folders - &lt;br /&gt;&lt;br /&gt;      app&lt;br /&gt;      cake&lt;br /&gt;      vendors&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;The cake folder is where the core libraries for Cake lay and you generally won't ever need to touch it. &lt;br /&gt;&lt;br /&gt;The app folder is where your application specific folders and files will go. The separation between the cake folder and the app folder make it possible for you to have many app folders sharing a single set of Cake libraries. This also makes it easy to update CakePHP: you just download the latest version of Cake and overwrite your current core libraries. No need to worry about overwriting something you wrote for your app.&lt;br /&gt;&lt;br /&gt;You can use the vendors directory to keep third-party libraries in. You will learn more about vendors later, but the basic idea is that you can access classes you've placed in the vendors directory using Cake's vendor() function.&lt;br /&gt;&lt;br /&gt;Let's look at the entire file layout:&lt;br /&gt;&lt;br /&gt;/app&lt;br /&gt;    /config          - Contains config files for your database, ACL, etc. &lt;br /&gt;&lt;br /&gt;    /controllers     - Controllers go here &lt;br /&gt;        /components  - Components go here&lt;br /&gt;&lt;br /&gt;    /index.php       - Allows you to deploy cake with /app as the DocumentRoot&lt;br /&gt;&lt;br /&gt;    /models          - Models go here&lt;br /&gt; &lt;br /&gt;    /plugins         - Plugins go here&lt;br /&gt;&lt;br /&gt;    /tmp             - Used for caches and logs&lt;br /&gt;&lt;br /&gt;    /vendors         - Contains third-party libaries for this application&lt;br /&gt;&lt;br /&gt;    /views           - Views go here&lt;br /&gt;        /elements    - Elements, little bits of views, go here&lt;br /&gt;        /errors      - Your custom error pages go here&lt;br /&gt;        /helpers     - Helpers go here&lt;br /&gt;        /layouts     - Application layout files go here&lt;br /&gt;        /pages       - Static views go here&lt;br /&gt;&lt;br /&gt;    /webroot         - The DocumentRoot for the application&lt;br /&gt;        /css&lt;br /&gt;        /files&lt;br /&gt;        /img&lt;br /&gt;        /js&lt;br /&gt;&lt;br /&gt;/cake                - Cake's core libraries. Don't edit any files here.&lt;br /&gt;&lt;br /&gt;index.php           &lt;br /&gt;&lt;br /&gt;/vendors             - Used for server-wide third-party libraries.&lt;br /&gt;&lt;br /&gt;VERSION.txt          - Let's you know what version of Cake you're using.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-4959022228440109722?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/4959022228440109722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=4959022228440109722' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4959022228440109722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/4959022228440109722'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/03/cakephpbasic-concepts.html' title='cakePHP:Basic Concepts'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5283829804020620688.post-3649218328149269598</id><published>2008-03-02T18:15:00.000-08:00</published><updated>2008-03-02T18:30:21.626-08:00</updated><title type='text'>Introduction to CakePHP</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Chapter 1. Introduction to CakePHP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Table of Contents&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What is CakePHP?&lt;br /&gt;Why CakePHP?&lt;br /&gt;History of CakePHP&lt;br /&gt;What is CakePHP?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;CakePHP is a free open-source rapid development framework for PHP. Its a structure of libraries, classes and run-time infrastructure for programmers creating web applications originally inspired by the Ruby on Rails framework. Our primary goal is to enable you to work in a structured and rapid manner - without loss of flexibility.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Why CakePHP?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CakePHP has several features that make it a great choice as a framework for developing applications swiftly and with the least amount of hassle. Here are a few in no particular order:&lt;br /&gt;&lt;br /&gt;Active, friendly community&lt;br /&gt;&lt;br /&gt;Flexible Licensing&lt;br /&gt;&lt;br /&gt;Compatibility with PHP4 and PHP5&lt;br /&gt;&lt;br /&gt;Integrated CRUD for database interaction and simplified queries&lt;br /&gt;&lt;br /&gt;Application Scaffolding&lt;br /&gt;&lt;br /&gt;Model View Controller (MVC) Architecture&lt;br /&gt;&lt;br /&gt;Request dispatcher with good looking, custom URLs&lt;br /&gt;&lt;br /&gt;Built-in Validation&lt;br /&gt;&lt;br /&gt;Fast and flexible templating (PHP syntax, with helpers)&lt;br /&gt;&lt;br /&gt;View Helpers for AJAX, Javascript, HTML Forms and more&lt;br /&gt;&lt;br /&gt;Security, Session, and Request Handling Components&lt;br /&gt;&lt;br /&gt;Flexible access control lists&lt;br /&gt;&lt;br /&gt;Data Sanitization&lt;br /&gt;&lt;br /&gt;Flexible View Caching&lt;br /&gt;&lt;br /&gt;Works from any web site subdirectory, with little to no Apache configuration involved&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;History of CakePHP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In 2005, Michal Tatarynowicz wrote a minimal version of a Rapid Application Framework in PHP. He found that it was the start of a very good framework. Michal published the framework under the MIT license, dubbing it Cake, and opened it up to a community of developers, who now maintain Cake under the name CakePHP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5283829804020620688-3649218328149269598?l=cakephphelp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cakephphelp.blogspot.com/feeds/3649218328149269598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5283829804020620688&amp;postID=3649218328149269598' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3649218328149269598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5283829804020620688/posts/default/3649218328149269598'/><link rel='alternate' type='text/html' href='http://cakephphelp.blogspot.com/2008/03/introduction-to-cakephp.html' title='Introduction to CakePHP'/><author><name>Sourabh</name><uri>http://www.blogger.com/profile/09102255426918570907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_GngxI2rnTxU/SSciHzPd7KI/AAAAAAAAAF8/5_eVWB9DFoQ/S220/DSC00109.jpg'/></author><thr:total>1</thr:total></entry></feed>
