<?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>Ryan&#039;s Blog &#187; ryan</title>
	<atom:link href="http://www.rmauger.co.uk/author/ryan/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rmauger.co.uk</link>
	<description>Randomness will get you everywhere.</description>
	<lastBuildDate>Thu, 05 May 2011 14:35:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using Twig with Zend Framework</title>
		<link>http://www.rmauger.co.uk/2011/05/using-twig-with-zend-framework/</link>
		<comments>http://www.rmauger.co.uk/2011/05/using-twig-with-zend-framework/#comments</comments>
		<pubDate>Wed, 04 May 2011 21:07:34 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[Content Management]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Twig]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[templating system]]></category>
		<category><![CDATA[twig]]></category>
		<category><![CDATA[zf]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=177</guid>
		<description><![CDATA[Twig, in short, is a templating system for PHP. But PHP is already a templating system many would argue! Well, I wouldn&#8217;t argue against that point. However, with the recent excitement in the air in the PHP Community about Symfony 2, I thought it worth checking out. Mostly I thought they were silly things that [...]]]></description>
			<content:encoded><![CDATA[<p>Twig, in short, is a templating system for PHP. But PHP is already a templating system many would argue! Well, I wouldn&#8217;t argue against that point. However, with the recent excitement in the air in the PHP Community about Symfony 2, I thought it worth checking out.<br />
Mostly I thought they were silly things that were not really needed unless you had a team of designers to work with, however, during my exploration, a couple of things occurred to me that I had not considered about templating systems before. One being the enforced separation of concerns they provide; you simply cannot do anything from inside them which you shouldn&#8217;t be, keeping your presentation very very clean. The second, being that they&#8217;re not all as terrible as Smarty.</p>
<p><span id="more-177"></span></p>
<h2>Installing Twig</h2>
<p>This really couldn&#8217;t get a lot simpler with pear:</p>
<pre>    $ pear channel-discover pear.twig-project.org
    $ pear install twig/Twig</pre>
<p>or, you can use the Git or Subversion repos as detailed on the projects website: <a href="http://www.twig-project.org/doc/intro.html">http://www.twig-project.org/doc/intro.html</a></p>
<p><strong>The Application Resource</strong></p>
<p>Setting up a ZF application resource for twig is a snip! The minimal config required to set up a Twig instance, is exactly that, minimal!</p>
<p>Simple create the class &#8220;Core_Resource_Twig&#8221; and place it in library/Core/Resource/Twig.php and consider the following code:</p>
<pre>&lt;?php

class Core_Resource_Twig extends Zend_Application_Resource_ResourceAbstract
{
    /**
     * @var Twig_Environment
     */
    protected $twig;

    public function init()
    {
        $options = $this-&gt;getOptions();
        $loader = new Twig_Loader_Filesystem($options['templateDir']);
        $this-&gt;twig = new Twig_Environment(
                $loader,
                $options['options']
        );
        return $this-&gt;twig;
    }
}</pre>
<p>All we are doing here, is creating an instance of the Filesystem Twig loader, which loads templates from files, and then passing that in to the Twig Environment, along with the rest of the options from our config, which in brief, would now look something like this:</p>
<pre>
[production]
autoloaderNamespaces[] = "Twig_"
pluginPaths.Core_Resource = APPLICATION_PATH "/../library/Core/Resource"

; FRONT CONTROLLER
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.controllerDirectory.default = APPLICATION_PATH "/controllers"
resources.frontController.noViewRenderer = true

; TWIG
resources.twig.templateDir = APPLICATION_PATH "/templates"
resources.twig.options.cache = APPLICATION_PATH "/../cache/twig"

[development : production]
resources.twig.options.debug = true
resources.twig.options.auto_reload = true
</pre>
<p>That now gives us two things, a configured Twig instance, and an application resource to hold it, which will be present in the invoke args in your controller. so for the next step, we stitch it together, and make it more useable, to make things super simple, a base controller class is useful here. The reason for a base controller class rather than an action helper is simple, performance, and simplicity; no need for the complexity or auto-rendering anything, we will simply call a method at the end of each action.</p>
<p>Given that we are now using twig, this has two benefits, we avoid the overhead of how ZF looks up the view name to decide which view template to render, which is a part of the bottleneck of ZF, and additionally, it matches more closely to the other documentation you&#8217;ll find on Twig elsewhere, and we are doing things in a slightly different manner to how we would use Zend_View, so why try to emulate it, when we are using something very different!</p>
<pre>&lt;?php

abstract class Core_Controller extends Zend_Controller_Action
{
    public function twig($template, array $vars)
    {
        $twig = $this-&gt;getBootstrap()-&gt;getResource('twig');

        $template = $twig-&gt;loadTemplate($template);
        $this-&gt;getResponse()-&gt;appendBody(
            $template-&gt;render($vars),
            'default'
        );
    }
}</pre>
<h2>Rendering the template</h2>
<p>Now that we have our base controller class, we can now use our template, in this manner from our action:</p>
<pre>&lt;?php

class IndexController extends Core_Controller
{
    /**
     * @var Core_Service_Posts
     */
    protected $service;

    public function init()
    {
        $this-&gt;service = new Core_Service_Posts();
    }

    public function indexAction()
    {
        $recent = $this-&gt;service-&gt;recentPosts();
        $this-&gt;twig('home.twig', array(
            'recent' =&gt; $recent,
        ));
    }

    public function viewAction()
    {
        $id = $this-&gt;getRequest()-&gt;getParam('id', false);
        if (false === $id) {
            throw new Core_InvalidIdException('No ID Present');
        }

        $paste = $this-&gt;service-&gt;byId($id);

        $this-&gt;twig('view-post.twig', array(
            'post' =&gt; $paste,
        ));
    }

}</pre>
<p>In this example, you have the indexAction, taking the service for the posts for the application, and passing the recent posts to the template, and in the view action, taking the selected post, and passes it to the template, with the selection of template for the action being passed as the first argument to our twig method we added to the base controller class.</p>
<p>And now, you can find examples and documentation on how to put together your twig templates here <a href="http://www.twig-project.org/documentation">http://www.twig-project.org/documentation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2011/05/using-twig-with-zend-framework/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>PHP BENELUX 2011</title>
		<link>http://www.rmauger.co.uk/2011/02/php-benelux-2011/</link>
		<comments>http://www.rmauger.co.uk/2011/02/php-benelux-2011/#comments</comments>
		<pubDate>Tue, 01 Feb 2011 20:21:35 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[conferences]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpbenelux]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=156</guid>
		<description><![CDATA[Back in October 2010, I was amazingly lucky, and won a ticket to the PHPBenelux 2011 conference! stuff like that doesn&#8217;t often happen to me, infact, phpnw is one of the few places I&#8217;ve ever won anything, the previous year I won a copy of PHP Object Oriented Solutions. With much excitement, I arranged to [...]]]></description>
			<content:encoded><![CDATA[<p>Back in October 2010, I was amazingly lucky, and won a ticket to the PHPBenelux 2011 conference! stuff like that doesn&#8217;t often happen to me, infact, phpnw is one of the few places I&#8217;ve ever won anything, the previous year I won a copy of PHP Object Oriented Solutions.</p>
<p>With much excitement, I arranged to travel with Rob Allen to the conference, as we are in (relatively) close proximity, and traveling with someone is always better than traveling alone.</p>
<p>As the months quickly passed by, the conference schedule was soon posted, and I became immediately impressed with the lineup, with speakers from America making an appearance along with the big names in PHP from Europe, this was going to be a great conference.</p>
<p><span id="more-156"></span></p>
<p>As quickly as I got my voucher to book my ticket for the conference, I signed up to an extra session of tutorials, after all I was going to be there anyway. with that and the hotel and flights booked, anticipation was the state of mind for the next two and a half months leading up to the conference. Once the tutorial sessions were announced, I discovered that I was in for a treat, Solr was on the agenda, a tool which I&#8217;ve only worked with from the outside, that is being involved in a team using it, but not working with it directly myself, so finally I was to get the chance to learn something more about it, so I booked my seat in that tutorial, and resumed my previous state of anticipation.</p>
<h2><a href="http://www.rmauger.co.uk/wp-content/uploads/2011/02/IMG_0553.jpg"><img class="size-medium wp-image-161 alignright" title="Beer!" src="http://www.rmauger.co.uk/wp-content/uploads/2011/02/IMG_0553-200x300.jpg" alt="" width="200" height="300" /></a>The Drinking begins!</h2>
<p>Finally, came travelling day. Leaving nice and early in the morning, up the M5, I stopped off and picked up Akrabat, and we headed for Birmingham airport, where what would turn out to be a long day began. Little did we know what we were in for, we were supposed to be flying at 10:50am, we eventually took off at 8:30pm! Thankfully, having a traveling buddy paid off, and the time passed quickly in the bar, and the beer began!</p>
<p>When we finally arrived at the hotel, many tweets later, and being kindly picked up by Michelangelo van Dam, we headed straight to the bar, to begin consumption of some fine belgian beer! (and very fine it was)</p>
<h2>The conference begins</h2>
<p>Kicking off with a tutorial on Solr, was Paul Borgermans, who has extensively used Solr in his work before, and gave an excellent introduction for those of us who were new to the subject, while managing to easily move on to some of the more complex subjects without causing confusion, and explaining everything with just the right amount of detail, not to little to leave you with dozens of questions, and not too much to take in at once. I came away from the session confident that I could set up and get running with Solr without much hassle, and without needing to spend a whole day in google. An excellent start!</p>
<p>Next up, after an excellent meal, was the Keynote. This wasn&#8217;t the first time I&#8217;ve seen Lorna or Ivo speak at a conference, and have enjoyed their talks where I have seen them before, so to have the two of them together was a real treat! Titled &#8217;27 Ways to be a better developer&#8217;, and interspersed with humour and wit,  were some really good messages, some new, some re-enforcing things that every developer should really know already, but overall a balanced talk about how to improve yourself as a developer. The Supreme Allied Commander (Matthew Weier O&#8217;Phinney) was even featured when discussing the idea of finding a mentor, and also passing that knowledge on in return.</p>
<p>Derick Rethans was next on my journey through the schedule, With a presentation on Geo-Location, and mapping, Mostly seemed to be aimed at using OpenStreetMap, but explained some of the nuances of how to present mapping data, and was a really interesting presentation. Perhaps less PHP involved than I expected, but had plenty of great information, and opened my mind to the possibility of not using google maps next time I need an interactive map in a website, it seems much simpler, and less restricted by google&#8217;s licensing (you can even use the data without using a map at all).</p>
<p>Next up for me from the schedule was, &#8216;Making software development tools work for you&#8217; by John Mertic of SugarCRM, discussing pretty much exactly what it said on the tin! talking about how to choose your tools, and how to get the best from them, covering tools from issue tracking to continuous integration, source control and more.</p>
<p>Then &#8216;Designing HTTP interfaces, and RESTful web services&#8217; by David Zülke of Bitextender. I really enjoy seeing David speak, he manages to fully inject his character and humour into his talk, and at the same time get right into technical details, and convey his point.</p>
<p><img class="size-medium wp-image-162 alignright" title="IMG_0618" src="http://www.rmauger.co.uk/wp-content/uploads/2011/02/IMG_0618-300x200.jpg" alt="" width="240" height="160" /></p>
<h2>The Drinking Continues</h2>
<p>At the end of the day came the closing Messages from Microsoft, and an introduction to Azure from Maarten Balliauw, and Katrien De Graeve, with Michelangelo van Dam giving us some insights into how PHP is maturing on windows. Michelangelo&#8217;s presentation promted a good deal of chatter on twitter, with his demonstration of how phing can be used to deploy the same codebase to different servers, (and deploying to linux is 2 lines and a few seconds in rsync, deploying to windows, 50,000 lines and a minute in ftp!). One feature I was sorry not to see discussed more, is Azure&#8217;s cloud simulator, which looks like a really cool tool to have, and would be nice to get running some linux vm&#8217;s in.</p>
<p>After this, we had a good spread of food laid on by Facebook, and the time to spend the beer vouchers given kindly by github! so over the road to the hotels second complex, where there was bowling and beer, a good mix by everyone&#8217;s standards!</p>
<h2>Day 2</h2>
<p>First up for me, Paul Jones, talking about benchmarking frameworks. This turned out to be totally not what I was expecting. instead of Solar Framework, trouncing the world, was a balanced and informed look at how to meter your own environment to see how different frameworks may perform for you, and how to take the steps to bring in control to ensure that you know what your framework is costing you, and what the application you build upon it costs. At the end, I think everyone came away better armed to know how to get the most from benchmarking their applications, and to take a balanced look at their systems.</p>
<p>Following Paul, was a talk from Scott MacVicar, talking about HipHop for PHP, which I have been following with interest for a while, and it was very interesting to see the developments since he gave a talk on this subject back in phpnw, I wasn&#8217;t sure at first if I should attend this, or another talk, but i&#8217;m glad I did, having learnt some more about what they have been doing, and learning a little more about some of the challenges that a site such as facebook faces from a technical perspective.</p>
<p>Then it was time for Rob&#8217;s talk on Zend Framework 2, where he announced publicly for the first time that Zend Framework 2 in Action was to be written, and that I would be working with him on it, the talk went down well with the audience, with lots of questions and curiosity from the audience, and Rob appeared to be surrounded when it was over with people asking his advice and opinion.</p>
<p>Next I attended an excellent talk by Keith Casey, entitled Project Triage and Recovery, which while he discussed the challenges of forking dotProject for web2Project, also went into some interesting concepts such as managing the complexity of a codebase, interacting with users, and dealing with issues which were really applicable to every project, not just getting on top of an out-of-control codebase. I came away from this brimming with ideas to take back to the office!</p>
<p>At the end of the day, was the closing keynote, brought to us by Elizabeth Naramore, and while it had chocolate chip cookies in the title, it was really about building a community, being the glue, and keeping it motivated. overall an excellent presentation mixed with humour, interaction from the audience and a confident speaker who left a great impression!</p>
<p>Closing the conference, were the raffles, and prizes, thanks for the sponsors, the speakers, and the crew, all of which brought together an excellent conference experience, and the hospitality from the crew was second to none! everybody at the conference was warm and welcoming, crew and other delegates alike, and every speaker was pleasant and approchable.</p>
<h2>More drinking</h2>
<p>I know it seems like a bit of a theme now, but the drinking is a very important aspect of a conference in this community. Not only do you get the chance to get drunk and have a good time, but you also make new connections, share experiences and ideas, and make friends. You could even say, that a good chunk of the magic of a conference, happens at the social, if you have not attended a conference before, try as hard as you can to make sure you can hang around for it when you attend your first one, you wont regret it!</p>
<p>After the close, and a quick call home, those of us who were staying at the hotel one more night, and some of the crew headed into Antwerpen for amazing pizza! and of course more beer, with the conference crew again demonstrating their hospitality driving us into the city center in their cars.</p>
<p>I had a fantastic time at PHPBenelux, and fully intend to be there again next year, (who knows, maybe they will accept me as a speaker!) and I&#8217;ve come back full of ideas and refreshed, and perhaps more importantly, the new faces I have met and some of the people I have met before, has also given me more leads and potential for my day to day life, so Im closing this with a huge thank you to the conference organisers, the speakers, and everyone I met for a great time!</p>
<p>Since the conference, new opportunities have already arisen for me, directly as a result of the social elements of the conference, what a great community we are lucky enough to have as PHP developers!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2011/02/php-benelux-2011/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Speaking at the first ever PHP South West</title>
		<link>http://www.rmauger.co.uk/2010/09/speaking-at-the-first-ever-php-south-west/</link>
		<comments>http://www.rmauger.co.uk/2010/09/speaking-at-the-first-ever-php-south-west/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 12:48:14 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[php community]]></category>
		<category><![CDATA[phpsw]]></category>
		<category><![CDATA[talks]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=140</guid>
		<description><![CDATA[Last Wednesday (1st September 2010) I had the privilege of giving the first ever talk at PHPSW, a new PHPUG for developers in the South West, and Wales. PHPSW has been put together kindly by Stuart Herbert, a great guy who I have had the pleasure of meeting briefly at past conferences and seeing give his talks [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Ryan gives the first PHPSW talk by akrabat, on Flickr" href="http://www.flickr.com/photos/akrabat/4953777240/"><img class="alignright" src="http://farm5.static.flickr.com/4083/4953777240_94c14578ec_m.jpg" alt="Ryan gives the first PHPSW talk" width="240" height="160" /></a>Last Wednesday (1st September 2010) I had the privilege of giving the first ever talk at PHPSW, a new PHPUG for developers in the South West, and Wales. PHPSW has been put together kindly by <a title="Stuart Herbert" href="http://www.stuartherbert.com/">Stuart Herbert</a>, a great guy who I have had the pleasure of meeting briefly at past conferences and seeing give his talks on <a title="Twittex - Stuart Herbert" href="http://www.slideshare.net/stuartherbert/twittex-from-idea-to-live-in-seven-days-presentation" target="_blank">Twittex</a> and <a title="Stuart Herbert - Living With Frameworks" href="http://www.slideshare.net/stuartherbert/living-with-frameworks">Living With Frameworks</a>.</p>
<p>Our venue for the evening was Bush House, a nice place with perfectly sized meeting rooms for the 15 guys who attended.</p>
<p>The talk I gave, was a rehersal for my talk at <a href="http://conference.phpnw.org.uk/phpnw10/">PHPNW10</a>, which is entitled &#8216;<a title="My talk at PHPNW10" href="http://conference.phpnw.org.uk/phpnw10/schedule/zend-framework-getting-to-grips/">Zend Framework: Getting to grips</a>&#8216;, and is aimed at  developers who have made it past the first steps of Zend Framework, and are moving on into the realms of developing their understanding, and exploring the quirks and nuances.</p>
<p><img class="alignleft" src="http://farm5.static.flickr.com/4150/4953185753_c0e607a30b_m.jpg" alt="The audience!" width="240" height="172" /></p>
<p>My talk went down well (at-least, nobody fell asleep), besides a few mistakes on my part when putting my slides together, and gave me some valuable experience to ensure that things go smoothly at PHPNW10, and a huge thanks has to be said to everyone there once more for all the feedback, you&#8217;ve given me a much needed confidence boost!</p>
<p>Afterwards, it was time to head downstairs to <a id="link_C_2" href="pplink&amp;ei=JOqATO7SAoOTjAfVydXQDA&amp;sig2=_yJcM1lu4s-goPobpXLRfw">Arnolfini‎</a><img src="http://maps.gstatic.com/intl/en_ALL/mapfiles/transparent.png" alt="" />, where we all got to mingle and socialise, and discuss all things geeky and wonderful, which is quite a refreshing experience having only experienced such pleasures when attending conferences.</p>
<p>It was also a pleasure to see a few guys who I have encountered over time on IRC, and also to see and appearance from <a title="Rob Allen" href="http://akrabat.com/">Rob Allen</a>, author of <a title="Zend Framework In Action" href="http://www.zendframeworkinaction.com">Zend Framework in Action</a>, whom I have come to regard as a friend over the years from both IRC and bumping into at conferences over the last few years, and was kind enough to give me permission to use the pics he took for this post. Another pleasant surprise was the presence of <a href="http://deglos.com/">Marcus Degalos</a>, who will be hosting the <a title="Framework Shootout, PHPNW10" href="http://conference.phpnw.org.uk/phpnw10/schedule/framework-shootout/">framework shootout at PHPNW10</a>, and is a Bristol resident, so hopefully we can expect to see much more of him at future meetings.</p>
<p>If you&#8217;re in the south west or wales, and you&#8217;re a php developer, come and <a title="PHPSW mailing list" href="http://groups.google.com/group/phpsw">sign up to the mailing list</a>, and get yourself along to the next meeting. See you there! The next scheduled PHPSW meeting will be on Wednesday 13th October 2010 (Venue TBA), so we can pick apart and share our experiences of PHPNW10!</p>
<p>(Before anyone asks to see the slides, they will be available after PHPNW10)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2010/09/speaking-at-the-first-ever-php-south-west/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Keeping your HTML valid with Zend Framework, Tidy and Firebug</title>
		<link>http://www.rmauger.co.uk/2010/01/keeping-your-html-valid-with-zend-framework-tidy-and-firebug/</link>
		<comments>http://www.rmauger.co.uk/2010/01/keeping-your-html-valid-with-zend-framework-tidy-and-firebug/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 13:49:09 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[html validation]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=119</guid>
		<description><![CDATA[With Zend Framework there is an easy way to ensure that you always create valid HTML in your applications. This involves the use of a simple Front Controller Plugin, and the php Tidy component. Valid HTML is important for a great many reasons, the most important of which is ensuring consistency across all of your [...]]]></description>
			<content:encoded><![CDATA[<p>With Zend Framework there is an easy way to ensure that you always create valid HTML in your applications. This involves the use of a simple Front Controller Plugin, and the php Tidy component.</p>
<p>Valid HTML is important for a great many reasons, the most important of which is ensuring consistency across all of your visitors browsers. The first step to making sure that your site appears correctly on all the browsers is to ensure that your HTML is valid. Even if the goons at Microsoft continue to ignore the standards and do their own thing, if you at least ensure your html passes validation, then fixing things for Internet Explo(r|it)er of all its versions is a far easier task, and usually possible with a few simple extra styling rules in your CSS.<br />
<span id="more-119"></span></p>
<h2>What is a front controller plugin</h2>
<p>A front controller plugin is like an observer for the front controller. It provides several events which can be hooked at the various stages of the dispatch cycle. These events are</p>
<ul>
<li>routeStartup: Called before routing takes place</li>
<li>routeShutdown: Called after routing has occured, but before the dispatcher is invoked</li>
<li>dispatchLoopStartup: Called before the dispatchloop begins, essentially the same as routeShutdown</li>
<li>preDispatch: Called before an action is dispatched (also before preDispatch of your controller, and after its init)</li>
<li>postDispatch: Called after an action is dispatched</li>
<li>dispatchLoopShutdown: Called when the dispatching is complete</li>
</ul>
<p>A simple example of a Front Controller plugin is to automatically change the layout based upon the active module.</p>
<p>For this, you may do something as follows:</p>
<pre>class Lupi_Controller_Plugin_ModuleLayout extends Zend_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request) {
        // Changes the Layout based on the module name
        $modulename = $request-&gt;getModuleName();
        $layout = Zend_Layout::getMvcInstance();
        $layout-&gt;setLayoutPath("../application/modules/{$modulename}/layouts")
                     -&gt;setLayout($modulename);
    }
}</pre>
<h2>What is Tidy</h2>
<blockquote><p>Tidy is a binding for the Tidy HTML clean and repair utility which    allows you to not only clean and otherwise manipulate HTML documents,    but also traverse the document tree.[source:<a title="PHP Tidy Extension introduction" href="http://uk.php.net/manual/en/intro.tidy.php" target="_blank">http://uk.php.net/manual/en/intro.tidy.php</a>]</p></blockquote>
<p>The Tidy extension for PHP provides numerous functions for assisting a developer with coding performant, valid, and accessible HTML.</p>
<p>It does this through a variety of methods, but generally it works in 3 steps. configure, parse and repair.</p>
<pre>class Lupi_Filter_Tidy implements Zend_Filter_Interface
{
    /**
     * @var tidy
     */
    protected $_tidy;

    /**
     * @var tidy
     */
    protected $_encoding = 'UTF-8';

    /**
     * @var array
     */
    protected $_config = array('indent' =&gt; true,
                                         'output-xhtml' =&gt; true,
                                         'wrap' =&gt; false,
                                         'show-body-only' =&gt; true);

    /**
     * Filter the content with Tidy.
     *
     * @return string
     */
    public function filter($content)
    {
        $tidy = $this-&gt;getTidy($content);
        $tidy-&gt;cleanRepair();
        return (string) $tidy;
    }

    /**
     * Gets the Tidy object
     */
    public function getTidy($string)
    {
        if (!is_string($string)) {
            throw new InvalidArguementException('Expected string, got: ' . get_type($string));
        }

        if (null === $this-&gt;_tidy) {
            $this-&gt;_tidy = new tidy();
        }

        $this-&gt;_tidy-&gt;parseString($string, $this-&gt;_config, $this-&gt;_encoding);
        return $this-&gt;_tidy;
    }
}</pre>
<p>The above example is a simple filter, which will correct and escape a HTML fragment, suitable for use in a Zend_Form where you wish to accept user input. (NOTE: Though Tidy does a damn  good job of cleaning up input, what it does not do is guarantee that the output will be XSS safe).</p>
<p>HTML Tidy has a huge number of options available, one of my favourites being &#8220;bare&#8221; which removes MS-Word specific attributes and styling which will ruin your output. (No, no matter how many times you tell your clients not to paste straight from word into your editor, they will still do it!). I won&#8217;t even try to explain all the options here, so instead, find a <a title="A complete list of HTML Tidy options" href="http://tidy.sourceforge.net/docs/quickref.html" target="_blank">full list of the options available for tidy</a> on its sourceforge site.</p>
<h2>Using Tidy with a Front Controller Plugin</h2>
<p>Ok, So you can use tidy for filtering user input, what about using it to effectivly clean my documents and ensure my output is always valid?</p>
<p>In the previous example, I set the &#8220;show-body-only&#8221; option, which will force the tidy component to only output the body of the document. This is needed because tidy would have added a doctype, html, head and body tags around the user input. this does set to an automatic option, and should only return the complete document if it detected a body tag, but why risk the user sticking a body tag in there?</p>
<p>For the next example, we have a Front controller plugin, which allows us to filter the output html of our application, so that we know we always have valid output.</p>
<pre>&lt;?php

class Lupi_Controller_Plugin_TidyOutput extends Zend_Controller_Plugin_Abstract
{
    /**
     * @var tidy|null
     */
     protected $_tidy;

    /**
     * @var array
     */
    protected static $_tidyConfig = array('indent'            =&gt; true,
                                          'indent-attributes' =&gt; true,
                                          'output-xhtml'      =&gt; true,
                                          'drop-proprietary-attributes' =&gt; true,
                                          'wrap'              =&gt; 120,
                                          );
    /**
     * @var string
     */
    protected static $_tidyEncoding = 'UTF8';

    public static function setConfig(array $config)
    {
        self::$_tidyConfig = $config;
    }

    public static function setEncoding($encoding)
    {
         if (!is_string($encoding)) {
             throw new InvalidArgumentException('Encoding must be a string');
         }
         self::$_tidyEncoding = $encoding;
    }

    protected function getTidy($string = null)
    {
        if (null === $this-&gt;_tidy) {
            if (null === $string) {
                $this-&gt;_tidy = new tidy();
            } else {
                $this-&gt;_tidy = tidy_parse_string($string,
                                                 self::$_tidyConfig,
                                                 self::$_tidyEncoding);
            }
        }
        return $this-&gt;_tidy;
    }

    public function dispatchLoopShutdown()
    {
        $response = $this-&gt;getResponse();
        $tidy     = $this-&gt;getTidy($response-&gt;getBody());
        $tidy-&gt;cleanRepair();
        $response-&gt;setBody((string) $tidy);
    }
}
</pre>
<p>When you are using this, it is a good idea where possible to use full page static caching, so your not fixing the same errors over and over again!</p>
<h2>Instant feedback with Firebug + Firephp for assisting development</h2>
<p>Ok, so now we have valid HTML, thanks to a filter. How does this help with actual development? well in short, it doesn&#8217;t, as we have no feedback about what its actually fixed. So onto the next step, getting some nice reporting, in a real handy manner. For this, we will use FirePHP, so that all the information we need is sent to the console on every request. This information can even include automated accessibility testing (really handy for government funded work, which usually has requirements on meeting accessibility standards).</p>
<p>So, firstly you need to set up your FirePHP Logger, this is a simple task, simply add the following method to your applications bootstrap:</p>
<pre>protected function _initWildFire()
{
    //Don't use in production!
    if (APPLICATION_ENV != 'development') {
       return;
    }
    $this-&gt;bootstrap('db');
    $db = Zend_Db_Table::getDefaultAdapter();
    $profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
    $profiler-&gt;setEnabled(true);
    $db-&gt;setProfiler($profiler);
    $writer = new Zend_Log_Writer_Firebug();
    $logger = new Zend_Log($writer);
    Zend_Registry::set('logger', $logger);
}
</pre>
<p>This simply sets up a logger, and also does something else useful, it adds a Profiler to the default database adapter, which will log all your queries for you. A little out of the scope of this post, but useful, so I left it in there for you.</p>
<p>The last 3 lines are really the important bit, they set up the write and log component which we will be using to send messages to FirePHP, so we can see validation errors and warnings in our FireBug console! Setting the logger in the registry here is also handy, so we can actually get our logger from anywhere without any hassle. you may also return it from the init method, and use the invoke args to get it.</p>
<p>Now for the really useful bit, the plugin itself.</p>
<pre>class Lupi_Controller_Plugin_TidyOutput extends Zend_Controller_Plugin_Abstract
{
    /**
     * @var tidy|null
     */
    protected $_tidy;

    /**
     * @var array
     */
    protected static $_tidyConfig = array('indent'            =&gt;true,
                                          'indent-attributes' =&gt; true,
                                          'output-xhtml'      =&gt; true,
                                          'drop-proprietary-attributes' =&gt; true,
                                          'wrap'              =&gt; 120,
    );

    protected static $_diagnose = true;

    /**
     * @var string
     */
    protected static $_tidyEncoding = 'UTF8';

    /**
     * Switch diagnosing HTML mode
     */
    public static function setDiagnose($diagnose = true)
    {
        self::$_diagnose = (bool) $diagnose;
    }

    public static function setConfig(array $config)
    {
        self::$_tidyConfig = $config;
    }

    public static function setEncoding($encoding)
    {
        if (!is_string($encoding)) {
            throw new InvalidArgumentException('Encoding must be a string');
        }
        self::$_tidyEncoding = $encoding;
    }

    protected function getTidy($string = null)
    {
        if (null === $this-&gt;_tidy) {
            if (null === $string) {
                $this-&gt;_tidy = new tidy();
            } else {
                $this-&gt;_tidy = tidy_parse_string($string,
                                                 self::$_tidyConfig,
                                                 self::$_tidyEncoding);
            }
        }
        return $this-&gt;_tidy;
    }

    public function dispatchLoopShutdown()
    {
        $response = $this-&gt;getResponse();
        $tidy     = $this-&gt;getTidy($response-&gt;getBody());

        if ('development' === APPLICATION_ENV) {
            if (true === self::$_diagnose ) {
                $tidy-&gt;diagnose();
                $lines = array_reverse(explode("\n", $tidy-&gt;errorBuffer));
                array_shift($lines);
                foreach ($lines as $line) {
                    Zend_Registry::get('logger')->log($line, Zend_Log::INFO);
                }
            }
        }
        $tidy-&gt;cleanRepair();
        $response-&gt;setBody((string) $tidy);
    }
}
</pre>
<p>So, hows it work? Well its essentially the same as the previous plugin, except I have added a section to the dispatchLoopShutdown method, and added a static method to enable / disable the logging output (sometimes it can get in the way!).</p>
<p>The reason for splitting the diagnosis output by line and sending it over multiple log calls, is because the Firebug console will not respect the newline characters, and instead tried to display it all on one line, making it hard to read. splitting it over multiple entries makes things much tidier. reversing the array also makes things a little easier to read!</p>
<p>In closing, heres some examples of the output for you:</p>
<div id="attachment_124" class="wp-caption alignleft" style="width: 310px"><a href="http://www.rmauger.co.uk/wp-content/uploads/2010/01/noerrors.jpg"><img class="size-medium wp-image-124 " title="noerrors" src="http://www.rmauger.co.uk/wp-content/uploads/2010/01/noerrors-300x123.jpg" alt="An example of the Tidy output for valid xhtml" width="300" height="123" /></a><p class="wp-caption-text">An example of the Tidy output for valid xhtml</p></div>
<div id="attachment_123" class="wp-caption alignleft" style="width: 310px"><a href="http://www.rmauger.co.uk/wp-content/uploads/2010/01/errors.jpg"><img class="size-medium wp-image-123 " title="errors" src="http://www.rmauger.co.uk/wp-content/uploads/2010/01/errors-300x123.jpg" alt="An example of the Tidy output with some errors in it" width="300" height="123" /></a><p class="wp-caption-text">An example of the Tidy output with some errors in it</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2010/01/keeping-your-html-valid-with-zend-framework-tidy-and-firebug/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Massive zend framework poster \ cheatsheet</title>
		<link>http://www.rmauger.co.uk/2009/08/massive-zend-framework-poster-cheatsheet/</link>
		<comments>http://www.rmauger.co.uk/2009/08/massive-zend-framework-poster-cheatsheet/#comments</comments>
		<pubDate>Sat, 15 Aug 2009 11:14:39 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/2009/08/massive-zend-framework-poster-cheatsheet/</guid>
		<description><![CDATA[Massive zend framework poster \ cheatsheet Originally uploaded by bittarman The other day, a wonderful thing arrived in the post, fresh from Björn Schotte of mayflower. The poster covers many of the commonly used components, and their parameters. I have had it on the wall for about 2 weeks now, and it has become something [...]]]></description>
			<content:encoded><![CDATA[<div style="float: right; margin-left: 10px; margin-bottom: 10px;">
<a href="http://www.flickr.com/photos/bittarman/3791750118/" title="photo sharing"><img src="http://farm3.static.flickr.com/2597/3791750118_47f1daa6d2_m.jpg" alt="" style="border: solid 2px #000000;" /></a><br />
<br />
<span style="font-size: 0.9em; margin-top: 0px;"><br />
<a href="http://www.flickr.com/photos/bittarman/3791750118/">Massive zend framework poster \ cheatsheet</a><br />
<br />
Originally uploaded by <a href="http://www.flickr.com/people/bittarman/">bittarman</a><br />
</span>
</div>
<p>The other day, a wonderful thing arrived in the post, fresh from Björn Schotte of mayflower.</p>
<p>The poster covers many of the commonly used components, and their parameters. I have had it on the wall for about 2 weeks now, and it has become something of a crutch already, and makes it very handy to quickly check, for example whether it&#8217;s dispatchLoopShutdown or dispatchLoopShutDown in a FC plugin, or what the parameters for the headLink helper are (two things I always have to double check!)</p>
<p>Mayflower is a partner of Zend, and offers many training and  consulting services for PHP companies, as well as developing their own software solutions, such as the &#8220;Chorizo!&#8221; security auditing suite, and consulting for the popular lightweight webserver &#8220;lighttpd&#8221;.</p>
<p>Check out the mayflower site at <a href="http://www.mayflower.de/en">http://www.mayflower.de/en</a>, and drop Björn Schotte an email if you are interested in a poster of your own, he may have some left!<br />
<br clear="all" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2009/08/massive-zend-framework-poster-cheatsheet/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating simple, extendible CRUD, using Zend Framework</title>
		<link>http://www.rmauger.co.uk/2009/06/creating-simple-extendible-crud-using-zend-framework/</link>
		<comments>http://www.rmauger.co.uk/2009/06/creating-simple-extendible-crud-using-zend-framework/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 20:30:16 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=66</guid>
		<description><![CDATA[The Form Creating a nice, easy to maintain form, starts with a form class. Creating your forms procedurally in your controller/actions is horrid. please don&#8217;t do it. To start with creating your form classes, you need your own namespace in your library. If you don&#8217;t have this, register one. This can be done by adding [...]]]></description>
			<content:encoded><![CDATA[<h3>The Form</h3>
<p>Creating a nice, easy to maintain form, starts with a form class. Creating your forms procedurally in your controller/actions is horrid. please don&#8217;t do it.</p>
<p>To start with creating your form classes, you need your own namespace in your library. If you don&#8217;t have this, register one. This can be done by adding an _initAutoloading method to your Bootstrap. below is a short example. its not comprehensive (you can also do this in your ini i believe, but I use php configuration files similar to <a title="DASPRiD's blog. native cachable configuration" href="http://www.dasprids.de/blog/2009/05/08/writing-powerful-and-easy-config-files-with-php-arrays" target="_blank">DASPRiD</a>&#8216;s, and i&#8217;m not trying to show how to set up autoloading here.)<span id="more-66"></span></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Bootstrap <span style="color: #000000; font-weight: bold;">extends</span> Zend_Application_Bootstrap
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//...</span>
    <span style="color: #009933; font-style: italic;">/**
    * Initilise autoloader and library namespaces
    */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> _initAutoloading<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$loader</span> <span style="color: #339933;">=</span> Zend_Loader_Autoloader<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$loader</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerNamespace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'My_'</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;">//...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Your next task, create a form. This is pretty simple. I will demonstrate using just a few fields. Create a file in your library called My/Form.php</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Form <span style="color: #000000; font-weight: bold;">extends</span> Zend_Form
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
    * Set up form fields, filtering and validation
    */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</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><span style="color: #004000;">setMethod</span><span style="color: #009900;">&#40;</span>Zend_Form<span style="color: #339933;">::</span><span style="color: #004000;">METHOD_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//Username</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uname</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element_Text<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'username'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$uname</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Username'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Db_NoRecordExists'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'users'</span><span style="color: #339933;">,</span>
                                                               <span style="color: #0000ff;">'field'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'username'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Alnum'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'allowWhiteSpace'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//Email</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$email</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element_Text<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$email</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Email'</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Db_NoRecordExists'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'users'</span><span style="color: #339933;">,</span>
                                                               <span style="color: #0000ff;">'field'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EmailAddress'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//First name</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$firstname</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element_Text<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'firstname'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$firstname</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'First name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//Last name</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lastname</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element_Text<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lastname'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$lastname</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Last name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now that your basic form is created, you need to add a method to perform your CRUD. I&#8217;m not actually going to cover the D (delete) as thats realy simple, and doesn&#8217;t require the form, which is the focus of this post.</p>
<p>This method should take an array for the post data, and a Zend_Db_Table_Row to provide the save functionality. In this example the DB columns have the same names as the form fields, this means we can set values with less code. As we are using Zend_Db, there should be no injection problems with this method, as everything is automagically quoted.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #666666; font-style: italic;">//...</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> process <span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$post</span><span style="color: #339933;">,</span> Zend_Db_Table_Row  <span style="color: #000088;">$row</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><span style="color: #004000;">setDefaults</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// If the id (primary key) is null then this is a new row, else it is an existing record</span>
        <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;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// Record already exists, exclude it from db record validation.</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'username'</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Db_NoRecordExists'</span><span style="color: #339933;">,</span>
                                 <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                                 <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'users'</span><span style="color: #339933;">,</span>
                                          <span style="color: #0000ff;">'field'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'username'</span><span style="color: #339933;">,</span>
                                          <span style="color: #0000ff;">'exclude'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'field'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
                                                                      <span style="color: #0000ff;">'value'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Db_NoRecordExists'</span><span style="color: #339933;">,</span>
                                 <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                                 <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'users'</span><span style="color: #339933;">,</span>
                                         <span style="color: #0000ff;">'field'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'email'</span><span style="color: #339933;">,</span>
                                         <span style="color: #0000ff;">'exclude'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'field'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
                                                                    <span style="color: #0000ff;">'value'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            try <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFromArray</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValues</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDescription</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'There was an error saving your details'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<h2>The Controller / Action</h2>
<p>Now that we have created our nice form (which is capable of CR and U)  now we need to use it from within out controller and model to perform the update or insert and interact with the user.</p>
<p>For this, you need 3 actions in your controller, Create, update, and delete (the delete I will not cover for the before mentioned reasons).</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> UserController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> newAction <span style="color: #009900;">&#40;</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;">ViewRenderer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setScriptAction</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'userform'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$users</span> <span style="color: #339933;">=</span> My_Users<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$users</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNewUserForm</span><span style="color: #009900;">&#40;</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;">-&gt;</span><span style="color: #004000;">getPost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$user</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: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addMessage</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'New User Created'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirector</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">gotoUrlAndExit</span><span style="color: #009900;">&#40;</span><span style="color: #009933; font-style: italic;">/** confirmation url here **/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</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;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> editAction<span style="color: #009900;">&#40;</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;">ViewRenderer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setScriptAction</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'userform'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">===</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span> <span style="color: #339933;">=</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: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</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: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Tampered URI'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$users</span> <span style="color: #339933;">=</span> My_Users<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$users</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEditUserForm</span><span style="color: #009900;">&#40;</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;">-&gt;</span><span style="color: #004000;">getPost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$user</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: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addMessage</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Details Saved'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirector</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">gotoUrlAndExit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user/edit/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</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;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>To explain what all this is about, Both actions do pretty similar things (infact this can be consolidated into a single action, but for clarity and ease of replication, I am using two).</p>
<p>There are two things which are pretty important in this, one is the use of the redirector, and the other is the checking of the ID before it is used. In my opinion when an id is passed in a url which is invalid, then a 404 should be raised. So in my error controllers i look for a variety of exception types so that i can debug, but only output a 404 for these in production.</p>
<p>Now looking more closely at the action code, we have calls to getxxxxUserForm() on our models. The return value of this is what we wish to inspect, as you could see in the process method we created earlier, we return boolean true, only when the record saves correctly.  So we do a strict check for this boolean value, and if it is true, we know that we can safely redirect our user. The redirect is an important step, it stops the browser trying to post the data again if the user clicks refresh after their record is created / updated. And the final note is that the flashMessenger is used to pass a message to inform that user that their action was completed on.</p>
<p>Also worth noting is that i have set both actions to use the same action name in the viewRenderer. This allows you to consolidate this common script into one. (repeat after me, Dont Repeat Yourself!). The view script for this is pretty simple.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;div class=&quot;messages&quot;&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span>Zend_Controller_Action_HelperBroker<span style="color: #339933;">::</span><span style="color: #004000;">getStaticHelper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'flashMessenger'</span><span style="color: #009900;">&#41;</span>
             <span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessages</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$message</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;p&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">escape</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<h2>The Model</h2>
<p>In the model, we now need two simple methods to tie the lot together. Now some people might (read: Will) argue that the model should be performing validation, I would argue that with this method, the Model *is* performing the validation, you are simply making use of a library class to perform this function, much in the same way you use Zend_Db_Row. Feel free to flame about this below, but I&#8217;m sticking with this, and it provides clean easy seperation, and provides a good clean mechanism to provide user feedback.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Users
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
    * @var Zend_Db_Table_Abstract
    */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_table</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//....</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
    * Retrieves a new user record, and processes a form against it.
    *
    * @param array $post
    * @return boolean|Zend_Form Boolean true if a save successfully occurs, a populated form on all other conditions
    */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getNewUserForm<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$post</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Form<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">process</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_table<span style="color: #339933;">-&gt;</span><span style="color: #004000;">createRow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
    * Retrieves a user record, and processes a form against it.
    *
    * @param array $post
    * @return boolean|Zend_Form Boolean true if a save successfully occurs, a populated form on all other conditions
    */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getEditUserForm<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$post</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_table<span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchRow</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$table</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Form<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">process</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #339933;">,</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Well, this really doesn&#8217;t need much explanation. this simply provides glue between the parts above. You can make these a little more complex, and infact you probably should (I do!) by sanitizing your input from the controller in the form of the user id, $id, in the edit method.</p>
<h2>In conclusion</h2>
<p>This post has partly been inspired by comments in #zftalk and in part, by the search for a good way to deal with forms, and I look forward to any feedback. Before there is any cirisitm of the validation and filtering in the form, I have kept is minimal to illustrate how the form element deals with two validators of the same name (by overwriting the first instance) and how that can be leveraged to your advantage, and also to keep the code minimal to outline the actual process, and not how to add validators. for that go and <a title="Zend Frame work manau" href="http://framework.zend.com/manual/en" target="_blank">RTFM</a>! <img src='http://www.rmauger.co.uk/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2009/06/creating-simple-extendible-crud-using-zend-framework/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Zend Framework 1.8 is upon us!</title>
		<link>http://www.rmauger.co.uk/2009/05/zend-framework-18-is-upon-us/</link>
		<comments>http://www.rmauger.co.uk/2009/05/zend-framework-18-is-upon-us/#comments</comments>
		<pubDate>Fri, 01 May 2009 20:05:53 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=69</guid>
		<description><![CDATA[Thats right, 1.8 is here! And with it comes with a whole bag load of new features, 4 of which i'm very eager to get using, in Zend_Application, and Zend_Tag, and Zend_Tool, and Zend_Navigation. There is another component which interests me, which is of course Zend_Validate_Db_RecordExists and Zend_Validate_Db_NoRecordExists, which were my small contribution to this release.
]]></description>
			<content:encoded><![CDATA[<h3>Thats right, 1.8 is here!</h3>
<p>And with it comes with a whole bag load of new features, 4 of which i&#8217;m very eager to get using, in Zend_Application, and Zend_Tag, and Zend_Tool, and Zend_Navigation. There is another component which interests me, which is of course <em>Zend_Validate_Db_RecordExists</em> and <em>Zend_Validate_Db_NoRecordExists</em>, which were my small contribution to this release.</p>
<p><span id="more-69"></span></p>
<p><strong>Zend_Application</strong> is a whole new way to bootstrap you application, and encompasses a whole bag of new features. One of which is a new autoloader, which of course means that the old one has now been depreciated. You can find excellent instruction on upgrading your legacy applications to 1.8&#8242;s new autoloader (to avoid the notices it will generate) at <a href="http://akrabat.com/2009/04/30/zend_loaders-autoloader_deprecated-in-zend-framework-18/">Akrabats blog</a>, His famous <a title="Akrabats Zend Framework tutorial" href="http://akrabat.com/2009/05/01/zend-framework-tutorial-for-zf-18/" target="_blank">tutorial </a>has also been updated to encompass 1.8 and its new features. If you want the full low-down of the new autoloader, a slightly more in depth look can be found at <a title="The word on Zend_Loader_Autoloader by Matthew weierophinney" href="http://devzone.zend.com/article/4525-Developing-a-Comprehensive-Autoloader" target="_blank">devzone</a></p>
<p><strong>Zend_Tool</strong> is The new CLI tool to provide scaffolding for your applications. It will save some of the tedium of setting up an application directory strucure, creating the various bootstrap, htaccess, and other miscelanous files you need to get you application started. Even better news about Zend_Tool, it will set your new application up to use Zend_Application, so you can get started with two of the latest features, simply by starting a new project! (I can&#8217;t wait!!)</p>
<p><strong>Zend_Tag</strong> is a new component for generating those lovely new-fangled tag clouds you see on everyones blogs. It is a pretty simple to use component, but possibably my favourite feature is its weighting system, which i can see being useful for more than just generating simple tag clouds, but, with a little extension, also for relevancy matching. This is something i will definatly be adding to my current CMS application project which is consuming so much of my time currently. Also worth looking at, is DASPRiD&#8217;s <a title="Zend_Tag_Cloud screencast" href="http://www.dasprids.de/blog/2009/04/24/zend-tag-cloud-screencast">screencast </a>detailing how to use Zend_Tag to generate clouds, and how the decorators work. He even demonstrates it being used in a CLI application (Genius!), and as the author of Zend_Tag, obviously watching this screencast will be like getting instruction straight from the horses mouth.</p>
<p><strong>Zend_Navigation</strong> is a nice way to create menus for your site. Its also a great way to optimise your site for indexing by search engines. It also provides a way to avoid using the dreded action(viewhelper|stack) for creating menus! Put simply this component should be used by everyone. I know i will be using it as soon as i get the chance to work it into my projects.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2009/05/zend-framework-18-is-upon-us/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Why the Zend Framework Actionstack is Evil</title>
		<link>http://www.rmauger.co.uk/2009/03/why-the-zend-framework-actionstack-is-evil/</link>
		<comments>http://www.rmauger.co.uk/2009/03/why-the-zend-framework-actionstack-is-evil/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 11:14:34 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Action Stack]]></category>
		<category><![CDATA[Dispatch Loop]]></category>
		<category><![CDATA[Fat Models]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Thin Controllers]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=45</guid>
		<description><![CDATA[The action stack seems to be a useful component to some people when starting out with the Zend Framework. This component is a seemingly un-needed part of the framework, as there really is no use-case for it which cannot be simplified with the use of a partial view, which reads data directly from the model, [...]]]></description>
			<content:encoded><![CDATA[<p>The action stack seems to be a useful component to some people when starting out with the <a href="http://framework.zend.com/" target="_blank">Zend Framework</a>. This component is a seemingly un-needed part of the framework, as there really is no use-case for it which cannot be simplified with the use of a partial view, which reads data directly from the model, possibly with a view helper alongside to provide some additional logic function, such as deciding on which view partial to use.</p>
<p>This part of the Framework causes the dispatch to loop. This is a costly process, as it involves quite alot. It also adds some further issues to your application design, such as where you should put code. for example if you have some code in your predispatch, and your looping through two actions in that controller, that code will be run twice. This is obviously, not good, and quite un-needed. Further complications can be added when it comes time to add ACL or authentication.</p>
<p><span id="more-45"></span></p>
<p>There is an even worse part of this feature, the <a title="The Action View Helper" href="http://framework.zend.com/manual/en/zend.view.helpers.html#zend.view.helpers.initial.action">Action View Helper</a>. This helper basically creates an additional dispatch, copying the request object, and creating a loop-within-a-loop . The setting up of the dispatch process is a costly one, anyone who has profiled their code will have seen just how much of the process of a <a title="Zend Framework" href="http://framework.zend.com/" target="_blank">Zend Framework</a> application this eats up. Creating a whole extra dispatch must be a <strong>bad</strong> idea, even the <a title="Increasing performance of Zend Framework Applications" href="http://framework.zend.com/manual/en/performance.html" target="_blank">Zend Framework Performance Guide</a> notes this fact</p>
<p>So, lets go through some reasons for this being bad.</p>
<h2>Why its bad</h2>
<h3>Performance</h3>
<p>Every time you go through the dispatch process, there are a number of things which are done, which will be completly un-nessicary for your action, namely calling preDispatch and postDispatch for each action which is called. This often results in questions in #zftalk of &#8220;Why is my ACL being called twice?&#8221;. If you have an ACL being built in your preDispatch (as many people quite rightly do) this means if you have 3 calls to different actions, your ACL will be built, and queried 3 times, and if you haven&#8217;t cached your ACL object, this may incur extra overhead from calls to database queries.</p>
<p>This is even more apparent if you use the action helper, as the request is copied, and a new dispatch created (profile your code and see just how much overhead this involves, its a lot!).</p>
<h3>Unnecessary Complexity</h3>
<p>Trying to follow the application flow through an application which utilises the action stack adds a level of complexity which need not be there.</p>
<p>If you want to see what&#8217;s going on at a URL, you should be able to go to that action, and see which model methods are being invoked, and what is being passed to the view.</p>
<h3>Design Issues</h3>
<p>This is the biggest reason for not using the action stack. If you are using the action stack, you are almost certainly a long way from a true &#8220;MVC&#8221; design. The units of code you are using in your actions, probably belongs in the model.</p>
<p>Your model should encapsulate all the code to extract data, insert data, and manipulate objects, so all your controller action should include is a bunch of calls to the model to fetch data, or insert/update it, but in the form of single method calls only. remember you should be directing the data to the model, not manipulating it.</p>
<h2>Why it is good</h2>
<h3>Illusion of DRY coding</h3>
<p>The action stack can lead you into a false sense of security that your writing nice &#8220;DRY&#8221; code. You are in fact writing dry code, but usually in the wrong place, in fact, if your code is not abstracted into your model, it will end up no-longer being dry, as you will end up with two actions with overlapping functionality, and as such, overlapping code!</p>
<h2>The way forward</h2>
<h3>Fat Models, Thin Controllers</h3>
<p>Your controllers should be minimalist. they exist only to direct data, and to provide some interface to HTTP actions such as redirects.</p>
<p>The bulk of the code in your application should be in your model. For example, if you are writing a blog application, and the action you are writing produces a list of posts. This should require in the action, nothing more than a call to $model-&gt;getPosts(); possibly passing one or more paramaters from the URL (such as year and month) as parameters to the method.</p>
<p>This not only allows you to do away with the action stack, but also allows your code to be portable throughout the application, in true DRY style.</p>
<p>There is an upcomming book, which has a very good overview of how these kinds of models should be written. You can read it <a title="The Zend Framework and Writing Models" href="http://www.survivethedeepend.com/zendframeworkbook/en/1.0/the.model">here</a></p>
<h3>View Helpers</h3>
<p>View helpers can be useful for items which you frequently need, or for items which are simply too small to justify writing a whole view script for them. there is a good example in the <a title="Writing a view helper to replace an action() call" href="http://framework.zend.com/manual/en/performance.view.html#performance.view.action.model">performance guide</a>.</p>
<p>When you want to perform some logic before rendering a view script, a view helper can also be useful to help keep your layout or view free of large switches or if statements. For example this can be something like rendering a login form when a user is not logged in (which would require no view script, only a Zend_Form object), and a menu when they are, or be useful to set up some context for a view partial before rendering it, so that your controller does not have to pass a variable to the view when it would be some default value.</p>
<h3>(Partial) Views</h3>
<p>Partial views do the leg work of replacing the actionstack. In your partial views, you should call read-only methods of the model, to build items such as menus. this could be something like $model-&gt;getSideBarMenuItems(); which would return a dataset to loop through and render.</p>
<h2>Some other notes</h2>
<p>There has been an issue raised in the Zend Framework JIRA (<a title="Zend Framework Jira Issue tracker" href="http://framework.zend.com/issues/browse/ZF-5840">ZF-5840</a>) with regard to removing the action view helper for ZF version 2.0. This is somewhere you may wish to post your opinion on this subject (keep it specific!), or vote to have it removed <img src='http://www.rmauger.co.uk/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2009/03/why-the-zend-framework-actionstack-is-evil/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
		<item>
		<title>Zend Framework, Zend_Dojo and  Dojo Tree</title>
		<link>http://www.rmauger.co.uk/2009/02/zend-framework-zend_dojo-and-dojo-tree/</link>
		<comments>http://www.rmauger.co.uk/2009/02/zend-framework-zend_dojo-and-dojo-tree/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 20:10:30 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[Dojo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=18</guid>
		<description><![CDATA[Working on a new CMS at work, I needed to allow a user to insert a page at a point in the site tree. And i thought to myself, well, Dojo has a tree widget, and Zend Framework supports dojo, it can&#8217;t be a difficult task. Unfortunately I was unable to find a &#8216;simple&#8217; method [...]]]></description>
			<content:encoded><![CDATA[<p>Working on a new CMS at work, I needed to allow a user to insert a page at a point in the site tree. And i thought to myself, well, Dojo has a tree widget, and Zend Framework supports dojo, it can&#8217;t be a difficult task.</p>
<p>Unfortunately I was unable to find a &#8216;simple&#8217; method of doing this already documented, so I experimented a little, and threw away some very in-elegant ideas, and finally came up with the following technique, after discovering the <a title="Zend dojo data envelopes" href="http://framework.zend.com/manual/en/zend.dojo.data.html" target="_blank">Zend_Dojo_Data</a>.</p>
<p><span id="more-18"></span></p>
<p>Firstly, I added a method to my tree model to walk the tree, and build an array suitable for turning into the required structure for the json.</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> SiteTree <span style="color: #000000; font-weight: bold;">extends</span> Zend_Db_Table_Abstract
<span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//....</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _walkTree<span style="color: #009900;">&#40;</span><span style="color: #990000;">Array</span> <span style="color: #000088;">$root</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$root</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       <span style="color: #000088;">$root</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBranchChildren</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$arrNodes</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$root</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$branch</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$thisPath</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'branch_name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$path</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'branch_name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'0'</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$arrNodes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span>       <span style="color: #339933;">=</span> <span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$arrNodes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'label'</span><span style="color: #009900;">&#93;</span>    <span style="color: #339933;">=</span> <span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'branch_name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$arrNodes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'path'</span><span style="color: #009900;">&#93;</span>     <span style="color: #339933;">=</span> <span style="color: #000088;">$thisPath</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$arrNodes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'iconClass'</span><span style="color: #009900;">&#93;</span>     <span style="color: #339933;">=</span> <span style="color: #0000ff;">'folder'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$arrNodes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$branches</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBranchChildren</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$branch</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$arrNodes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_walkTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$branches</span><span style="color: #339933;">,</span> <span style="color: #000088;">$thisPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$i</span><span style="color: #339933;">++;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$arrNodes</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//....</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This function recursively maps the database into a nested array. Please note, this function will cause many database queries on deep tree structures, so I really would advise you cache the return of this function, so to keep queries to a minimum.</p>
<p>The line &#8220;$key = ($branch['parent'] == &#8217;0&#8242;) ? $branch['id'] : $i;&#8221; is important. For Zend_Dojo_Data to output the correctly formatted json, you need to have an associative array for the top level (root) nodes, and indexed arrays for all of their children.</p>
<p>Next, this data needs to be turned into json for the tree. To do this, I simply created a new action to use as the source for the json, and inserted the following:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> jsonNewpageAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    Zend_Dojo<span style="color: #339933;">::</span><span style="color: #004000;">enableView</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Zend_Layout<span style="color: #339933;">::</span><span style="color: #004000;">getMvcInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">disableLayout</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$tree</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SiteTree<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$treeObj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Dojo_Data<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tree</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$treeObj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'label'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$treeObj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMetadata</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'path'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</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;">tree</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$treeObj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toJson</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Setting the Label is important here, it is used to determine which attribute of each node is its label, next the Metadata attribute &#8220;path&#8221; I used for my customisation of the tree for my own needs, which you will see later. The view script for this action simply echo&#8217;s the tree value.</p>
<p>The next step is to create the view to output your tree. this part is where the real fun begins, as you can get carried away with tweaking the dojo widget if your not careful.</p>
<p>The following lines were added to the action with my form on it. (The tree is not part of the form, I simple made mine interact with a read only element inside it)</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Zend_Dojo<span style="color: #339933;">::</span><span style="color: #004000;">enableView</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<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;">dojo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireModule</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'dojo.data.ItemFileReadStore'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</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;">dojo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireModule</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'dijit.Tree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</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;">dojo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireModule</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'dojo.parser'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This will add the require statements to the view, so that the required dojo parts are available.</p>
<p>And in the view itself, you need at least the following:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div dojoType=&quot;dojo.data.ItemFileReadStore&quot;  url=&quot;/admin/pages/json-newpage&quot; jsid=&quot;jsonData&quot;&gt;&lt;/div&gt;
&lt;div dojoType=&quot;dijit.tree.ForestStoreModel&quot; jsId=&quot;treeModel&quot; store=&quot;jsonData&quot; rootId=&quot;treeRoot&quot; rootLabel=&quot;Home&quot; childrenAttrs=&quot;children&quot; &gt;&lt;/div&gt;
&nbsp;
&lt;div dojoType=&quot;dijit.Tree&quot; model=&quot;treeModel&quot; labelAttrs=&quot;label&quot; &gt;&lt;/div&gt;</pre></div></div>

<p>The first div, is the part which will read your json from the first action I listed. If you have only a single root node, you may get away without the second div, which is the ForestStoreModel. The ForestStoreModel had me scratching my head for a while, as I had no idea I needed it, and I kept finding errors in my FireBug console. Eventually I found <a title="The dojo model - An explanation of the ForestStoreModel" href="http://dojotoolkit.org/2008/02/24/dijit-tree-and-dojo-data-dojo-1-1-model" target="_blank">this</a> page on the dojo site.</p>
<p>If you were to put all this together now, you would probably end up with a working tree. BUT, it can be improved. In my tree, all the leaves would actually represent folders, but as default they look like little documents, not good at all. So I asked around in IRC, and was told I needed to google getIconClass, which put me on to writing this,</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>div dojoType<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;dijit.Tree&quot;</span> model<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;treeModel&quot;</span> labelAttrs<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;label&quot;</span> iconClass<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;dijitFolderOpened&quot;</span><span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;dojo/method&quot;</span> event<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;getIconClass&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #b1b100;">return</span>  <span style="color: #0000ff;">'dijitFolderClosed'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></div></div>

<p>As you can see, a script is inserted INSIDE the container of the tree, and the event attribute tells the script which even it is responsible for overriding.</p>
<p>If you run this now, you will find that all of the folders in the tree are now closed. Not good, as the nice opening and closing folders as you expand/contract elements are lost. This can be changed by adding another attribute to the script:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;dojo/method&quot;</span> event<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;getIconClass&quot;</span> args<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;item, opened&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>opened ? <span style="color: #0000ff;">'dijitFolderOpened'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">'dijitFolderClosed'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></pre></div></div>

<p>The args attribute allows arguments from the item firing the event to be passed to the script. so a simple ternary, and you can switch between opened and closed folders.</p>
<h2>Update</h2>
<p>You may also find <a title="Codeutopia.net Zend Framework and Dojo Tree's with Checkboxes" href="http://codeutopia.net/blog/2008/11/21/creating-a-dojo-dijittree-with-checkboxes/" target="_blank">this</a> post at codeutopia.net useful if you are working with tree&#8217;s in Dojo / Zend Framework</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2009/02/zend-framework-zend_dojo-and-dojo-tree/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>My first Zend Framework proposal is now in incubator!</title>
		<link>http://www.rmauger.co.uk/2009/01/my-first-zend-framework-proposal-is-now-in-incubator/</link>
		<comments>http://www.rmauger.co.uk/2009/01/my-first-zend-framework-proposal-is-now-in-incubator/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 20:57:17 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[Proposal]]></category>
		<category><![CDATA[validator]]></category>
		<category><![CDATA[Validators]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.rmauger.co.uk/?p=16</guid>
		<description><![CDATA[My previous post was all about my proposal for a database lookup validator for Zend Framework. This proposal has now been accepted and is available in the incubator. During the process of refining the proposal, Ralph Schindler suggested renameing the validator, and splitting it in two, to make it as verbose as possible (i.e. the [...]]]></description>
			<content:encoded><![CDATA[<p>My previous post was all about my proposal for a database lookup validator for Zend Framework.</p>
<p><span id="more-16"></span></p>
<p>This proposal has now been accepted and is available in the incubator.</p>
<p>During the process of refining the proposal, Ralph Schindler suggested renameing the validator, and splitting it in two, to make it as verbose as possible (i.e. the name says exactly what it does). So, an abstract class has been added, and the DbMatch name dropped. The validators are  now called Zend_Validate_Db_RecordExists and Zend_Validate_Db_NoRecordExists. check the <a title="Check a user does not already exist with Zend Framework" href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Validate_Db_RecordExists+-+Zend_Validate_Db_NoRecordExists+-+Ryan+Mauger">wiki page</a> for more information.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rmauger.co.uk/2009/01/my-first-zend-framework-proposal-is-now-in-incubator/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

