<?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>stevehollis.com &#187; action helper</title>
	<atom:link href="http://www.stevehollis.com/tag/action-helper/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.stevehollis.com</link>
	<description>Barking on about PHP, MySQL and Zend Framework</description>
	<lastBuildDate>Mon, 05 Apr 2010 18:07:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Super-Skinny your Zend Framework Action Controllers (Part One)</title>
		<link>http://www.stevehollis.com/2010/03/super-skinny-your-zend-framework-action-controllers-part-one/</link>
		<comments>http://www.stevehollis.com/2010/03/super-skinny-your-zend-framework-action-controllers-part-one/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 09:50:18 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[action helper]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[zend_controller_action]]></category>
		<category><![CDATA[zf]]></category>

		<guid isPermaLink="false">http://www.stevehollis.com/?p=53</guid>
		<description><![CDATA[Inspired by Padraic Brady&#8217;s post on Fat Stupid Ugly Controllers and Chris Hartjes&#8217; Fat Models, Skinny Controllers, I&#8217;ve been putting my controllers on a crash diet. Slim controllers are easier to test, encourage the DRY principle and force business logic back into the model layer where it belongs. In this first article, I&#8217;ll be looking [...]]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_101" class="wp-caption alignright" style="width: 310px"><a href="http://www.stevehollis.com/wp-content/uploads/2010/03/scales.jpg"><img src="http://www.stevehollis.com/wp-content/uploads/2010/03/scales.jpg" alt="Super Skinny Your Controllers" title="Super Skinny Your Controllers" width="300" height="301" class="size-full wp-image-101" /></a><p class="wp-caption-text">Lose pounds of excess code in 1 easy step!</p></div>Inspired by Padraic Brady&#8217;s post on <a href="http://blog.astrumfutura.com/archives/373-The-M-in-MVC-Why-Models-are-Misunderstood-and-Unappreciated.html">Fat Stupid Ugly Controllers</a> and Chris Hartjes&#8217; <a href="http://www.littlehart.net/atthekeyboard/2007/04/27/fat-models-skinny-controllers/">Fat Models, Skinny Controllers</a>, I&#8217;ve been putting my controllers on a crash diet.</p>
<p>Slim controllers are easier to test, encourage the <acronym title="Don't Repeat Yourself">DRY</acronym> principle and force business logic back into the model layer where it belongs.</p>
<p>In this first article, I&#8217;ll be looking at a quick way to de-bloat Zend Framework Action Controllers by using an Action Helper to automatically instatiate models and assign them to properties in the controller and view.</p>
<h3>Lather, Rinse, Repeat</h3>
<p>Controller actions often perform mundane, repetitive tasks. Checking for required parameters, creating objects and assigning variables (again and again) eats up line after line of code in a typical controller. </p>
<p>Using the address book example, a simple action in our Contact controller might look something like this:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> ContactController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> viewAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// check that we have a contact ID, otherwise redirect to index</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_hasParam<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span>Contact<span style="color: #339933;">::</span><span style="color: #004000;">exists</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getParam<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">FlashMessenger</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'No contact specified or contact does not exist.'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_redirect<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'contact'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #666666; font-style: italic;">// lookup and instantiate the contact object</span>
	<span style="color: #000088;">$contact</span> <span style="color: #339933;">=</span> Contact<span style="color: #339933;">::</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getParam<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// assign contact to view</span>
	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">contact</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$contact</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code></p>
<p>A few things are happening here:</p>
<ol>
<li>First, we check to see if the &#8216;id&#8217; param exists in the request.</li>
<li>Then we use our model&#8217;s static exists() method to check that the contact ID corresponds to a real contact.</li>
<li>The contact object is then looked up using a static finder method.</li>
<li>&#8230;and finally we assign the contact to the view.</li>
</ol>
<p>The exact code will vary depending on your model implementation, but this sort of process is pretty typical in my experience. In many actions, that&#8217;s all that&#8217;s required: the view then does its thing on the contact object that it&#8217;s been given.</p>
<p>Pretty boring stuff and chances are some or all of the above will be repeated in a handful of other actions in the same controller. That&#8217;s a &#8220;code smell&#8221; if ever I smelled one.</p>
<p>By automating these repetitive operations, there&#8217;s an opportunity to substantially reduce the size of our controllers without losing any functionality.</p>
<h3>The Action Helper</h3>
<p>Fortunately, Zend Framework has the perfect tool for this kind of job: an Action Helper.</p>
<p>By tapping into the preDispatch() hook provided and making a few basic assumptions, we can look for models specified in the request, instantiate them and then assign them to properties in both the action controller and the view. </p>
<p>Here&#8217;s the basic action helper class, which I&#8217;ve called &#8220;ModelWatcher&#8221;:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Dog_Zend_Controller_Action_Helper_ModelWatcher <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action_Helper_Abstract
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * @var string
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_controllerName</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @return void
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_controllerName <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getControllerName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_view <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_actionController<span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">;</span>
&nbsp;
	try <span style="color: #009900;">&#123;</span>
	    <span style="color: #000088;">$model</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getModel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	    <span style="color: #666666; font-style: italic;">// assign to the controller and view</span>
	    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_actionController<span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_controllerName<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$model</span><span style="color: #339933;">;</span>
	    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_view<span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_controllerName<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$model</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span> Exception <span style="color: #000088;">$e</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @return object The instantiated model object
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _getModel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #009900; font-weight: bold;">NULL</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;ID parameter not found in request&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// attempt to find and instantiate the model object</span>
	<span style="color: #000088;">$modelClass</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ucfirst</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_controllerName <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$model</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$modelClass</span><span style="color: #339933;">::</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$id</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$model</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code></p>
<p><strong>Important:</strong> Don&#8217;t forget that you&#8217;ll need to add the helper to your bootstrap for this to work. Something like this should do the trick:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Zend_Controller_Action_HelperBroker<span style="color: #339933;">::</span><span style="color: #004000;">addHelper</span><span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> Dog_Zend_Controller_Action_Helper_ModelWatcher<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p></code></p>
<p>When the helper&#8217;s preDispatch() method is called, it checks the request for the &#8220;id&#8221; parameter and attempts to find and create the model object. In the case of our address book, a request URL like <em>http://www.example.com/contact/id/123</em> would try to retrieve an object of the class Contact whose ID is 123. </p>
<p>We wrap the call to _getModel() in a try&#8230;catch block to deal with two scenarios: </p>
<ol style="list-style-type:decimal;">
<li>When no ID parameter exists in the request or</li>
<li>No record exists for the given ID</li>
</ol>
<p>The latter assumes that the find() method will throw an exception if the record is not found. </p>
<p>If the lookup is successful, the newly created object is assigned to the controller and view with a property named after the controller. So with our address book example, you&#8217;d access the contact object using $this->contact from within both the controller and the view. </p>
<p>On failure, we do nothing &#8211; leaving the action controller to implement its own logic for dealing with non-existent objects.</p>
<h3>The Final Weigh-In</h3>
<p>All this means we&#8217;re left with a significantly slimmer controller action:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> ContactController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> viewAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// check that we have a contact object</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">contact</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">FlashMessenger</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'No contact specified or contact does not exist.'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_redirect<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'contact'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
The controller action now only needs to check that a contact object has been created by the action helper. There&#8217;s no need for it to get its hands dirty with the request params, object generation or assigning variables to the view as it&#8217;s already been done.</p>
<p>This approach does require an adherence to some naming conventions&#8230; primarily that the model class name has to mirror the controller name and the identifying parameter is always passed as &#8220;id&#8221; in the URL. Provided they aren&#8217;t too wacky, it should be reasonably easy to re-jig the code to suit any conventions of your own.</p>
<h3>Further Weight Loss</h3>
<p>A slightly more flexible approach is to use verbose ID parameters like &#8220;contact-id&#8221;. This gives you the ability to have model classes which don&#8217;t match the controller name and also allows multiple models to be instantiated by the ModelWatcher in one request, both of which can be useful. I use something similar in my own implementation.</p>
<p>You might also want to consider adding other logic in to the ModelWatcher helper like record locking or fine-grained access control. Even if you decide to separate these activities into a separate helper class, you can still use the models inserted into the controller rather than going back to the request parameters again. Just make sure that the ModelWatcher is added to the action helper plugin stack before any helper that relies on it or the models it creates.</p>
<h3>Final Thoughts</h3>
<p>Hopefully it should be fairly clear that this simple action helper has the potential to dramatically reduce the amount of boiler plate code in your controllers. Eagle-eyed readers might also have noticed that automatically assigning models to the controller is a feature of <a href="http://book.cakephp.org/view/53/components-helpers-and-uses">CakePHP</a>.</p>
<p>Look out for future posts where I&#8217;ll be discussing more ways to de-clutter and cut down your controllers.</p>
<p>P.S. Thanks to <a href="http://www.zendframeworkinaction.com/2010/03/05/steve-hollis-blog-practical-nested-transactions-with-zend_db-and-mysql/">Rob Allen</a>, <a href="http://weierophinney.net/matthew/">Matthew Weier O&#8217;Phinney</a>, <a href="http://blog.astrumfutura.com/">Pádraic Brady</a>, <a href="http://blog.ekini.net/2010/03/05/zend-framework-how-to-use-nested-transactions-with-zend_db-and-mysql/">Wenbert Del Rosario</a> and others for retweeting/linking to my <a href="http://www.stevehollis.com/2010/03/practical-nested-transactions-with-zend_db-and-mysql/">first post</a> <img src='http://www.stevehollis.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevehollis.com/2010/03/super-skinny-your-zend-framework-action-controllers-part-one/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

