<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Code for Concinnity &#187; CakePHP</title>
	<atom:link href="http://cfc.kizzx2.com/index.php/category/cakephp/feed/" rel="self" type="application/rss+xml" />
	<link>http://cfc.kizzx2.com</link>
	<description>beautiful and elegant solutions</description>
	<lastBuildDate>Fri, 10 Feb 2012 13:24:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Restoring elegance to CakePHP &#8212; doing multiple joins The Right Way&#8482;</title>
		<link>http://cfc.kizzx2.com/index.php/restoring-elegance-to-cakephp-doing-multiple-joins-the-right-way/</link>
		<comments>http://cfc.kizzx2.com/index.php/restoring-elegance-to-cakephp-doing-multiple-joins-the-right-way/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 12:30:40 +0000</pubDate>
		<dc:creator>kizzx2</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[joins]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://cfc.kizzx2.com/?p=157</guid>
		<description><![CDATA[In my last article about unit testing, I mentioned one way to do ad-hoc multiple joins in CakePHP rather succinctly. Here&#8217;s a recap: 1234567891011121314151617function tagged&#40;$tag&#41; &#123; &#160; &#160; $this-&#62;bindModel&#40;array&#40;'hasOne'=&#62;array&#40; &#160; &#160; &#160; &#160; 'PostsTag'=&#62;array&#40; &#160; &#160; &#160; &#160; &#160; &#160; 'foreignKey'=&#62;false, &#160; &#160; &#160; &#160; &#160; &#160; 'conditions'=&#62;&#34;PostsTag.post_id = Post.id&#34; &#160; &#160; &#160; &#160; &#41;, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="margin-left: 10px; float: right;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcfc.kizzx2.com%2Findex.php%2Frestoring-elegance-to-cakephp-doing-multiple-joins-the-right-way%2F">
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcfc.kizzx2.com%2Findex.php%2Frestoring-elegance-to-cakephp-doing-multiple-joins-the-right-way%2F&amp;source=kizzx2&amp;style=normal&amp;b=2" height="61" width="50" />
			</a>
		</div><p>In my <a href="/index.php/unit-testing-in-cakephp-the-missing-manual-and-a-step-by-step-tutorial/">last article about unit testing</a>, I mentioned one way to do ad-hoc multiple joins in CakePHP rather succinctly. Here&#8217;s a recap:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> tagged<span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bindModel</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'hasOne'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'PostsTag'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span><span style="color: #339933;">=&gt;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;PostsTag.post_id = Post.id&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'Tag'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span><span style="color: #339933;">=&gt;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;PostsTag.tag_id = Tag.id&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'all'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'Tag.name'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>

<p>This is, of course, rather unintuitive. A <code>hasOne</code> relationship when in fact I&#8217;m trying to look for someone <code>hasAndBelongsToMany</code>? I thought more about it.</p>

<p>There is a <a href="http://bakery.cakephp.org/articles/view/quick-tip-doing-ad-hoc-joins-in-model-find">Bakery article that talked about doing ad-hoc joins</a>. It looks more technically correct but just too freaking much verbose for my liking:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <br />
&nbsp; &nbsp; <span style="color: #000088;">$markers</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Marker</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'all'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'joins'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'table'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'markers_tags'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'alias'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'MarkersTag'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'inner'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MarkersTag.marker_id = Marker.id'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'table'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'tags'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'alias'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Tag'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'inner'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'Tag.id = MarkersTag.tag_id'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'Tag.tag'</span> <span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/explode"><span style="color: #990000;">explode</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'url'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'q'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>

<p>Actually, a simple refactoring can make it (almost) syntactically sweet and technically more correct:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// /app/vendors/joins.php</span><br />
<br />
<span style="color: #009933; font-style: italic;">/**<br />
&nbsp;* A new helper class to produce those join arrays just to make <br />
&nbsp;* life less miserable<br />
&nbsp;*/</span><br />
<span style="color: #000000; font-weight: bold;">class</span> Joins<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> left<span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #339933;">,</span> <span style="color: #000088;">$conditions</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span>_makeJoin<span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #339933;">,</span> <span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'left'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> inner<span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #339933;">,</span> <span style="color: #000088;">$conditions</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span>_makeJoin<span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #339933;">,</span> <span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'inner'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000000; font-weight: bold;">function</span> _makeJoin<span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #339933;">,</span> <span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$type</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'table'</span><span style="color: #339933;">=&gt;</span>Inflector<span style="color: #339933;">::</span><span style="color: #004000;">tableize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$model</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'alias'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$model</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'type'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$type</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span><span style="color: #339933;">=&gt;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$conditions</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// /app/app_model.php</span><br />
<br />
App<span style="color: #339933;">::</span><span style="color: #004000;">import</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Vendor'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'joins'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> AppModel <span style="color: #000000; font-weight: bold;">extends</span> Model<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// /app/models/post.php</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> tagged<span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*<br />
&nbsp; &nbsp; &nbsp;* Let's make use of our new class, this has become<br />
&nbsp; &nbsp; &nbsp;* a &quot;one-liner.&quot;<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'all'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Tag.name'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'joins'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Joins<span style="color: #339933;">::</span><span style="color: #004000;">inner</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'PostsTag'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'PostsTag.post_id = Post.id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Joins<span style="color: #339933;">::</span><span style="color: #004000;">inner</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Tag'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;PostsTag.tag_id = Tag.id&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss>http://cfc.kizzx2.com/index.php/restoring-elegance-to-cakephp-doing-multiple-joins-the-right-way/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit testing in CakePHP &#8212; the missing manual and a step-by-step tutorial</title>
		<link>http://cfc.kizzx2.com/index.php/unit-testing-in-cakephp-the-missing-manual-and-a-step-by-step-tutorial/</link>
		<comments>http://cfc.kizzx2.com/index.php/unit-testing-in-cakephp-the-missing-manual-and-a-step-by-step-tutorial/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 16:53:40 +0000</pubDate>
		<dc:creator>kizzx2</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[manual]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[unit-testing]]></category>

		<guid isPermaLink="false">http://cfc.kizzx2.com/?p=150</guid>
		<description><![CDATA[Today I&#8217;ve finally formalized a streamlined procedure to do unit testing properly in CakePHP &#8212; without all the pain. Needless to say, The Cookbook&#8217;s chapter on this issue cover the basic grounds but is inconsistent and lack a real life feeling to it. The Cookbook&#8217;s coverage is really basic and doesn&#8217;t hold up to more [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="margin-left: 10px; float: right;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcfc.kizzx2.com%2Findex.php%2Funit-testing-in-cakephp-the-missing-manual-and-a-step-by-step-tutorial%2F">
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcfc.kizzx2.com%2Findex.php%2Funit-testing-in-cakephp-the-missing-manual-and-a-step-by-step-tutorial%2F&amp;source=kizzx2&amp;style=normal&amp;b=2" height="61" width="50" />
			</a>
		</div><p>Today I&#8217;ve finally formalized a streamlined procedure to do unit testing properly in CakePHP &#8212; without all the pain. Needless to say, <a href="http://book.cakephp.org/view/160/Testing">The Cookbook&#8217;s chapter</a> on this issue cover the basic grounds but is inconsistent and lack a real life feeling to it.</p>

<p>The Cookbook&#8217;s coverage is really basic and doesn&#8217;t hold up to more real life complicated cases. Cake seems to be particularly picky about its <em>automagical</em> (too clever for me to figure out for a long time) configurations and bark errors at me very often. That led to reluctance to write tests and sometimes giving it up all together :p</p>

<p>The steps I&#8217;ve written here should lay down a very solid framework to make you bullet proof for all your future testing needs.</p>

<p>(Of course, this might be coming a bit late since most people would be better off looking at Cake&#8217;s successor <a href="http://lithify.me/">Lithium</a>, anyway here we goes.)</p>

<p>Can&#8217;t gather up much time to make a polished article but I believe this point-form brain dump is much more effective than most documentation out there.</p>

<h2>Testing models</h2>

<p>First, some notes</p>

<ul>
<li><p>Testing models is the most important thing. Of course, a proper MVC application should have fat models and thin controllers.</p></li>
<li><p>For the most part, <em>you really should use fixtures</em> even if you do not use fixtures to load data. If you just use the database live, chances are Cake might mess up your data and errors might pop up, just go ahead and use fixtures. <em>Yes, you don&#8217;t need to load data with your fixtures if you don&#8217;t want, but you need to turn this feature on</em>. Yes, this was the thing that confused me a lot.</p></li>
<li><p>CakePHP uses SimpleTest, you would think that you&#8217;d put your setup and teardown code in <code>setUp()</code> and <code>tearDown()</code> just like everybody else? Wrong. Cake has already invaded those spaces. You&#8217;ll need to use <code>startTest()</code> and <code>endTest()</code>. This was documented in the Cookbook but this took me quite some time to figure out since I took it for granted and didn&#8217;t RTFM.</p></li>
<li><p>I may cover controller testing later but IMO controller testing in Cake is mostly broken and is quite straight forward to figure out.</p></li>
</ul>

<h2>Testing models &#8212; the tutorial</h2>

<p>First we&#8217;ll set up the database, install SimpleTest etc. If you don&#8217;t know how to do this step you should read the <a href="http://book.cakephp.org/">Real Manual</a> first.</p>

<p>Set up our testing application database in (My)SQL.</p>

<div class="codecolorer-container sql default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- We have the title field called &quot;name&quot; instead of &quot;title&quot;</span><br />
<span style="color: #808080; font-style: italic;">-- IMO this is idiomatic Cake because your post's title </span><br />
<span style="color: #808080; font-style: italic;">-- will now automatically show up in Post::find('list')</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`posts`</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`name`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`body`</span> TEXT<br />
<span style="color: #66cc66;">&#41;</span>;<br />
<br />
<span style="color: #808080; font-style: italic;">-- You may think that the &quot;name&quot; field should be primary key.</span><br />
<span style="color: #808080; font-style: italic;">-- Wrong! Doing so will make Cake unhappy if you ever use</span><br />
<span style="color: #808080; font-style: italic;">-- Cake's console schema or the all other Cake migration</span><br />
<span style="color: #808080; font-style: italic;">-- plugins out there. The id field is the Creed.</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`tags`</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`name`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">UNIQUE</span><br />
<span style="color: #66cc66;">&#41;</span>;<br />
<br />
<span style="color: #808080; font-style: italic;">-- The id field is the Creed, even for join tables</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`posts_tags`</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`post_id`</span> <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">`tag_id`</span> <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span><span style="color: #66cc66;">&#40;</span>post_id<span style="color: #66cc66;">,</span> tag_id<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>

<p>Bake our stuffs. Bake has come a long way since the earlier versions and the bake in Cake 1.3 is genuinely useful:</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake bake all Post<br />
$ cake bake all Tag</div></td></tr></tbody></table></div>

<p>Now go create some test data:</p>

<div class="codecolorer-container sql default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`name`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Lorem&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Ipsum&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Dolor&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Sit&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`tags`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`name`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;apple&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;orange&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`posts_tags`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`post_id`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`tag_id`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>

<p>Now open <code>/app/models/post.php</code> and <code>/app/models/tag.php</code>. Both look OK! And Cake has gone ahead and created the test cases for us at <code>/app/tests/cases/model</code>. Let&#8217;s try to run it</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake testsuite app all<br />
Error: Missing database table <span style="color: #ff0000;">'test_suite_posts_tags'</span> <span style="color: #000000; font-weight: bold;">for</span> model <span style="color: #ff0000;">'PostsTag'</span></div></td></tr></tbody></table></div>

<p>This is how broken it is! Now let&#8217;s fix it. The thing is that we haven&#8217;t baked the fixture for the join table class <code>PostsTag</code>. Of course, we don&#8217;t want to have to create controller, models, views just for a simple join class. Luckily we can amend it by creating all missing fixtures:</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>cake bake fixture all <span style="color: #660033;">-records</span> <span style="color: #660033;">-count</span> <span style="color: #000000;">999</span></div></td></tr></tbody></table></div>

<p>This will create all the missing fixtures. The <code>-records -count 999</code> part tells Cake to pull real data from our database as fixture. The <code>-count</code> part is needed because it defaults to 10. Might as well enter some very large number but YMMV. This will also <em>update</em> our existing fixtures for Post and Tag so that the new fixture data we&#8217;ve added to the database will be reflected in the fixtures. Let&#8217;s try to run the tests again:</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake testsuite app all<br />
...<br />
<span style="color: #000000;">4</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">4</span> &nbsp;<span style="color: #7a0874; font-weight: bold;">test</span> cases complete.</div></td></tr></tbody></table></div>

<p>Finally, we&#8217;ve got the testing architecture down. To honor TDD, let&#8217;s create (edit) our test file before we do some development. Now go to <code>/app/tests/cases/models/post.test.php</code>, you&#8217;ll see this line:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$fixtures</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app.tag'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'app.post'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'app.posts_tag'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>

<p>This is unfortunate, because it means every time you add a new association to your model, you&#8217;ll have to manually edit this <code>$fixtures</code> array. Too bad there isn&#8217;t an automated way to do this. (Running <code>bake test</code> will overwrite your whole file. You&#8217;ve been warned!)</p>

<p>Anyway, let&#8217;s just write some tests for kicks in <code>/app/tests/cases/model/post.test.php</code>:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> testSanity<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Our fixtures should be loaded with data</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$posts</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'all'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>

<p>Run it, all is good:</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake testsuite app all<br />
...<br />
<span style="color: #000000;">4</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">4</span> <span style="color: #7a0874; font-weight: bold;">test</span> cases complete: <span style="color: #000000;">2</span> passes.</div></td></tr></tbody></table></div>

<p>To honor TDD, we&#8217;ll write our test first before we do any implementation. Let&#8217;s add our test function. We&#8217;re going to write a model function that will find all posts for a given tag:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> testTagged<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// These are based on our testing fixture data above</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$posts</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tagged</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'apple'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">::</span><span style="color: #004000;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/Post[name=Lorem]'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">::</span><span style="color: #004000;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/Post[name=Ipsum]'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertFalse</span><span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">::</span><span style="color: #004000;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/Post[name=Dolor]'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$posts</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tagged</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'orange'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">::</span><span style="color: #004000;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/Post[name=Lorem]'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">::</span><span style="color: #004000;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/Post[name=Dolor]'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertFalse</span><span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">::</span><span style="color: #004000;">matches</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/Post[name=Ipsum]'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$posts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>

<p>Run the test and watch it fail:</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake testsuite app all<br />
...</div></td></tr></tbody></table></div>

<p>Do our implementation in <code>/app/models/post.php</code></p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">/*<br />
&nbsp;* If this line seems alien to you, don't worry.<br />
&nbsp;* Doing HABTM in CakePHP is a train wreck and whole another<br />
&nbsp;* topic. This is probably the most elegant way to do it <br />
&nbsp;* (not necessarily the shortest and cleanest) as far as <br />
&nbsp;* I know.<br />
&nbsp;*<br />
&nbsp;* The good thing about unit test -- we can be sure <br />
&nbsp;* it works even though we don't understand it lol<br />
&nbsp;*/</span><br />
<span style="color: #000000; font-weight: bold;">function</span> tagged<span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bindModel</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'hasOne'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'PostsTag'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span><span style="color: #339933;">=&gt;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;PostsTag.post_id = Post.id&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'Tag'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'foreignKey'</span><span style="color: #339933;">=&gt;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;PostsTag.tag_id = Tag.id&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'all'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'conditions'</span><span style="color: #339933;">=&gt;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'Tag.name'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>

<p>The above trick was used to force CakePHP to do left joins for us. There is an <a href="http://teknoid.wordpress.com/2008/07/17/forcing-an-sql-join-in-cakephp/">article that talks about this technique</a> on the <a href="http://teknoid.wordpress.com/">nuts and bolts of cakephp</a> blog.</p>

<p>Well, let&#8217;s add one more test. We want to make a function to get us the content of a post:</p>

<div class="codecolorer-container sql default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- First, update our test database</span><br />
<span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #ff0000;">`body`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Hello World!!&quot;</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #ff0000;">`name`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Lorem&quot;</span>;</div></td></tr></tbody></table></div>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// /app/tests/cases/models/post.test.php</span><br />
<span style="color: #666666; font-style: italic;">// Then write our new test</span><br />
<span style="color: #000000; font-weight: bold;">function</span> testGetContent<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$post</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findByName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Lorem&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertTrue</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContent</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'Post'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertPattern</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/hello world/i'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>

<p>Run it, watch it fail. And then we add our implementation:</p>

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// /app/models/post.php</span><br />
<span style="color: #000000; font-weight: bold;">function</span> getContent<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$post</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">read</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'Post'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'body'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>

<p>Great, now run it and expect it to pass&#8230;.</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake testsuite app all<br />
...<br />
<span style="color: #000000;">4</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">4</span> <span style="color: #7a0874; font-weight: bold;">test</span> cases complete: <span style="color: #000000;">11</span> passes, <span style="color: #000000;">1</span> fails.</div></td></tr></tbody></table></div>

<p>Wtf!? It failed? Yeah, we forgot to update our fixtures. That&#8217;s it. Every time we update our database, we need to update the fixture. Fortunately, this is one area from Cake that is really painless:</p>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ cake bake fixture all <span style="color: #660033;">-records</span> <span style="color: #660033;">-count</span> <span style="color: #000000;">999</span><br />
...<br />
$ cake testsuite app all<br />
...<br />
<span style="color: #000000;">4</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">4</span> <span style="color: #7a0874; font-weight: bold;">test</span> cases complete: <span style="color: #000000;">12</span> passes.</div></td></tr></tbody></table></div>

<p>The fixture updating part was a little redundant, but it&#8217;s better than manually updating the fixture from SQL and also from <code>*_fixture.php</code>. I suggest you can store all your test fixtures data into an SQL file and make some bash script or ruby script to deconstruct the database and load the test SQL file for each test run. You can play around with different connection settings if you don&#8217;t want to sabotage your main table for every test run. You can package this loading of SQL file and the fixture baking into one script file so that it can be done in one click. (left as an exercise to reader)</p>

<p>That&#8217;s it! In retrospect, it isn&#8217;t rocket science, it&#8217;s just that I haven&#8217;t found any good piece of comprehensive tutorial that hand holds me from start to finish. I&#8217;ve been putting off a lot of unit test writing because I&#8217;ve always had Cake barking errors at me left and right. Now there&#8217;s no excuse <img src='http://cfc.kizzx2.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://cfc.kizzx2.com/index.php/unit-testing-in-cakephp-the-missing-manual-and-a-step-by-step-tutorial/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Super Awesome Advanced CakePHP Tips</title>
		<link>http://cfc.kizzx2.com/index.php/super-awesome-advanced-cakephp-tips/</link>
		<comments>http://cfc.kizzx2.com/index.php/super-awesome-advanced-cakephp-tips/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 21:11:25 +0000</pubDate>
		<dc:creator>kizzx2</dc:creator>
				<category><![CDATA[CakePHP]]></category>

		<guid isPermaLink="false">http://cfc.kizzx2.com/?p=53</guid>
		<description><![CDATA[Super Awesome Advanced CakePHP Tips is free e-book about the CakePHP Framework. It covers topics that are generally missed in the beginner books that are on the market. The CakePHP framework hasn&#8217;t been known for good documentation since its debut almost a couple of years ago. Now that the official manual > Super Awesome Advanced [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="margin-left: 10px; float: right;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcfc.kizzx2.com%2Findex.php%2Fsuper-awesome-advanced-cakephp-tips%2F">
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcfc.kizzx2.com%2Findex.php%2Fsuper-awesome-advanced-cakephp-tips%2F&amp;source=kizzx2&amp;style=normal&amp;b=2" height="61" width="50" />
			</a>
		</div><blockquote>
  <p><a href="http://www.pseudocoder.com/free-cakephp-book/">Super Awesome Advanced CakePHP Tips</a> is free e-book about the CakePHP Framework. It covers topics that are generally missed in the beginner books that are on the market.</p>
</blockquote>

<p>The CakePHP framework hasn&#8217;t been known for good documentation since its debut almost a couple of years ago. Now that the official manual > <a href="http://www.pseudocoder.com/free-cakephp-book/">Super Awesome Advanced CakePHP Tips</a> is free e-book about the CakePHP Framework. It covers topics that are generally missed in the beginner books that are on the market.</p>

<p>The CakePHP framework hasn&#8217;t been known for good documentation since its debut almost a couple of years ago. Now that the official manual <a href="http://book.cakephp.org/">The Cookbook</a> has reached some maturity that this framework is actually possible for more mortals, there still seems to be a lack of materials bridging the masters and the newbies.</p>

<p>Super Awesome Advanced CakePHP Tips by <a href="http://www.pseudocoder.com/">Matt Curry</a> is a good bridge for this gap. It covers topics beyond the basics but that are actually lifesavers when it comes to more complicated CakePHP apps, such as caching, performance, unit testing, configuration/deployment and stuffs.</p>

<p>Reading through the short book gives me a feeling that Matt really knows a lot about this framework. I don&#8217;t know why this book isn&#8217;t more popular than it currently is (maybe it&#8217;s just me, lol).</p>
]]></content:encoded>
			<wfw:commentRss>http://cfc.kizzx2.com/index.php/super-awesome-advanced-cakephp-tips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

