<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Tips and tricks for the CakePHP framework</title>
	<atom:link href="http://taart.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://taart.wordpress.com</link>
	<description>Explaining CakePHP while learning it myself...</description>
	<lastBuildDate>Sun, 26 Jun 2011 09:52:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='taart.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Tips and tricks for the CakePHP framework</title>
		<link>http://taart.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://taart.wordpress.com/osd.xml" title="Tips and tricks for the CakePHP framework" />
	<atom:link rel='hub' href='http://taart.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Twitter autofollow cakephp shell script</title>
		<link>http://taart.wordpress.com/2010/07/28/twitter-autofollow-cakephp-shell-script/</link>
		<comments>http://taart.wordpress.com/2010/07/28/twitter-autofollow-cakephp-shell-script/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 19:17:12 +0000</pubDate>
		<dc:creator>taart</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://taart.wordpress.com/?p=12</guid>
		<description><![CDATA[To promote a website I created some time ago, I thought it would be nice to setup a Twitter account for that site. But how to get some followers? Follow the potential followers first! How to do that? Find tweets with keywords that relate to the site and follow those people, because they are probably [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=12&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>To promote a website I created some time ago, I thought it would be nice to setup a Twitter account for that site. But how to get some followers? Follow the potential followers first! How to do that? Find tweets with keywords that relate to the site and follow those people, because they are probably interested in my site too <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>For this I created a cakephp shell script that will do this magic. One limitation is that Twitter does not allow you to follow more than 2000 people unless you have &#8216;enough&#8217; people following you back. But if your site is interesting enough, you will get followed back.</p>
<p>The code can be improved some more by storing some of the responses in a database, this will speed up the script when you get a lot of followers, maybe later when I have some time again I will add that feature. You need API access to Twitter, please consult the developer pages at twitter.com to learn more about that.</p>
<p>Note: there is a problem with the Twitter search API and the Twitter API, they do not use the same IDs for users, so it is not (yet) possible to do matching on userIDs, we have to use screennames instead, pitty because it slows things down.</p>
<p>So here is the code for the script:</p>
<div style="font-family:Courier;">&lt;?php<br />
class TwitterfollowShell extends Shell {<br />
// Twitter user, password and screenname<br />
private $user=&#8217;userIDforTwitterAccount&#8217;;<br />
private $pass=&#8217;passwordForTwitterAccount&#8217;;<br />
private $screen_name = &#8220;screennameForTwitterAccount&#8221;;function main() {</p>
<p>// $term contains the search words to find in recent tweets<br />
$term = &#8220;twitter+OR+follow+OR+tweet&#8221;;</p>
<p>// Get followers<br />
$cursor = -1;<br />
$followed = array();<br />
do {<br />
$apiUrl = &#8220;http://api.twitter.com/1/statuses/friends/&#8221;.$this-&gt;screen_name.&#8221;.json?cursor=&#8221;.$cursor;<br />
$apiresponse = $this-&gt;callTwitter($apiUrl);<br />
if ($apiresponse) {<br />
echo $cursor.&#8221;\n&#8221;;<br />
$json = json_decode($apiresponse);</p>
<p>$cursor = $json-&gt;next_cursor_str;<br />
if ($json != null) {<br />
foreach ($json-&gt;users as $user) {<br />
$followed[] = strtolower($user-&gt;screen_name);<br />
}<br />
}<br />
}<br />
} while ($apiresponse &amp;&amp; $cursor);</p>
<p>// Get blocked users and add them to the followed array<br />
//        $apiUrl = &#8220;http://api.twitter.com/1/blocks/blocking/ids.json&#8221;;<br />
$blockedUsers = 0;<br />
$page = 1;<br />
do {<br />
$apiUrl = &#8220;http://api.twitter.com/1/blocks/blocking.json?page=&#8221;.$page;<br />
$apiresponse = $this-&gt;callTwitter($apiUrl);<br />
if ($apiresponse) {<br />
$json = json_decode($apiresponse);<br />
if ($json != null) {<br />
foreach ($json as $user) {<br />
$followed[] = strtolower($user-&gt;screen_name);<br />
$blockedUsers++;<br />
}<br />
}<br />
if (count($json) == 20) {<br />
$page++;<br />
} else {<br />
$page = 0;<br />
}<br />
}<br />
} while ($apiresponse &amp;&amp; $page);</p>
<p>// search some keywords !<br />
$apiUrl = &#8220;http://search.twitter.com/search.json?q=&#8221; . $term . &#8220;&amp;rpp=100&#8243;;<br />
$apiresponse = $this-&gt;callTwitter($apiUrl);</p>
<p>if ($apiresponse) {<br />
$results = json_decode($apiresponse);<br />
$count = 20;</p>
<p>if ($results != null) {<br />
$resultsArr = $results-&gt;results;<br />
if (is_array($resultsArr)) {<br />
foreach ($resultsArr as $result) {<br />
$from_user = strtolower($result-&gt;from_user);<br />
if (!in_array($from_user,$followed) ) {<br />
$apiUrl = &#8220;http://twitter.com/friendships/create/&#8221; . $from_user. &#8220;.json&#8221;;<br />
$apiresponse = $this-&gt;callTwitter($apiUrl,true,&#8221;follow=true&#8221;);<br />
if ($apiresponse) {<br />
$response = json_decode($apiresponse);<br />
if ($response != null) {<br />
if (property_exists($response,&#8221;following&#8221;)) {<br />
if ($response-&gt;following === true) {<br />
echo &#8220;Now following &#8221; . $response-&gt;screen_name . &#8220;\n&#8221;;<br />
$followed[] = strtolower($response-&gt;screen_name);<br />
} else {<br />
echo &#8220;Couldn&#8217;t follow &#8221; . $response-&gt;screen_name . &#8220;\n&#8221;;<br />
}<br />
} else {<br />
echo &#8220;Follow limit exceeded, skipped &#8221; . $result-&gt;from_user.&#8221;(&#8220;.$result-&gt;from_user_id . &#8220;)\n&#8221;;<br />
exit;<br />
}<br />
}<br />
}<br />
} else {<br />
// Already following<br />
echo &#8216;.&#8217;;<br />
}<br />
}<br />
}<br />
}<br />
}<br />
}</p>
<p>function callTwitter($apiUrl, $post=false, $postFields = null) {<br />
$ch = curl_init($apiUrl);<br />
curl_setopt($ch, CURLOPT_USERPWD, $this-&gt;user.&#8221;:&#8221;.$this-&gt;pass);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);<br />
if ($post) {<br />
curl_setopt($ch, CURLOPT_POST, 1);<br />
}<br />
if ($postFields) {<br />
curl_setopt($ch, CURLOPT_POSTFIELDS,$postFields);<br />
}<br />
$apiresponse = curl_exec($ch);<br />
curl_close($ch);<br />
return $apiresponse;<br />
}<br />
}<br />
?&gt;</p>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/taart.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/taart.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/taart.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/taart.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/taart.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/taart.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/taart.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/taart.wordpress.com/12/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=12&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://taart.wordpress.com/2010/07/28/twitter-autofollow-cakephp-shell-script/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb4b2af61c22019fd40d3e88be801097?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">taart</media:title>
		</media:content>
	</item>
		<item>
		<title>Problem with $this-&gt;Session-&gt;setFlash when using caching</title>
		<link>http://taart.wordpress.com/2009/10/23/problem-with-this-session-setflash-when-using-caching/</link>
		<comments>http://taart.wordpress.com/2009/10/23/problem-with-this-session-setflash-when-using-caching/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 08:15:01 +0000</pubDate>
		<dc:creator>taart</dc:creator>
				<category><![CDATA[Questions]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://taart.wordpress.com/?p=6</guid>
		<description><![CDATA[Originally posted in the CakePHP Google Groups I have a problem with some cakephp (version 1.2.3.8166 1.2.5) code. It concerns using $this-&#62;Session-&#62;setFlash in a controller action. Part of the controller code: $this-&#62;Session-&#62;setFlash(__(&#8216;Everything fine.&#8217;, true), &#8216;flashinfo&#8217;); $this-&#62;redirect(array(&#8216;controller&#8217;=&#62;&#8217;users&#8217;,'action&#8217;=&#62;&#8217;index&#8217;)); As you can see I use a custom layout for the Flash message called &#8216;flashinfo&#8217;: &#60;div id=&#8221;flashInfoMessage&#8221; style=&#8221;display:none;&#8221;&#62; &#60;?php [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=6&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://groups.google.com/group/cake-php/browse_thread/thread/d889e0555d04490a/8bfcbd25ba77e2c9" target="_blank">Originally posted in the CakePHP Google Groups</a></p>
<p>I have a problem with some cakephp (version <span style="text-decoration:line-through;">1.2.3.8166</span> 1.2.5) code. It<br />
concerns using $this-&gt;Session-&gt;setFlash in a controller action. Part<br />
of the controller code:</p>
<p>$this-&gt;Session-&gt;setFlash(__(&#8216;Everything fine.&#8217;, true), &#8216;flashinfo&#8217;);<br />
$this-&gt;redirect(array(&#8216;controller&#8217;=&gt;&#8217;users&#8217;,'action&#8217;=&gt;&#8217;index&#8217;));</p>
<p>As you can see I use a custom layout for the Flash message called<br />
&#8216;flashinfo&#8217;:</p>
<p>&lt;div id=&#8221;flashInfoMessage&#8221; style=&#8221;display:none;&#8221;&gt;<br />
&lt;?php echo $content_for_layout; ?&gt;<br />
&lt;/div&gt;<br />
&lt;script language=&#8221;JavaScript&#8221; type=&#8221;text/javascript&#8221;&gt;<br />
&lt;!&#8211;<br />
Flash.show(&#8216;flashInfoMessage&#8217;);<br />
//&#8211;&gt;<br />
&lt;/script&gt;</p>
<p>code for the javascript Flash class:<br />
Flash={<br />
show:function(element){<br />
$(element).visualEffect(&#8216;appear&#8217;);<br />
this.timer=setTimeout(&#8216;Flash.hide(&#8220;&#8216;+element+&#8217;&#8221;)&#8217;,7000);<br />
},<br />
hide:function(element){<br />
$(element).visualEffect(&#8216;fade&#8217;);<br />
clearTimeout(this.timer);<br />
return false;<br />
}<br />
};</p>
<p>What this does is show the flash message for 7 seconds after which it<br />
will be hidden by using the nice scriptaculous effect Fade.</p>
<p>I have two of these layouts, one for informational messages (green<br />
background) and one for errors (red background).</p>
<p>This all works perfectly fine as long as I do not use cake view<br />
caching. But of course I want to have caching in the site for speed.</p>
<p>To render the flash message I placed this into the layout<br />
(default.ctp):</p>
<p>&lt;cake:nocache&gt;<br />
&lt;?php $session-&gt;flash(); ?&gt;<br />
&lt;/cake:nocache&gt;</p>
<p>With caching turned on and a cached version of the page being rendered<br />
already present in the cache, this generates the following error as<br />
soon as the redirect is performed and the specified URL in the<br />
redirect is being rendered:</p>
<p>Notice (8): Trying to get property of non-object [CORE/cake_1.2.3.8166/<br />
libs/view/helpers/session.php, line 145]</p>
<p>Code | Context</p>
<p>$key    =       &#8220;flash&#8221;<br />
$flash  =       array(<br />
&#8220;message&#8221; =&gt; &#8220;Uw contactformulier is verzonden.&#8221;,<br />
&#8220;layout&#8221; =&gt; &#8220;flashinfo&#8221;,<br />
&#8220;params&#8221; =&gt; array()<br />
)<br />
$view   =       false</p>
<p>} else {<br />
$view =&amp; ClassRegistry::getObject(&#8216;view&#8217;);<br />
list($tmpLayout, $tmpVars, $tmpTitle) = array<br />
($view-&gt;layout, $view-&gt;viewVars, $view-&gt;pageTitle);</p>
<p>SessionHelper::flash() &#8211; CORE/cake_1.2.3.8166/libs/view/helpers/<br />
session.php, line 145<br />
include &#8211; APP/tmp/cache/views/home.php, line 72<br />
View::renderCache() &#8211; CORE/cake_1.2.3.8166/libs/view/view.php, line<br />
495<br />
Dispatcher::cached() &#8211; CORE/cake_1.2.3.8166/dispatcher.php, line 678<br />
Dispatcher::dispatch() &#8211; CORE/cake_1.2.3.8166/dispatcher.php, line 123<br />
[main] &#8211; APP/webroot/index.php, line 88</p>
<p>Fatal error: Call to undefined method stdClass::renderLayout() in /usr/<br />
www/htdocs/afvalcontainer/cake_1.2.3.8166/libs/view/helpers/<br />
session.php on line 147</p>
<p>The error does not occur on first time rendering of the page,<br />
everything works as expected in that case. Also when caching is<br />
globally turned off, everything works as expected.</p>
<p>Any ideas of what I am doing wrong ? Or is this a bug ?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/taart.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/taart.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/taart.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/taart.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/taart.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/taart.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/taart.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/taart.wordpress.com/6/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=6&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://taart.wordpress.com/2009/10/23/problem-with-this-session-setflash-when-using-caching/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb4b2af61c22019fd40d3e88be801097?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">taart</media:title>
		</media:content>
	</item>
		<item>
		<title>The HABTM drama continues</title>
		<link>http://taart.wordpress.com/2007/11/29/the-habtm-drama-continues/</link>
		<comments>http://taart.wordpress.com/2007/11/29/the-habtm-drama-continues/#comments</comments>
		<pubDate>Thu, 29 Nov 2007 20:54:23 +0000</pubDate>
		<dc:creator>taart</dc:creator>
				<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://taart.wordpress.com/2007/11/29/the-habtm-drama-continues/</guid>
		<description><![CDATA[I&#8217;m not happy, thought I worked it out: how to paginate a model with multiple HABTM associations like I wrote in my previous blog post. But no, well the first page I get back from the query is ok. But when going to page 2, which is the last page according to what is shown [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=5&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not happy, thought I worked it out: how to paginate a model with multiple HABTM associations like I wrote in my previous blog post. But no, well the first page I get back from the query is ok. But when going to page 2, which is the last page according to what is shown on page 1, I get some results from page 1 and suddenly there is a total of 5 pages (all records from the database). Going back from page 2 to page 1 by clicking the pagination navigation link, I get a different page 1 then the one I got initially. Back to the drawing board ?</p>
<p>What&#8217;s happing is this: the initial search parameters that are fed to the controller from the form are not passed on to the next page. The only thing passed is the page number. In <a href="http://bakery.cakephp.org/articles/view/advanced-pagination-1-2" target="_blank">this article at the cake bakery</a> I found a possible solution. What Rob Conner suggests there is to use sessions to pass along the search parameters. Guess I will try to implement it like that. Not a very clean solution in my opinion. I think CakePHP is still missing some functionality in the pagination part. It all works fine of course if you specify fixed conditions in the controller, but it does not seem &#8216;automagic&#8217; when you feed the controller with parameters from a form.</p>
<p>The way I&#8217;m feeding the parameters, through a &#8216;post&#8217; form, might be the cause. See, the page links (previous, next and page numbers) are nothing more than just html links (&lt;a&gt; tag), so the link should contain the paramters. This is possible by using a &#8216;get&#8217; form, but that doesn&#8217;t create such nice URLs (you will see your database field names). Another option could be using a form with hidden fields that is submitted when clicking the page links, but I&#8217;m not sure yet if that is possible with the pagination functions provided by Cake. So I think for now I will take the session approach.</p>
<p>There must be more of you running into problems like this. I wonder how you solve these kind of things with Cake. Please leave a comment with your solution(s).</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/taart.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/taart.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/taart.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/taart.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/taart.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/taart.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/taart.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/taart.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/taart.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/taart.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=5&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://taart.wordpress.com/2007/11/29/the-habtm-drama-continues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb4b2af61c22019fd40d3e88be801097?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">taart</media:title>
		</media:content>
	</item>
		<item>
		<title>Getting what you want with HABTM using multiple models and pagination&#8230;</title>
		<link>http://taart.wordpress.com/2007/11/28/getting-what-you-want-with-habtm-using-multiple-models-and-pagination/</link>
		<comments>http://taart.wordpress.com/2007/11/28/getting-what-you-want-with-habtm-using-multiple-models-and-pagination/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 23:29:15 +0000</pubDate>
		<dc:creator>taart</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[cakephp1.2]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[habtm]]></category>
		<category><![CDATA[model]]></category>

		<guid isPermaLink="false">http://taart.wordpress.com/2007/11/28/getting-what-you-want-with-habtm-using-multiple-models-and-pagination/</guid>
		<description><![CDATA[Oh my o my&#8230; This has cost me hours/days. Maybe it&#8217;s easy if you&#8217;re a long term CakePHPer. But I just started developing with this framework, also never used anything like an MVC framework before. Ok, I know how to do databases, php, javascript,etc&#8230; But this is something else. The basics of CakePHP are quite [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=3&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://taart.files.wordpress.com/2007/11/dbschema.jpg" alt="dbschema" align="right" />Oh my o my&#8230; This has cost me hours/days. Maybe it&#8217;s easy if you&#8217;re a long term CakePHPer. But I just started developing with this framework, also never used anything like an MVC framework before. Ok, I know how to do databases, php, javascript,etc&#8230; But this is something else. The basics of CakePHP are quite easy to understand and use. Simple stuff like you read in the tutorials: a user has posts, a post has comments. These are all hasMany and belongTo relations, those just work fine when doing pagination. But then you have something like Posts have Tags. Then you get into the hasAndBelongsToMany (HABTM) arena, where the &#8216;fun&#8217; begins&#8230; With just to tables and doing a findAll or paginate is still not all that complicated. (by the way I&#8217;m using nightly builds of the 1.2 version).</p>
<p>So what has given me so much &#8216;stress&#8217; the past few days? Well, I&#8217;m developing a site that now has something like 30 tables (habtm join tables included), not all that big yet. But I have one table (addresses) that has multiple habtm relations (sections, areas, tags; among others). Still no problem if you just do a plain findAll(), but what if you want to search for  addresses that are linked to a certain section AND area and maybe even a tag? To make it even more complex, an address hasMany telephone numbers, URLs and belongs to a user and a country and hasOne logo. There is more in the model but this gives you an idea of what I&#8217;m doing.</p>
<p>So I present a form to the user of the site. The form has some SELECTs where the user can select which section, area, tag and/or zip code to find addresses for. The result should be a paginated presentation of addresses. An address consists of fields like: company name, street name, zip code, telephone number(s), URL(s), logo, etc.. Here comes the somewhat simplified code (there are some comments in the controller code to explain what happens):</p>
<p><span id="more-3"></span><em><strong>(Please note</strong> that this code will not work just like that, these are just some code fragments to show how I did my implementation. If you want some more info, please leave a comment. If you find an error, type or other, let me know and I will fix it. Thanks.)</em></p>
<p><strong>Model for Addresses<br />
</strong></p>
<pre>class Address extends AppModel {
  var $name = 'Address';
  var $belongsTo = array(
    'Country' =&gt; array('className' =&gt; 'Country',
    'foreignKey' =&gt; 'country_id'),

    'User' =&gt; array('className' =&gt; 'User',
    'foreignKey' =&gt; 'user_id'),
  );

  var $hasOne = array(
    'Logo' =&gt; array('className' =&gt; 'Logo',
    'foreignKey' =&gt; 'user_id',
    'depent' =&gt; true),
  );

  var $hasMany = array(
    'Telephonenumber' =&gt; array('className' =&gt; 'Telephonenumber',
    'foreignKey' =&gt; 'address_id'),
    'Website' =&gt; array('className' =&gt; 'Website',
    'foreignKey' =&gt; 'address_id'),
  );

  var $hasAndBelongsToMany = array(
    'Area' =&gt; array('className' =&gt; 'Area',
    'joinTable' =&gt; 'addresses_areas',
    'foreignKey' =&gt; 'address_id',
    'associationForeignKey' =&gt; 'area_id'),

    'Section' =&gt; array('className' =&gt; 'Section',
    'joinTable' =&gt; 'addresses_sections',
    'foreignKey' =&gt; 'address_id',
    'associationForeignKey' =&gt; 'section_id'),

    'Keyword' =&gt; array('className' =&gt; 'Keyword',
    'joinTable' =&gt; 'addresses_keywords',
    'foreignKey' =&gt; 'address_id',
    'associationForeignKey' =&gt; 'keyword_id'),
  );
}</pre>
<p><strong>Model for join table</strong><br />
You should have one for each habtm join table</p>
<pre>class AddressesSection extends AppModel {
  var $name='AddressesSection';
  var $belongsTo=array('Address', 'Section');
}</pre>
<p><strong>join table example</strong></p>
<pre>id, integer, primary, autoinc
address_id, integer
section_id, integer</pre>
<p><strong>Controller for the query form</strong></p>
<pre>class SearchController extends AppController {
  var $name = 'Search';
  var $uses = array('Section','Area','Keyword');
  var $helpers = array('Html', 'Form', 'Ajax');
  function index() {
    $areas = $this-&gt;Area-&gt;generateList();
    $sections = $this-&gt;Section-&gt;generateList();
    $keywords = $this-&gt;Keyword-&gt;generateList();
    $this-&gt;set(compact('areas', 'sections', 'keywords'));
  }
}</pre>
<p><strong>Controller to do the query</strong></p>
<pre>function search() {

/* bind the HABTM tables to the Address table using a hasOne
   relationship (see sources below for explanation on this) */

  $this-&gt;Address-&gt;bindModel(array('hasOne'=&gt;array('AddressesArea'=&gt;array())),false);
  $this-&gt;Address-&gt;bindModel(array('hasOne'=&gt;array('AddressesKeyword'=&gt;array())),false);
  $this-&gt;Address-&gt;bindModel(array('hasOne'=&gt;array('AddressesSection'=&gt;array())),false);

/* set the fields that should be returned by the paginate() call, this
   basically is what you would normally do in a sql SELECT statement
   to specify which columns the query should return. This is just for
   the query on the addresses table. For the end result cake will also
   give you all the HABTM stuff associated with each address, nice!
   The DISTINCT is important here, because of all the associations to
   many rows would be returned otherwise. */

  $this-&gt;paginate['fields'] = array('DISTINCT Address.id', 'name',
                    'street', 'zip', 'city','Country.*','Logo.*');

// ok, fire-up the query already! result is placed in $addresses for the View

  $this-&gt;set('addresses',$this-&gt;paginate('Address',Set::filter($this-&gt;postConditions($this-&gt;data))));
}</pre>
<p>(I will explain the Set::filter($this-&gt;postConditions($this-&gt;data))) in another article)</p>
<p><strong>View for query form (query.ctp)</strong></p>
<pre>&lt;div class="search form"&gt;
&lt;?php echo $form-&gt;create('Address',array('url' =&gt; '/addresses/search'));?&gt;
&lt;fieldset&gt;
&lt;legend&gt;&lt;?php __('Search Address');?&gt;&lt;/legend&gt;
&lt;?php

/* Note: use the join table field name (AddressesSection.section_id)
   here as a name for the INPUTs, otherwise the cool PostConditions
   function in the Controller won't work. */

echo $form-&gt;input('AddressesSection.section_id', array('type'=&gt;'select',
     'label'=&gt;__('Section',true), 'empty'=&gt;true, 'selected'=&gt;0));
echo $form-&gt;input('AddressesArea.area_id', array('type'=&gt;'select',
     'label'=&gt;__('Area',true), 'empty'=&gt;true, 'empty'=&gt;true, 'selected'=&gt;0));
echo '&lt;label for="Keyword"&gt;';
__('Tag');
echo '&lt;/label&gt;';
echo $ajax-&gt;autoComplete('AddressesTag.tag_id','/tags/autoComplete');
echo $form-&gt;input('zip');
?&gt;
&lt;/fieldset&gt;
&lt;?php echo $form-&gt;end('Submit');?&gt;
&lt;/div&gt;</pre>
<p><strong>View for end result (search.ctp)</strong></p>
<pre>/* there should be code here to check if all data really exists before
   using it, but this is for demo purpose only */
foreach ($addresses as $address) {
  echo $address['Address']['name'].'&lt;br /&gt;';
  echo $address['Address']['street'].'&lt;br /&gt;';
  echo $address['Address']['zip'].' '.$address['Address']['city'].'&lt;br /&gt;';
  foreach ($address['Tags'] as $tag) {
    echo $tag['tag].' ';
  }
  echo '&lt;br /&gt;';
}</pre>
<p>Now that it is finished (well this part is), not that much code at all. But it took me hours of trying this and that, reading loads of web pages, articles and the manual, tearing the little hair I have left off of my head&#8230;</p>
<p>Sources I used to come to this solution (and believe me, I read a lot more than just what&#8217;s on these links, my eyes, my Eyes, arghhh). Thanks to all the people that wrote this stuff, it helped me a lot:</p>
<p><a href="http://www.nabble.com/Help-me-with-paginate,-please---)-t4760463.html" target="_blank">nabble.com &#8211; Help me with paginate, please</a></p>
<p><a href="http://groups.google.com/group/cake-php/browse_frm/thread/d0e535b3b87bd75f" target="_blank">Paginating the results after creating a dummy model to filter HABTM results? </a></p>
<p><a href="http://groups.google.com/group/cake-php/browse_frm/thread/f23b1825050ad543" target="_blank">Filtering HABTM associations using columns in both models</a></p>
<p><a href="http://tempdocs.cakephp.org/" target="_blank">CakePHP 1.2 manual</a></p>
<p>But it works now, so I&#8217;m happy and can continue baking the rest. Hope that things will get a bit easier now, because that&#8217;s what CakePHP should do for us right: make development life a bit easier / less <a href="http://en.wikipedia.org/wiki/Stress_(medicine)" target="_blank">stressful</a>. So maybe this article will help some of you creating that wonderful website, leave a comment if you like. Also tips on this subject are very welcome, maybe I did something completely wrong here. This article cost me more than an hour to write, I need sleep now&#8230;</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/taart.wordpress.com/3/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/taart.wordpress.com/3/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/taart.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/taart.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/taart.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/taart.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/taart.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/taart.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/taart.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/taart.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=3&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://taart.wordpress.com/2007/11/28/getting-what-you-want-with-habtm-using-multiple-models-and-pagination/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb4b2af61c22019fd40d3e88be801097?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">taart</media:title>
		</media:content>

		<media:content url="http://taart.files.wordpress.com/2007/11/dbschema.jpg" medium="image">
			<media:title type="html">dbschema</media:title>
		</media:content>
	</item>
		<item>
		<title>Hello and welcome to my Piece of Cake!</title>
		<link>http://taart.wordpress.com/2007/11/28/hello-world/</link>
		<comments>http://taart.wordpress.com/2007/11/28/hello-world/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 21:16:24 +0000</pubDate>
		<dc:creator>taart</dc:creator>
				<category><![CDATA[Site news]]></category>
		<category><![CDATA[cakephp]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Hi there, this is taart.wordpress.com. What is &#8216;taart&#8217; ? Well it&#8217;s Dutch for &#8216;cake&#8217; and since this blog is about CakePHP&#8230; yeah I know, but the thing must have a name. Hope you find what you find here usefull. Happy baking, Steve<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=1&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hi there, this is taart.wordpress.com. What is &#8216;taart&#8217; ? Well it&#8217;s Dutch for &#8216;cake&#8217; and since this blog is about <a href="http://www.cakephp.org/" target="_blank">CakePHP</a>&#8230; yeah I know, but the thing must have a name. Hope you find what you find here usefull.</p>
<p>Happy <a href="http://www.opensourcefood.com/" target="_blank">baking</a>,</p>
<address>Steve </address>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/taart.wordpress.com/1/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/taart.wordpress.com/1/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/taart.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/taart.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/taart.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/taart.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/taart.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/taart.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/taart.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/taart.wordpress.com/1/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=taart.wordpress.com&amp;blog=2222615&amp;post=1&amp;subd=taart&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://taart.wordpress.com/2007/11/28/hello-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb4b2af61c22019fd40d3e88be801097?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">taart</media:title>
		</media:content>
	</item>
	</channel>
</rss>
