<?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>Tony Thomas &#187; CakePHP</title>
	<atom:link href="http://anthonygthomas.com/category/web-development/php/cakephp-php/feed/" rel="self" type="application/rss+xml" />
	<link>http://anthonygthomas.com</link>
	<description>This is my blog.</description>
	<lastBuildDate>Thu, 25 Feb 2010 12:59:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>CakePHP: Containable Behavior is Your Friend</title>
		<link>http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/</link>
		<comments>http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 16:21:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[containable behavior]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[behaviors]]></category>
		<category><![CDATA[containable]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=369</guid>
		<description><![CDATA[When it comes to optimizing your CakePHP queries, you need to abandon Recursive and adopt Containable.
In the example below I have the following models:

Patient
Specimen
Result
ResultType

The associations in the model are:

Result

belongsTo

ResultType

hasMany

Result




Patient

hasMany

Result
Specimen




Specimen

belongsTo

Patient


hasMany

Result










$paginate in the Result Controller
Original version
var $paginate = array(
		'fields' =&#62; array(
			'ResultType.type',
			'Specimen.draw_date',
			'Result.id',
			'Result.patient_id',
			'Result.specimen_id',
			'Result.result',
			'Result.created',
			'Result.modified'
			),
		'recursive' =&#62; 0,
		'limit' =&#62; 50);
The Same Thing Using Containable
var $paginate = array(
		'fields' =&#62; array(
			'id',
			'patient_id',
			'specimen_id',
			'result',
			'created',
			'modified'
			),
		'limit' =&#62; 50,
		'contain' =&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes to optimizing your CakePHP queries, you need to abandon Recursive and adopt Containable.</p>
<p>In the example below I have the following models:</p>
<ul>
<li>Patient</li>
<li>Specimen</li>
<li>Result</li>
<li>ResultType</li>
</ul>
<p>The associations in the model are:</p>
<ul>
<li>Result
<ul>
<li>belongsTo
<ul>
<li>ResultType
<ul>
<li>hasMany
<ul>
<li>Result</li>
</ul>
</li>
</ul>
</li>
<li>Patient
<ul>
<li>hasMany
<ul>
<li>Result</li>
<li>Specimen</li>
</ul>
</li>
</ul>
</li>
<li>Specimen
<ul>
<li>belongsTo
<ul>
<li>Patient</li>
</ul>
</li>
<li>hasMany
<ul>
<li>Result</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><span id="more-369"></span><br />
<h3>$paginate in the Result Controller</h3>
<h4>Original version</h4>
<pre class="brush: php; highlight: [12];">var $paginate = array(
		'fields' =&gt; array(
			'ResultType.type',
			'Specimen.draw_date',
			'Result.id',
			'Result.patient_id',
			'Result.specimen_id',
			'Result.result',
			'Result.created',
			'Result.modified'
			),
		'recursive' =&gt; 0,
		'limit' =&gt; 50);</pre>
<h4>The Same Thing Using Containable</h4>
<pre class="brush: php; highlight: [11,12,13,14,15,16,17,18,19,20,21,22,23];">var $paginate = array(
		'fields' =&gt; array(
			'id',
			'patient_id',
			'specimen_id',
			'result',
			'created',
			'modified'
			),
		'limit' =&gt; 50,
		'contain' =&gt; array(
			'ResultType' =&gt; array(
				'fields' =&gt; array(
					'ResultType.type',
					'ResultType.id'
					)
				),
			'Specimen' =&gt; array(
				'fields' =&gt; array(
					'Specimen.id',
					'Specimen.draw_date'
					)
				)
			)
		);</pre>
<h3>The SQL</h3>
<h4>SQL Generated from the Original $paginate var</h4>
<pre class="brush: sql; highlight: [7,8,19,20];">SELECT COUNT(*) AS `count`
FROM `results` AS `Result`
LEFT JOIN `result_types` AS `ResultType`
ON (`Result`.`result_type_id` = `ResultType`.`id`)
LEFT JOIN `specimens` AS `Specimen`
ON (`Result`.`specimen_id` = `Specimen`.`id`)
LEFT JOIN `patients` AS `Patient`
ON (`Result`.`patient_id` = `Patient`.`id`)
WHERE 1 = 1

/* 1879 milliseconds */

SELECT `ResultType`.`type`, `Specimen`.`draw_date`, `Result`.`id`, `Result`.`patient_id`, `Result`.`specimen_id`, `Result`.`result`, `Result`.`created`, `Result`.`modified`
FROM `results` AS `Result`
LEFT JOIN `result_types` AS `ResultType`
ON (`Result`.`result_type_id` = `ResultType`.`id`)
LEFT JOIN `specimens` AS `Specimen`
ON (`Result`.`specimen_id` = `Specimen`.`id`)
LEFT JOIN `patients` AS `Patient`
ON (`Result`.`patient_id` = `Patient`.`id`)
WHERE 1 = 1
ORDER BY `Result`.`created` desc
LIMIT 50

/* 2106 milliseconds */</pre>
<h4>SQL Generated Using Containable Behavior</h4>
<pre class="brush: sql;">SELECT COUNT(*) AS `count`
FROM `results` AS `Result`
LEFT JOIN `result_types` AS `ResultType`
ON (`Result`.`result_type_id` = `ResultType`.`id`)
LEFT JOIN `specimens` AS `Specimen`
ON (`Result`.`specimen_id` = `Specimen`.`id`)
WHERE 1 = 1

/* 10 milliseconds */

SELECT `Result`.`id`, `Result`.`patient_id`, `Result`.`specimen_id`, `Result`.`result`, `Result`.`created`, `Result`.`modified`, `ResultType`.`type`, `ResultType`.`id`, `Specimen`.`id`, `Specimen`.`draw_date`
FROM `results` AS `Result`
LEFT JOIN `result_types` AS `ResultType`
ON (`Result`.`result_type_id` = `ResultType`.`id`)
LEFT JOIN `specimens` AS `Specimen`
ON (`Result`.`specimen_id` = `Specimen`.`id`)
WHERE 1 = 1
ORDER BY `Result`.`created` desc
LIMIT 50

/* 19 milliseconds */</pre>
<h3>The Difference</h3>
<p>The first set of queries took nearly 4 seconds. The second: 29 milliseconds. Containable just gives you so much more control over what&#8217;s selected in your query. Using <code>recursive =&gt; 0</code> still joined the patients table both times even though we didn&#8217;t need it because it was associated in the model. Using the Containable Behavior in the second example removed the patients table from the queries altogether.</p>
<p>This is one of the key pitfalls of using a framework like CakePHP; You can get things running quickly, but you have to go back and optimize. Otherwise you can build a heavy load on the server.</p>
<h3>Resources</h3>
<ul>
<li><a title="CakePHP Framework" href="http://cakephp.org" onclick="pageTracker._trackPageview('/outgoing/cakephp.org?referer=');">CakePHP</a></li>
<li><a href="http://book.cakephp.org/view/474/Containable" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/474/Containable?referer=');">The Containable Behavior</a></li>
<li><a title="The Recursive Model Attribute" href="http://book.cakephp.org/view/439/recursive" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/439/recursive?referer=');">The Recursive Model Attribute</a></li>
</ul>
<p><strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/" rel="bookmark" title="February 18, 2010">CakePHP: Containable Behavior is Your Friend</a></li>
<li><a href="http://anthonygthomas.com/2008/12/10/use-functions-from-other-controllers-while-maintaining-mvc-architecture-in-cakephp/" rel="bookmark" title="December 10, 2008">Use Functions from Other Controllers While Maintaining MVC Architecture in CakePHP</a></li>
<li><a href="http://anthonygthomas.com/2008/11/26/getting-blueprint-css-javascript-libraries-into-your-cakephp-layout/" rel="bookmark" title="November 26, 2008">Getting Blueprint CSS &#038; JavaScript Libraries Into Your CakePHP Layout</a></li>
<li><a href="http://anthonygthomas.com/2009/05/22/roll-your-own-cakephp-components/" rel="bookmark" title="May 22, 2009">Roll Your Own CakePHP Components</a></li>
<li><a href="http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/" rel="bookmark" title="July 22, 2009">Simple Security in CakePHP</a></li>
</ul>
<p><!-- Similar Posts took 6.452 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Security in CakePHP</title>
		<link>http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/</link>
		<comments>http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 01:23:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[components]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=134</guid>
		<description><![CDATA[When I started to dig in to investigate using the Security Component of CakePHP, I was a bit daunted. It took me quite a while to get my head around ACL after all. Then I found this article. Here&#8217;s the crux:
The Security component will create a hash based on the form fields produced by our [...]]]></description>
			<content:encoded><![CDATA[<p>When I started to dig in to investigate using the <a href="http://book.cakephp.org/view/175/Security-Component" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/175/Security-Component?referer=');">Security Component</a> of <a href="http://cakephp.org" onclick="pageTracker._trackPageview('/outgoing/cakephp.org?referer=');">CakePHP</a>, I was a bit daunted. It took me quite a while to get my head around <a href="http://book.cakephp.org/view/171/Access-Control-Lists" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/171/Access-Control-Lists?referer=');">ACL</a> after all. Then I found <a href="http://teknoid.wordpress.com/2008/11/05/make-your-cakephp-forms-a-lot-more-secure/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/teknoid.wordpress.com/2008/11/05/make-your-cakephp-forms-a-lot-more-secure/?referer=');">this article</a>. Here&#8217;s the crux:</p>
<blockquote><p>The Security component will create a hash based on the form fields produced by our Form Helper. If someone tampers with the form fields (by adding or removing or changing any field), the hash is not going to match with the expected one and the add() action will fail.</p>
<p>Yep, it’s that simple.</p></blockquote>
<p>Really? It just can&#8217;t be that easy, can it? Yes. It can. I simply added the Security Component to my controller like so:</p>

<div class="wp_syntax"><div class="code"><pre class="language" style="font-family:monospace;">var $components = array('Security');</pre></div></div>

<p>Sure enough, when I reloaded a page with a form in my browser, this hidden field was there:</p>

<div class="wp_syntax"><div class="code"><pre class="language" style="font-family:monospace;">&lt;input id=&quot;TokenFields1483167134&quot; name=&quot;data[_Token][fields]&quot; type=&quot;hidden&quot; value=&quot;f513aebc448fabe42c7feedf31d43fa5bd71ec79%3An%3A0%3A%7B%7D&quot; /&gt;</pre></div></div>

<p>I installed a Firefox Add-on that allowed me to tamper with the POST data, and when I submitted the form, it failed, or in CakePHP terms, it was &#8220;<a href="http://book.cakephp.org/view/267/blackHole-object-controller-string-error" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/267/blackHole-object-controller-string-error?referer=');">Blackholed</a>.&#8221; Awesome.</p>
<p>This isn&#8217;t going to protect me from all attacks, but it certainly is a good, easy start to implementing security in my application.<strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/" rel="bookmark" title="July 22, 2009">Simple Security in CakePHP</a></li>
<li><a href="http://anthonygthomas.com/2009/05/22/roll-your-own-cakephp-components/" rel="bookmark" title="May 22, 2009">Roll Your Own CakePHP Components</a></li>
<li><a href="http://anthonygthomas.com/2008/09/22/and-were-back/" rel="bookmark" title="September 22, 2008">And We&#8217;re Back!</a></li>
<li><a href="http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/" rel="bookmark" title="February 18, 2010">CakePHP: Containable Behavior is Your Friend</a></li>
<li><a href="http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/" rel="bookmark" title="June 20, 2008">Wow. ACL is Hard</a></li>
</ul>
<p><!-- Similar Posts took 4.787 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP Console ACL Help File</title>
		<link>http://anthonygthomas.com/2009/03/22/cakephp-console-acl-help-file/</link>
		<comments>http://anthonygthomas.com/2009/03/22/cakephp-console-acl-help-file/#comments</comments>
		<pubDate>Sun, 22 Mar 2009 15:30:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ACL]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[cli]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=95</guid>
		<description><![CDATA[Every now and then I want to view my help files in pretty, formatted HTML instead of plain text in a text editor or terminal window. Right now I&#8217;m working on setting up some Access Control Lists (ACL) in the CakePHP Console. ACL is a powerful, yet sometimes hard-to-grasp concept. I always figure that if [...]]]></description>
			<content:encoded><![CDATA[<p>Every now and then I want to view my help files in pretty, formatted HTML instead of plain text in a text editor or terminal window. Right now I&#8217;m working on setting up some Access Control Lists (ACL) in the <a href="http://book.cakephp.org/view/108/the-cakephp-console" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/108/the-cakephp-console?referer=');">CakePHP Console</a>. ACL is a powerful, yet sometimes hard-to-grasp concept. I always figure that if I want a resource like this, there has to be someone else out there who does, so for your reference and mine, here it is. (By the way, to get to this from the console, simply type <code>cake acl help</code>.)</p>
<p>Usage: <code>cake acl &lt;command&gt; &lt;arg1&gt; &lt;arg2&gt;...<!--formatted--></code><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Commands:</p>
<p><code>create aro|aco &lt;parent&gt; &lt;node&gt;<!--formatted--></code><br />
Creates a new ACL object &lt;node&gt; under the parent specified by &lt;parent&gt;, an id/alias.<br />
The &lt;parent&gt; and &lt;node&gt; references can be in one of the following formats:</p>
<ul>
<li> &#8211; &lt;model&gt;.&lt;id&gt; &#8211; The node will be bound to a specific record of the given model</li>
<li>- &lt;alias&gt; &#8211; The node will be given a string alias (or path, in the case of &lt;parent&gt;),</li>
</ul>
<p>i.e. &#8216;John&#8217;.  When used with &lt;parent&gt;, this takes the form of an alias path,<br />
i.e. &lt;group&gt;/&lt;subgroup&gt;/&lt;parent&gt;.<br />
To add a node at the root level, enter &#8216;root&#8217; or &#8216;/&#8217; as the &lt;parent&gt; parameter.</p>
<p><code>delete aro|aco &lt;node&gt;<!--formatted--></code><br />
Deletes the ACL object with the given &lt;node&gt; reference (see &#8216;create&#8217; for info on node references).</p>
<p><code>setParent aro|aco &lt;node&gt; &lt;parent&gt;<!--formatted--></code><br />
Moves the ACL object specified by &lt;node&gt; beneath the parent ACL object specified by &lt;parent&gt;.<br />
To identify the node and parent, use the row id.</p>
<p><code>getPath aro|aco &lt;node&gt;<!--formatted--></code><br />
Returns the path to the ACL object specified by &lt;node&gt;. This command is useful in determining the inhertiance of permissions for a certain object in the tree.<br />
For more detailed parameter usage info, see help for the &#8216;create&#8217; command.</p>
<p><code>check &lt;aro_id&gt; &lt;aco_id&gt; [&lt;aco_action&gt;] or all<!--formatted--></code><br />
Use this command to check ACL permissions.<br />
For more detailed parameter usage info, see help for the &#8216;create&#8217; command.</p>
<p><code>grant &lt;aro_id&gt; &lt;aco_id&gt; [&lt;aco_action&gt;] or all<!--formatted--></code><br />
Use this command to grant ACL permissions. Once executed, the ARO specified (and its children, if any) will have ALLOW access to the specified ACO action (and the ACO&#8217;s children, if any). For more detailed parameter usage info, see help for the &#8216;create&#8217; command.</p>
<p><code>deny &lt;aro_id&gt; &lt;aco_id&gt; [&lt;aco_action&gt;]or all<!--formatted--></code><br />
Use this command to deny ACL permissions. Once executed, the ARO specified (and its children, if any) will have DENY access to the specified ACO action (and the ACO&#8217;s children, if any). For more detailed parameter usage info, see help for the &#8216;create&#8217; command.</p>
<p><code>inherit &lt;aro_id&gt; &lt;aco_id&gt; [&lt;aco_action&gt;]or all<!--formatted--></code><br />
Use this command to force a child ARO object to inherit its permissions settings from its parent. For more detailed parameter usage info, see help for the &#8216;create&#8217; command.</p>
<p><code>view aro|aco [&lt;node&gt;]<!--formatted--></code><br />
The view command will return the ARO or ACO tree. The optional id/alias parameter allows you to return only a portion of the requested tree. For more detailed parameter usage info, see help for the &#8216;create&#8217; command.</p>
<p><code>initdb</code><br />
Uses this command : <code>cake schema run create DbAcl</code></p>
<p><code>help [&lt;command&gt;]<!--formatted--></code><br />
Displays this help message, or a message on a specific command.</p>
<h3>The &#8216;create&#8217; help file</h3>
<p>Usage: cake acl &lt;command&gt; &lt;arg1&gt; &lt;arg2&gt;&#8230;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<ul>
<li>Commands:
<ul>
<li><code>create aro|aco &lt;parent&gt; &lt;node&gt;<code> </code><!--formatted--></code>
<ul>
<li>Creates a new ACL object <code>&lt;node&gt;<!--formatted--></code> under the parent specified by <code>&lt;parent&gt;<!--formatted--></code>, an id/alias. The <code>&lt;parent&gt; and &lt;node&gt;<!--formatted--></code> references can be in one of the following formats:
<ul>
<li>- <code>&lt;model&gt;.&lt;id&gt;<!--formatted--></code> &#8211; The node will be bound to a specific record of the given model</li>
<li>- <code>&lt;alias&gt;<!--formatted--></code> &#8211; The node will be given a string alias (or path, in the case of <code>&lt;parent&gt;<!--formatted--></code>), i.e. &#8216;John&#8217;.  When used with <code>&lt;parent&gt;<!--formatted--></code>, this takes the form of an alias path, i.e. <code>&lt;group&gt;/&lt;subgroup&gt;/&lt;parent&gt;<!--formatted--></code>. To add a node at the root level, enter &#8216;root&#8217; or &#8216;/&#8217; as the <code>&lt;parent&gt;<!--formatted--></code> parameter.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2009/03/22/cakephp-console-acl-help-file/" rel="bookmark" title="March 22, 2009">CakePHP Console ACL Help File</a></li>
<li><a href="http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/" rel="bookmark" title="June 20, 2008">Wow. ACL is Hard</a></li>
<li><a href="http://anthonygthomas.com/2008/04/10/googles-appengine/" rel="bookmark" title="April 10, 2008">Google&#8217;s AppEngine</a></li>
<li><a href="http://anthonygthomas.com/2008/11/26/getting-blueprint-css-javascript-libraries-into-your-cakephp-layout/" rel="bookmark" title="November 26, 2008">Getting Blueprint CSS &#038; JavaScript Libraries Into Your CakePHP Layout</a></li>
<li><a href="http://anthonygthomas.com/2008/11/25/wordpress-auto-update-is-ok-but-the-command-line-is-faster/" rel="bookmark" title="November 25, 2008">Wordpress&#8217; Auto Update Is OK, But The Command Line Is Faster</a></li>
</ul>
<p><!-- Similar Posts took 6.040 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2009/03/22/cakephp-console-acl-help-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use Functions from Other Controllers While Maintaining MVC Architecture in CakePHP</title>
		<link>http://anthonygthomas.com/2008/12/10/use-functions-from-other-controllers-while-maintaining-mvc-architecture-in-cakephp/</link>
		<comments>http://anthonygthomas.com/2008/12/10/use-functions-from-other-controllers-while-maintaining-mvc-architecture-in-cakephp/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 23:52:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[About the Author]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[This Site]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dry]]></category>
		<category><![CDATA[mvc]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=66</guid>
		<description><![CDATA[UPDATE (7/22/2009)
requestionAction may not be the best solution. Read this.
At my day job, I&#8217;m working on an application to keep track of specimens for our lab. A specimen is sent to the lab, then divided into aliquots which are put into boxes and stored in freezers. The previous sentence ought to give you some idea [...]]]></description>
			<content:encoded><![CDATA[<h3>UPDATE (7/22/2009)</h3>
<p>requestionAction may not be the best solution. <a href="http://teknoid.wordpress.com/2009/01/17/can-we-talk-enough-about-requestaction/" onclick="pageTracker._trackPageview('/outgoing/teknoid.wordpress.com/2009/01/17/can-we-talk-enough-about-requestaction/?referer=');">Read this</a>.</p>
<p>At my day job, I&#8217;m working on an application to keep track of specimens for our lab. A specimen is sent to the lab, then divided into aliquots which are put into boxes and stored in freezers. The previous sentence ought to give you some idea of the architecture of the database, which in turn drives the Model for my application.</p>
<p>To take a step back for a second, I&#8217;m developing the application using the <a title="CakePHP" href="http://cakephp.org" onclick="pageTracker._trackPageview('/outgoing/cakephp.org?referer=');">CakePHP framework</a> which uses <a href="http://en.wikipedia.org/wiki/Model-view-controller" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Model-view-controller?referer=');">MVC architecture</a>.</p>
<p>As you may have guessed I have specimen, aliquot, boxes and freezers tables. In turn then, I have Specimen, Aliquot, Box and Freezer Models.</p>
<p>The trick here is that I want to alert users when there are aliquots in the system that have not yet been assigned to boxes. It&#8217;s a simple query:</p>

<div class="wp_syntax"><div class="code"><pre class="language" style="font-family:monospace;">SELECT COUNT(aliquot.id)
FROM aliquots
WHERE aliquots.box_id IS NULL</pre></div></div>

<p>The problem is that I want the number of unstored aliquots to be displayed on every page in the left column as a persistent reminder that there are are aliquots that need to be put away. I want to do that in a way that maintains the MVC architecture and doesn&#8217;t violate the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Don_27t_repeat_yourself?referer=');">DRY philosophy</a>.</p>
<p>Since the query is run on the aliquots table and each view is generally specific to it&#8217;s own model, I either have to run a recursive query to access data across models&#8211;which adds overhead&#8211;or implement the solution below which lightens the load a bit and is a more elegant bit of code. (<a title="CakePHP Group" href="http://groups.google.com/group/cake-php/browse_thread/thread/b302d650fa9ec36e/82fd46c3d4e9eeec#82fd46c3d4e9eeec" onclick="pageTracker._trackPageview('/outgoing/groups.google.com/group/cake-php/browse_thread/thread/b302d650fa9ec36e/82fd46c3d4e9eeec_82fd46c3d4e9eeec?referer=');">Tip of the hat to Jon Bennet for offering the solution</a>.)</p>
<p><a href="http://api.cakephp.org/class_object.html#c40a38b60a3748b9cf75215b92ee3db1" onclick="pageTracker._trackPageview('/outgoing/api.cakephp.org/class_object.html_c40a38b60a3748b9cf75215b92ee3db1?referer=');">The solution involves CakePHP&#8217;s requestAction()</a>.</p>
<p>I can define the method in my aliquots controller and call it from anywhere. So if aliquots_controller.php has a method that retrieves the data from the model (in this case called &#8216;unstored&#8217;) I can simply put the following code into my layout:</p>

<div class="wp_syntax"><div class="code"><pre class="language" style="font-family:monospace;">$unstored = $this-&amp;gt;requestAction('aliquots/unstored');
if(!empty($unstored)) {
echo $html-&amp;gt;link('&lt;strong&gt;' . $unstored['unstored'] . ' aliquots have not been stored.&lt;/strong&gt;', '/aliquots/store');
}</pre></div></div>

<p>I only have to define the method once to use it throughout my application. Problem solved.<strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2008/12/10/use-functions-from-other-controllers-while-maintaining-mvc-architecture-in-cakephp/" rel="bookmark" title="December 10, 2008">Use Functions from Other Controllers While Maintaining MVC Architecture in CakePHP</a></li>
<li><a href="http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/" rel="bookmark" title="February 18, 2010">CakePHP: Containable Behavior is Your Friend</a></li>
<li><a href="http://anthonygthomas.com/2009/05/22/roll-your-own-cakephp-components/" rel="bookmark" title="May 22, 2009">Roll Your Own CakePHP Components</a></li>
<li><a href="http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/" rel="bookmark" title="July 22, 2009">Simple Security in CakePHP</a></li>
<li><a href="http://anthonygthomas.com/2008/09/22/and-were-back/" rel="bookmark" title="September 22, 2008">And We&#8217;re Back!</a></li>
</ul>
<p><!-- Similar Posts took 5.733 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2008/12/10/use-functions-from-other-controllers-while-maintaining-mvc-architecture-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Blueprint CSS &amp; JavaScript Libraries Into Your CakePHP Layout</title>
		<link>http://anthonygthomas.com/2008/11/26/getting-blueprint-css-javascript-libraries-into-your-cakephp-layout/</link>
		<comments>http://anthonygthomas.com/2008/11/26/getting-blueprint-css-javascript-libraries-into-your-cakephp-layout/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 19:55:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blueprint Framework]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[libraries]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=59</guid>
		<description><![CDATA[Updated 12/3/2008
The other day I wrote about getting the Blueprint CSS framework into your Wordpress theme. If you&#8217;re developing in CakePHP, it&#8217;s even easier to link multiple style sheets and JavaScript libraries to your layout file.
&#60;?php
$css = array('blueprint/screen', 'blueprint/ie', 'style');
$jslibraries = array('prototype', 'scriptaculous', 'jquery');
echo $html-&#62;css('blueprint/print', 'stylesheet', 'media="print"');
echo $html-&#62;css($css, 'stylesheet', 'media=”screen, projection”');
echo $javascript-&#62;link($jslibraries);
?&#62;
Let&#8217;s take these one [...]]]></description>
			<content:encoded><![CDATA[<p>Updated 12/3/2008</p>
<p>The other day I wrote about <a href="http://anthonygthomas.com/2008/11/23/incorporating-blueprint-css-into-your-new-wordpress-theme/">getting the Blueprint CSS framework into your Wordpress theme</a>. If you&#8217;re developing in <a href="http://cakephp.org" onclick="pageTracker._trackPageview('/outgoing/cakephp.org?referer=');">CakePHP</a>, it&#8217;s even easier to link multiple style sheets and JavaScript libraries to your <a href="http://book.cakephp.org/view/96/Layouts" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/96/Layouts?referer=');">layout file</a>.</p>
<p><code>&lt;?php</code></p>
<p><code>$css = array('blueprint/screen', 'blueprint/ie', 'style');<br />
$jslibraries = array('prototype', 'scriptaculous', 'jquery');</code><code><span style="text-decoration: line-through;"><br />
</span>echo $html-&gt;css('blueprint/print', 'stylesheet', 'media="print"');</code><code><br />
echo $html-&gt;css($css, 'stylesheet', 'media=”screen, projection”');<br />
echo $javascript-&gt;link($jslibraries);</code><br />
<code>?&gt;</code></p>
<p>Let&#8217;s take these one at a time.</p>
<p><code>$css = array('blueprint/screen', 'blueprint/ie', 'style');</code></p>
<p><a href="http://book.cakephp.org/view/205/HTML" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/205/HTML?referer=');">CakePHP&#8217;s html helper</a> will load any css file you specify. First, make sure the css files are in <code>app/webroot/css</code>. Then put any css files you want to link to your layout in an array like I have above. You might have noticed that I didn&#8217;t include print in my array. That&#8217;s because we want to add an media=&#8221;print&#8221; as a separate attribute that the other style sheets won&#8217;t have.</p>
<p>Once they&#8217;re loaded into your array, simply put <code>echo $html-&gt;css($css);</code> in the head of your layout. The output will be:<br />
<code>&lt;link rel="stylesheet" type="text/css" href="/app/webroot/css/blueprint/screen.css" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="/app/webroot/css/blueprint/ie.css" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="/app/webroot/css/style.css" /&gt;</code></p>
<p>We still haven&#8217;t linked our print style sheet. Make sure you link the print style sheet above the others so they override it. We can add <code>media="print"</code> by putting this into our layout head:</p>
<p><code>echo $html-&gt;css('blueprint/print', 'stylesheet', 'media="print"');</code></p>
<p>So now:</p>
<p><code>$css = array('blueprint/screen', 'blueprint/ie', 'style');<br />
</code><code>echo $html-&gt;css('blueprint/print', 'stylesheet', 'media="print"');</code><code><br />
</code><code>echo $html-&gt;css($css, 'stylesheet', 'media=”screen, projection”');</code></p>
<p>Results in:</p>
<p><code>&lt;link rel="stylesheet" type="text/css" href="/cvp-msi/https/app/webroot/css/blueprint/print.css" media="print" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="/cvp-msi/https/app/webroot/css/blueprint/screen.css" media="screen, projection" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="/cvp-msi/https/app/webroot/css/blueprint/ie.css" media="screen, projection" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="/cvp-msi/https/app/webroot/css/style.css" media="screen, projection" /&gt;</code></p>
<p>Two things to note. In <code>$html-&gt;css($path, $attributes)</code>, the first argument is the path from <code>app/webroot/css</code>. The second argument is html attributes.</p>
<p>Linking JavaScript libraries is very similar.</p>
<p><code>$jslibraries = array('prototype', 'scriptaculous', 'jquery');</code></p>
<p>This will link to <code>prototype.js</code>, <code>scriptaculous.js</code> and <code>jquery.js</code> respectively as long as there in <code>app/webroot/js</code>.</p>
<p>Put <code>echo $javascript-&gt;link($jslibraries);</code> into the head of your layout and you&#8217;re done. You have all three JavaScript libraries at your disposal.</p>
<p>Other good resources:</p>
<ul>
<li><a href="http://book.cakephp.org/view/181/Core-Helpers" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/181/Core-Helpers?referer=');">CakePHP Core Helpers</a></li>
<li><a href="http://book.cakephp.org/view/27/Developing-with-CakePHP" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/27/Developing-with-CakePHP?referer=');">Developing With CakePHP</a></li>
<li><a href="http://api.cakephp.org/class_javascript_helper.html#cab1eb59cacd608ec02e79cfd8710094" onclick="pageTracker._trackPageview('/outgoing/api.cakephp.org/class_javascript_helper.html_cab1eb59cacd608ec02e79cfd8710094?referer=');">CakePHP API JavaScript link Helper</a></li>
<li><a href="http://api.cakephp.org/class_html_helper.html#b8e7fe2bca7be4c25f9a660038131f00" onclick="pageTracker._trackPageview('/outgoing/api.cakephp.org/class_html_helper.html_b8e7fe2bca7be4c25f9a660038131f00?referer=');">CakePHP API CSS link Helper</a></li>
</ul>
<p><strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2008/11/26/getting-blueprint-css-javascript-libraries-into-your-cakephp-layout/" rel="bookmark" title="November 26, 2008">Getting Blueprint CSS &#038; JavaScript Libraries Into Your CakePHP Layout</a></li>
<li><a href="http://anthonygthomas.com/2008/11/23/incorporating-blueprint-css-into-your-new-wordpress-theme/" rel="bookmark" title="November 23, 2008">Incorporating Blueprint CSS Into Your New Wordpress Theme</a></li>
<li><a href="http://anthonygthomas.com/2010/02/08/introducing-the-baseline-development-wordpress-theme/" rel="bookmark" title="February 8, 2010">Introducing the Baseline Development Wordpress Theme</a></li>
<li><a href="http://anthonygthomas.com/2008/11/22/blueprint-css-readme-file/" rel="bookmark" title="November 22, 2008">Blueprint CSS Readme File</a></li>
<li><a href="http://anthonygthomas.com/2010/02/16/baseline-theme-version-1-0-1/" rel="bookmark" title="February 16, 2010">Baseline Theme Version 1.0.1</a></li>
</ul>
<p><!-- Similar Posts took 3.846 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2008/11/26/getting-blueprint-css-javascript-libraries-into-your-cakephp-layout/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>And We&#8217;re Back!</title>
		<link>http://anthonygthomas.com/2008/09/22/and-were-back/</link>
		<comments>http://anthonygthomas.com/2008/09/22/and-were-back/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 20:55:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ACL]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=36</guid>
		<description><![CDATA[I have been so incredibly busy the last few months that aside for 140 character Twitter updates, I haven&#8217;t been able to keep this blog updated with my exploits.
If you are still paying attention, I was complaining about ACL. After several attempts, I gave up using the built-in ACL component in CakePHP and just decided [...]]]></description>
			<content:encoded><![CDATA[<p>I have been so incredibly busy the last few months that aside for 140 character Twitter updates, I haven&#8217;t been able to keep this blog updated with my exploits.</p>
<p>If you are still paying attention, <a href="http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/">I was complaining about ACL</a>. After several attempts, I gave up using the <a href="http://book.cakephp.org/view/171/Access-Control-Lists" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/171/Access-Control-Lists?referer=');">built-in ACL component in CakePHP</a> and just decided to keep things simple, <a href="http://book.cakephp.org/view/172/Authentication" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/172/Authentication?referer=');">use the Auth component</a> with role-based access control. Problem solved.</p>
<p>The development of the application has progressed smoothly since getting over that hurdle.</p>
<p>In the meantime, I&#8217;ve been setting up my own virtual server for hosting websites for my freelance clients. That has been a learning experience in itself. I&#8217;ll post more about that as I formally launch that service.</p>
<p>I&#8217;m also way behind on podcasts for the Minneapoliscast podcast. I hope to resume that at a modest pace this fall.</p>
<p>More later as all of my respective projects get updates including SVN info on my CakePHP app.<strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2008/09/22/and-were-back/" rel="bookmark" title="September 22, 2008">And We&#8217;re Back!</a></li>
<li><a href="http://anthonygthomas.com/2009/07/22/simple-security-in-cakephp/" rel="bookmark" title="July 22, 2009">Simple Security in CakePHP</a></li>
<li><a href="http://anthonygthomas.com/2009/04/06/minnewebcon-2009/" rel="bookmark" title="April 6, 2009">MinneWebCon 2009</a></li>
<li><a href="http://anthonygthomas.com/2009/05/22/roll-your-own-cakephp-components/" rel="bookmark" title="May 22, 2009">Roll Your Own CakePHP Components</a></li>
<li><a href="http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/" rel="bookmark" title="June 20, 2008">Wow. ACL is Hard</a></li>
</ul>
<p><!-- Similar Posts took 7.466 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2008/09/22/and-were-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wow. ACL is Hard</title>
		<link>http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/</link>
		<comments>http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/#comments</comments>
		<pubDate>Fri, 20 Jun 2008 18:55:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ACL]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[access control lists]]></category>
		<category><![CDATA[modified preorder tree traversal algorithm]]></category>

		<guid isPermaLink="false">http://anthonygthomas.com/?p=34</guid>
		<description><![CDATA[That is Access Control Lists. I&#8217;ve been developing with CakePHP this spring and summer and it was all going very well until I actually needed to control access to the application. It&#8217;s not even that CakePHP falls short here. There are apparently tons of built-in tools for managing access. They&#8217;re just poorly documented and the [...]]]></description>
			<content:encoded><![CDATA[<p>That is Access Control Lists. I&#8217;ve been developing with <a href="http://cakephp.org" onclick="pageTracker._trackPageview('/outgoing/cakephp.org?referer=');">CakePHP</a> this spring and summer and it was all going very well until I actually needed to control access to the application. It&#8217;s not even that CakePHP falls short here. There are apparently tons of built-in tools for managing access. They&#8217;re just poorly documented and the community is relatively new so no one has built a complete plug in. If you&#8217;re looking for a solution like I was, I&#8217;m afraid I&#8217;m not going to give you the best answer here. I did find something that works, so read on. Especially if you&#8217;re learning ACL or Modified Preorder Tree Traversal Algorithm (MPTTA) for the first time.</p>
<p>Disclosure: I&#8217;m not formally trained as a programmer/developer. Everything I&#8217;ve learned, I&#8217;ve taught myself. So there are definitely some silos in my knowledge as I&#8217;ve learned things on the basis of necessity. I have, however, been developing in PHP for over six years. So it&#8217;s not all that bad.</p>
<p>So the learning curve for implementing ACL has been relatively steep for me. First, I had to get my head around the concept. The big picture is easy. <a title="ACL in the CakePHP Manual" href="http://book.cakephp.org/view/171/access-control-lists" onclick="pageTracker._trackPageview('/outgoing/book.cakephp.org/view/171/access-control-lists?referer=');">What we&#8217;re after is a tree of access with &#8216;admin&#8217; at the root and everything else branching off from that with diminishing access</a>. That&#8217;s not hard to conceptualize. What is hard is putting that into practice.</p>
<p>I messed around with this for a long time before stumbling upon <a href="http://www.sitepoint.com/article/hierarchical-data-database/2" onclick="pageTracker._trackPageview('/outgoing/www.sitepoint.com/article/hierarchical-data-database/2?referer=');">this tutorial about the Modified Preorder Tree Traversal Algorithm</a>. Stop now. Read it. Come back.</p>
<p>Now you should understand the concepts that drive CakePHP&#8217;s ACL. Unfortunately here is also where we depart from using CakePHP&#8217;s tools. At least until a decent plug-in comes along that allows you to manage Access Request Objects (ARO) and Access Control Objects (ACO) via a good, web-based interface.</p>
<p>After many attempts with <a href="http://bakery.cakephp.org/tags/view/acl" onclick="pageTracker._trackPageview('/outgoing/bakery.cakephp.org/tags/view/acl?referer=');">various solutions that are currently avaliable</a>, I finally settled on <a href="http://conseil-recherche-innovation.net/authake" onclick="pageTracker._trackPageview('/outgoing/conseil-recherche-innovation.net/authake?referer=');">Authake</a>.</p>
<p>Pros:</p>
<ul>
<li>Works in CakePHP 1.2</li>
<li>User, ARO &amp; ACO adminstration is a snap</li>
<li>Access control works immediately without modifying anything you&#8217;ve built in your app.</li>
</ul>
<p>Cons:</p>
<ul>
<li>Installation requires you replace the entire CakePHP engine with Authake&#8217;s modified version. This will make upgrading CakePHP a lot harder.</li>
<li>The developer has abandoned it in favor of developing in RoR. No hope for future versions unless the community continues development. Personally, I&#8217;d prefer a plug-in like<a href="http://bakery.cakephp.org/articles/view/acl-management-plugin" onclick="pageTracker._trackPageview('/outgoing/bakery.cakephp.org/articles/view/acl-management-plugin?referer=');"> Jeff <span class="author">Loiselle</span>&#8217;s ACL Management Plugin</a> that I could just drop right into app/plugins without replacing the entire installation. (<a href="http://dev.newnewmedia.com/cakephp/admin/acl" onclick="pageTracker._trackPageview('/outgoing/dev.newnewmedia.com/cakephp/admin/acl?referer=');">The issue I have with Jeff&#8217;s are all listed on his &#8220;Known Bugs&#8221; list</a>. Namely, &#8220;does not show inherited permissions, does not show full path in finder &amp; does not have crud fields&#8221;. Unfortunately, those are three very major elements of managing ACL.)</li>
</ul>
<p>If you are reading this in the not so distant future and someone had developed a plugin that has an admin area like Authake&#8217;s but drops into app/plugins like Jeff&#8217;s plugin, please, <em>please</em> let me know.<strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/" rel="bookmark" title="June 20, 2008">Wow. ACL is Hard</a></li>
<li><a href="http://anthonygthomas.com/2009/03/22/cakephp-console-acl-help-file/" rel="bookmark" title="March 22, 2009">CakePHP Console ACL Help File</a></li>
<li><a href="http://anthonygthomas.com/2010/02/18/cakephp-containable-behavior-is-your-friend/" rel="bookmark" title="February 18, 2010">CakePHP: Containable Behavior is Your Friend</a></li>
<li><a href="http://anthonygthomas.com/2008/09/22/and-were-back/" rel="bookmark" title="September 22, 2008">And We&#8217;re Back!</a></li>
<li><a href="http://anthonygthomas.com/2008/11/25/wordpress-auto-update-is-ok-but-the-command-line-is-faster/" rel="bookmark" title="November 25, 2008">Wordpress&#8217; Auto Update Is OK, But The Command Line Is Faster</a></li>
</ul>
<p><!-- Similar Posts took 5.455 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://anthonygthomas.com/2008/06/20/wow-acl-is-hard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
