<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>A.J. Brown's Blog</title>
	
	<link>http://ajbrown.org/blog</link>
	<description>Coding adventures and technology musing for the masses</description>
	<pubDate>Sat, 02 May 2009 20:18:12 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ajbrowns_blog" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>What does “meeting the dealine” mean to you?</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/AMMQwUt0tzU/</link>
		<comments>http://ajbrown.org/blog/?p=195#comments</comments>
		<pubDate>Sat, 02 May 2009 20:18:12 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=195</guid>
		<description><![CDATA[One of the most important aspects of maintaining good relationships is doing what you say you&#8217;re going to do, when you say you&#8217;re going to do it.  As a software developer, your time to shine in this context is delivering the goods before your customer has to wonder where they are.
It&#8217;s equally important to [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most important aspects of maintaining good relationships is doing what you say you&#8217;re going to do, when you say you&#8217;re going to do it.  As a software developer, your time to shine in this context is delivering the goods before your customer has to wonder where they are.</p>
<p>It&#8217;s equally important to know what done means to the customer, and how it may conflict with your definition of done.  If I&#8217;m hiring you to line a parking lot for my store, and the deadline is the day of the grand opening, done is when the paint is dry, not when the last stroke is sprayed (and still wet!).  Since I don&#8217;t paint asphalt for a living, you surely can&#8217;t expect me to know how long it takes the paint to dry.</p>
<h3 id="toc-a-real-world-example">A Real World Example</h3>
<p>I once worked for an international online retailer who&#8217;s idea of &#8220;meeting a deadline&#8221; was a little different than mine.  We were scheduled to do a major release of the website consisting of a brand new design, and some additional features.  It had a large supporting marketing campaign advertising it as a new generation of the store with super-awesome-o features.  A hard launch date was set in the marketing material and community hype, so launching on that date was critical.  The developers (through no fault of their own) ended up needing to work 20+ hour shifts in the days approaching the launch in order to make sure all of the promised features made the cut.  After gallons of coffee and mountain dew, the launch was finally completed at 11:50pm local time on the day of the deadline.</p>
<p>In the coming days, the launch was touted as a total success, and the words &#8220;we met the deadline&#8221; were strewn about the meeting halls by the software development managers.  I felt that expressing my opinion about the so called meeting of the deadline would create a lot of flak and would be taken as a slam to my fellow developers, so I decided to keep it to myself.  </p>
<p>Quite frankly, this was not a satisfactory meeting of the deadline in my opinion.  The expectation as a customer of the site was that they would log-on on the launch date and see a brand new website with pretty little features.  Instead, we kept them waiting and wondering.  Our blog site for the store was lit up with comments by loyal customers, wondering where the site is. Many had given up on it being launched that day, and only those 7 hours behind GMT (the time zone any international company should be paying attention to) or greater actually saw the website on the launch date.  Yet, we were proud of meeting this tough deadline because &#8220;hey, we technically finish it on the date we promised!&#8221;.</p>
<p>The real issue in the online retailer case is the approach to the problem.  The delivery date and the marketing campaign date should not have been the same.  The deadline for software development should have been at least 1 day prior to the launch, giving the developers a deadline that could be approached in the manner it was, but still allowing the site to actually be launched and available to the customer when they expected it to be.  The developers could push their efforts right up to the wire (as we did) without any negative impact.</p>
<h3 id="toc-conclusion">Conclusion</h3>
<p>You&#8217;ve probably heard the saying &#8220;If you&#8217;re 5 minutes early, you&#8217;re on time.  If you&#8217;re on time, you&#8217;re late!&#8221; or some similar version of it.  This saying definitely holds a lot of merit when it comes to delivering your products.  Surprise your customers and clients by delivering &#8220;5 minutes early&#8221; instead of making them come looking.  Don&#8217;t use the vagueness of your own deadline as an excuse to say you delivered on time.  Save that for the cable company, and their &#8220;sometime between 9am and 5pm&#8221; appointments.</p>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/AMMQwUt0tzU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=195</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=195</feedburner:origLink></item>
		<item>
		<title>Zend_Service_PayPal Proposal Back on Track</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/w27amkOAnzc/</link>
		<comments>http://ajbrown.org/blog/?p=192#comments</comments>
		<pubDate>Tue, 03 Feb 2009 19:01:37 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Zend Framework]]></category>

		<category><![CDATA[Zend_Service_PayPal]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=192</guid>
		<description><![CDATA[I just wanted to drop a quick note letting everyone know that after nearly 2 years of dormancy, Zend_Service_PayPal is back in the works.  Shahar Evron has been too busy with his work over at Zend Technologies to continue work on the proposal, so I&#8217;ve volunteered my time to get it back on track.
If [...]]]></description>
			<content:encoded><![CDATA[<p>I just wanted to drop a quick note letting everyone know that after nearly 2 years of dormancy, Zend_Service_PayPal is back in the works.  <a href="http://prematureoptimization.org/blog/">Shahar Evron</a> has been too busy with his work over at Zend Technologies to continue work on the proposal, so I&#8217;ve volunteered my time to get it back on track.</p>
<p>If you&#8217;re interested in seeing this component in Zend Framework soon, please follow progress at the <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Service_PayPal+-+A.J.+Brown">Zend Framework Contributors Wiki</a>, This blog, and on the <a href="http://github.com/ajbrown/zend_service_paypal" alt="GitHub Zend_Service_Paypal">project page at GitHub</a>.  Any feedback, suggestions, and patches you can provide will be nothing but useful.  Send me an email, comment on the wiki, or This proposal is still in it&#8217;s early stages, but I hope to be knocking out a lot of the work in the next couple of weeks.</p>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/w27amkOAnzc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=192</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=192</feedburner:origLink></item>
		<item>
		<title>Learning What You Don’t Know, So That You Do</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/EyCipZrD7CE/</link>
		<comments>http://ajbrown.org/blog/?p=185#comments</comments>
		<pubDate>Fri, 30 Jan 2009 20:53:01 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[Opinion]]></category>

		<category><![CDATA[Software Engineering]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=185</guid>
		<description><![CDATA[It&#8217;s been a very busy couple of weeks for me, and I&#8217;ve fallen behind on some of the articles I&#8217;ve promised to write.  I&#8217;ve begun drafting them again, but I wanted to take some time out to talk about something a little more philosophical than technical.
For me, learning the areas that I&#8217;ve yet to [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a very busy couple of weeks for me, and I&#8217;ve fallen behind on some of the articles I&#8217;ve promised to write.  I&#8217;ve begun drafting them again, but I wanted to take some time out to talk about something a little more philosophical than technical.</p>
<p>For me, learning the areas that I&#8217;ve yet to master has been a huge motivation to keep pushing the envelope of my own knowledge.  I consider myself a very capable developer, and I don&#8217;t feel that my co-workers, clients, or associates would say otherwise. At the same time, I know I still have a lot to learn.  In fact, anyone that says they&#8217;re a master of every craft of web and software development probably hasn&#8217;t learned enough to know what there is to know.  This blog itself is a consequence of my desire to explore more technologies and techniques.</p>
<p>The best gift I&#8217;ve been given recently is a true evaluation of my level of mastery.  This particular evaluation came interview-style from a Zend developer and client support specialist (meaning their salary is paid by Zend Technologies).  Before I entered the conversation, I knew it would be highly technical.  After all, you&#8217;re talking about <em>the</em> PHP company.   I&#8217;ve been writing code in PHP for 7 years, am Zend Certified, ranked #3 on oDesk for the Advanced PHP Expert Rating test, placed top 10% in many other assessment tests on other freelance sites, yadda yadda yadda.  While none of this equates to guru, it does equate to experience and track record with the language.  Thus, I expected to be stumped occasionally, but stride through most of it as usual. </p>
<p>As you can imagine, that wasn&#8217;t the case.</p>
<p>Overall, I did OK with the evaluation.  The questions that I was truly stumped on were things that only the best of the best would know off-hand (and even my evaluator admitted to not knowing the answer until he started working at Zend).  Then, of course, there were the middle-ground questions that I knew most of the answer to, but there was a small edge-case that I didn&#8217;t think of, or that took me a bit of thinking to come up with.  But what surprised me the most were the questions that I did know (or should have known) off hand because I encounter them every day, but have been numb to the rhyme-or-reason of them.  I won&#8217;t even mention getting a question wrong that I obviously knew the answer to, but was to worried about it being a trick question to think it all the way through.</p>
<p>I won&#8217;t get into specifics of the questions that were asked, as I don&#8217;t want to provide a cheat sheet for the next person.  But, the point is this &#8212; being able to academically and fluently explain something on the spot is the true test of how in-depth your knowledge is on a subject.  Don&#8217;t settle for just being able to do it well, but understand why you&#8217;re doing it, how you did it, and what&#8217;s the best way to do it.  The Pragmatic Programmers would call this programming by confidence, not coincidence.</p>
<p>Thanks for making me study harder, Zend <img src='http://ajbrown.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/EyCipZrD7CE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=185</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=185</feedburner:origLink></item>
		<item>
		<title>Automated Testing Using Zend Framework, Part 1</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/BTnsUdE4qqg/</link>
		<comments>http://ajbrown.org/blog/?p=157#comments</comments>
		<pubDate>Sun, 04 Jan 2009 20:05:41 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[PHPUnit]]></category>

		<category><![CDATA[Testing]]></category>

		<category><![CDATA[Zend Framework]]></category>

		<category><![CDATA[Zend_Test]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=157</guid>
		<description><![CDATA[Automated testing for your web applications is an important step in having the confidence to make changes to your application, and still be confident you're delivering a quality, regression-free product.  With Zend Framework's testing framework, you can build a thorough suite of test cases for your web application with very little hassle.]]></description>
			<content:encoded><![CDATA[<div class="toc">
<ol>
<li><a href="http://ajbrown.org/blog/?p=157#toc-preparing-your-application">Preparing Your Application</a></li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-a-basic-example">A Basic Example</a></li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-running-your-tests">Running Your Tests</a></li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-extending-the-testing-functionality">Extending the Testing Functionality</a>
<ol>
<li><a href="http://ajbrown.org/blog/?p=157#toc-disposable-testing-models">Disposable Testing Models</a></li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-authentication-support">Authentication Support</a></li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-putting-it-all-together">Putting It All Together</a></li>
</ol>
</li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-writing-our-controller-test">Writing Our Controller Test</a></li>
<li><a href="http://ajbrown.org/blog/?p=157#toc-conclusion">Conclusion</a></li>
</ol>
</div>
<p>Automated testing for your web applications is an important step in having the confidence to make changes to your application, and still be confident you&#8217;re delivering a quality, regression-free product.  With Zend Framework&#8217;s testing framework (built with <a href="http://phpunit.de">PHPUnit</a>), you can build a thorough suite of test cases for your web application with very little hassle.</p>
<p>Part 1 will give you all of the basic information you need to start writing automated tests for your Zend Framework applications.   In Part 2, I&#8217;ll provide more real-world example covering some other ways to write tests.</p>
<p>Lets get right to it.</p>
<p>For the examples below, I will be using an actual controller from one of my projects.  This controller handles account activies, such as logins, logouts, registrations, and confirmations.  We&#8217;ll be using a test database with a schema that clones our production database, and Doctrine to manage ORM (Sorry Zend_Db :().  I&#8217;ll assume that you&#8217;re using the prescribed Zend Framework (1.6+) project layout, and that you&#8217;re somewhat familiar with <a href="http://framework.zend.com/manual/en/zend.config.html" rel="nofollow">Zend_Config</a> and using an <a href="http://devzone.zend.com/article/3372-Front-Controller-Plugins-in-Zend-Framework">Initializer controller plugin</a> (created by default if you&#8217;re using Zend Studio for Eclipse 6.1).</p>
<h3 id="toc-preparing-your-application">Preparing Your Application</h3>
<p>The first step to setting up automated testing is to prepare your application&#8217;s environment and settings appropriately.  Depending no your setup, this can involve setting global variables, changing database connections, or reconfiguring paths.  Fortunately for us, this capability is easy using Zend_Config and an Initializer controller plugin. </p>
<p>Zend_Config allows you to specify &#8220;sections&#8221;, which can inherit from another section.  This allows you to modify configuration for different environments without duplicating settings across different files (and thereby helping us ensure we don&#8217;t forget to set something!).  In our example project, we&#8217;ll need only to modify our database connection string, so we&#8217;re using the test database.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="xml xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;</span> ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;production<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;db<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dsn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>mysql://dbowner:password@localhost/maindb<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dsn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attributes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;model_loading<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>conservative<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/model_loading<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attributes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/db<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/production<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test</span> <span style="color: #000066;">extends</span>=<span style="color: #ff0000;">&quot;production&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;db<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dsn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>mysql://dbowner:password@localhost/maindb_test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dsn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/db<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p><sup>Notice how we can even inherit child attributes:  Even though we specified a a <db> node, we didn&#8217;t have to specify everything below the </db><db> node</db></sup></p>
<p>Now that we have our configurations in order, we need something to manage this configuration for us, and switch off based on the environment we&#8217;re running in.  That&#8217;s the role of our Initializer plugin, which accepts the environment to initialize as a constructor parameter.  Showing the source of an Initializer is outside the scope of this article, but <a href="http://pastie.org/352285" rel="nofollow">here&#8217;s a pastie for the curious</a>. </p>
<h3 id="toc-a-basic-example">A Basic Example</h3>
<p>Lets start with the basic framework of a controller test.  If you&#8217;re using Zend Studio for Eclipse, you can easily create this structure by right-clicking on your controller in PHP Explorer and selecting <cite>New > Zend Framework Item</cite>, and then selecting <cite>Zend Controller Test Case</cite>.  Then, simply make sure the controller you want to test is chosen, and click finish.
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #b1b100;">require_once</span> <span style="">'Zend/Test/PHPUnit/ControllerTestCase.php'</span>;
<span style="color: #b1b100;">require_once</span> <span style="">'application/Initializer.php'</span>;
<span style="color: #b1b100;">require_once</span> <span style="">'application/default/controllers/IndexController.php'</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> AccountControllerTest <span style="color: #000000; font-weight: bold;">extends</span> Zend_Test_PHPUnit_ControllerTestCase <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Prepares the environment before running a test.
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> setUp<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;">bootstrap</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="">'appBootstrap'</span> <span style="color: #009900;">&#41;</span>;
		parent<span style="color: #339933;">::</span><span style="color: #004000;">setUp</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
		<span style="color: #666666; font-style: italic;">// TODO Auto-generated FooControllerTest::setUp()</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Prepares the environment before running a test.
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> appBootstrap<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;">frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerPlugin</span> <span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> Initializer<span style="color: #009900;">&#40;</span> <span style="">'test'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Cleans up the environment after running a test.
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// TODO Auto-generated FooControllerTest::tearDown()</span>
		parent<span style="color: #339933;">::</span><span style="color: #004000;">tearDown</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Constructs the test case.
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// TODO Auto-generated constructor</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Tests FooController-&gt;barAction()
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testIndexAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// TODO Auto-generated FooControllerTest-&gt;testBarAction()</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dispatch</span> <span style="color: #009900;">&#40;</span> <span style="">'/index/index'</span> <span style="color: #009900;">&#41;</span>;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertController</span> <span style="color: #009900;">&#40;</span> <span style="">'index'</span> <span style="color: #009900;">&#41;</span>;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertAction</span> <span style="color: #009900;">&#40;</span> <span style="">'index'</span> <span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>You&#8217;ll see on <strong>line 20</strong> where we&#8217;re using our initializer to setup the test environment before we run the tests. Before each test metod is run, PHPUnit will call our <cite>setup()</cite> method, which has been programmed to call our appBootstrap method.  This ensures us that we&#8217;re using a clean configuration and environment before each test, as if each test was a separate process.  When each test case is done, the <cite>tearDown()</cite> method is called.   <cite>tearDown()</cite> is the place to put any code for removing resources or resetting any persistable changes that tests might make.  We&#8217;ll make use of this in our advanced examples later.</p>
<p><strong>Line 41</strong> contains a bare-bones test case, which will ensure that dispatching to &#8216;/index/index&#8217; results in the controller named &#8216;index&#8217; and an action called &#8216;index&#8217; are the last to be executed.  This might seem trivial, but it helps detect errors with your controllers.  If an uncaught exception is thrown, the controller assertion will fail, since your controller will be the last executed.</p>
<h3 id="toc-running-your-tests">Running Your Tests</h3>
<p>To keep this article focused, I&#8217;ve decided to remove this section and cover only writing the tests.  If you need help creating Test Suites and running tests from the command line, check out <a rel="nofollow" href="http://www.phpunit.de/manual/3.3/en/">PHPUnit Documentation</a>, specifically the sections on <a rel="nofollow" href="http://www.phpunit.de/manual/3.3/en/textui.html">the Command Line Test Runner</a> and <a rel="nofollow" href="http://www.phpunit.de/manual/3.3/en/organizing-test-suites.html">Organizing Test Suites</a>.  If you have any specific questions, feel free to shoot me an email.</p>
<h3 id="toc-extending-the-testing-functionality">Extending the Testing Functionality</h3>
<p>Now that we covered the basics, lets get to fully testing our Accounts controllers.  There are a couple of &#8220;outside the box&#8221; requirements we have for testing our accounts controller.  First off, we need a way to test the full account creation process, as if a user was actually registering.  When we&#8217;re done with a test, we want to get rid of that data whenever possible, so we can run tests as many times as we want and not worry about growing our test database.  Secondly, We need a way to simulate an authenticated user, as well as checking for whether a user has been authenticated or not.</p>
<p>Because these operations are pretty general and an opportunity for reuse exists, Lets put our supporting logic in a parent class and let our test cases inherit them.</p>
<h4 id="toc-disposable-testing-models">Disposable Testing Models</h4>
<p>There are two ways to ensure the data you&#8217;re creating during a test is deleted once a test is complete.  Some choose to create the database on the fly using seed data.  Since I&#8217;m using Doctrine for my projects and working directly with models (no raw queries) in the tests, I decided that just deleting the data was the best approach.  To do this, all we need to do is &#8220;schedule&#8221; our model for deletion after it has been created (or loaded).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;">protected <span style="color: #000000; font-weight: bold;">function</span> _setDisposable<span style="color: #009900;">&#40;</span> Doctrine_Record <span style="color: #000088;">$model</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>_disposables<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$model</span>;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This function simply takes a reference to a model, and stores it in array, which will be handled by our tearDown() function later:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;">	protected <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
&nbsp;
&nbsp;
	<span style="color: #009900;">&#123;</span>
	    parent<span style="color: #339933;">::</span><span style="color: #004000;">tearDown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_disposables <span style="color: #b1b100;">as</span> <span style="color: #000088;">$model</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;">$model</span> instanceof Doctrine_Record <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	            <span style="color: #000088;">$model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	        <span style="color: #009900;">&#125;</span>
	        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$model</span> <span style="color: #009900;">&#41;</span>;
	    <span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>We simply loop through all of our &#8220;scheduled&#8221; models and delete them.  This must be done in tearDown() and not inside of any test method because it&#8217;s the only way to ensure it happens.  Once an assertion fails or an unexpected exception occurs in a test, that method stops executing.  IF we were to try to dispose our models after an assertion, it may never happen<sup class='footnote'><a href='#fn-157-1' id='fnref-157-1'>1</a></sup>.   Similarly, we obviously can&#8217;t dispose of a model <em>before</em> an assertion if that model is needed for the assertion (and why would it exist if you didn&#8217;t need it?).</p>
<h4 id="toc-authentication-support">Authentication Support</h4>
<p>There are 3 things we must be able to do in order to fully test authentication.</p>
<ul>
<li>Create a fake identity</li>
<li>Set our environment to a state equivalent to a user being logged in.</li>
<li>Assert whether the environment has been changed to a logged in state.</li>
</ul>
<p>Our example controller uses a database adapter for authentication and identity retrieval<sup class='footnote'><a href='#fn-157-2' id='fnref-157-2'>2</a></sup>, so generating a fake identity for us means creating (or loading) a record in our accounts table, and returning the identity data we would normally get.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #0000ff; font-style: italic;">/**
 * Generates a fake identity, usefull for simulating a logged in user
 *
 * @return StdClass an identity
 */</span>
protected <span style="color: #000000; font-weight: bold;">function</span> _generateFakeIdentity<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$identity</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> stdClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
        <span style="color: #000088;">$account</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Account<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">username</span>     <span style="color: #339933;">=</span> <span style="">'AutoTest'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">emailAddress</span> <span style="color: #339933;">=</span> <span style="">'autotest@example.org'</span>;
        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span>     <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span> <span style="">'password'</span> <span style="color: #009900;">&#41;</span>;
        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">confirmed</span>    <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enabled</span>      <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
        <span style="color: #000088;">$account</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setDisposable<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</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: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$val</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	        <span style="color: #000088;">$identity</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$val</span>;
	<span style="color: #009900;">&#125;</span>
	<span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$identity</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$identity</span>;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><cite>Account</cite> is our model, a <cite>Doctrine_Record</cite> type.  We&#8217;re just simply creating a random account, and returning it&#8217;s data as our idenity.  Notice that we&#8217;re also scheduling this model for disposal (as we covered above.) Now, we just need a way to set our environment to the &#8220;logged in state&#8221; as this fake user.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #0000ff; font-style: italic;">/**
 * Sets the current state as if there is a logged in user
 *
 * @param object $identity the idenity to use, otherwise one is generated
 * @return void
 */</span>
protected  <span style="color: #000000; font-weight: bold;">function</span> _doLogin<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$identity</span> <span style="color: #339933;">=</span> <span style="color: #000000; 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;">$identity</span> <span style="color: #339933;">===</span> <span style="color: #000000; font-weight: bold;">null</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$identity</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_generateFakeIdentity<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span>
    Zend_Auth<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;">-&gt;</span><span style="color: #004000;">getStorage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$identity</span> <span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>In our example application, if <a rel="nofollow" href="http://framework.zend.com/manual/en/zend.auth.html">Zend_Auth</a> has an identity, a user must be logged in.  Therefore, all we have to do is store an identity in Zend_Auth&#8217;s storage adapter, and call ourselves logged in.  That makes asserting login as simple as checking for an identity.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> assertNotLoggedIn<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;">assertFalse</span><span style="color: #009900;">&#40;</span> Zend_Auth<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;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="">'Login assertion failed'</span> <span style="color: #009900;">&#41;</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> assertLoggedIn<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;">assertTrue</span><span style="color: #009900;">&#40;</span> Zend_Auth<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;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="">'Login assertion failed'</span> <span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>These simple assertions <sup class='footnote'><a href='#fn-157-3' id='fnref-157-3'>3</a></sup> ensure that we&#8217;re logged in (or not logged in)</p>
<h4 id="toc-putting-it-all-together">Putting It All Together</h4>
<p>Putting it all together, we now have a base class which provides all of our test cases with the functionality we need.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="">'Zend/Test/PHPUnit/ControllerTestCase.php'</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> BaseControllerTest <span style="color: #000000; font-weight: bold;">extends</span> Zend_Test_PHPUnit_ControllerTestCase
<span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #0000ff; font-style: italic;">/**
     * Contains models which should be destroyed on tear down
     *
     * @var array
     */</span>
    protected <span style="color: #000088;">$_disposables</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
&nbsp;
	protected <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
	    parent<span style="color: #339933;">::</span><span style="color: #004000;">tearDown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_disposables <span style="color: #b1b100;">as</span> <span style="color: #000088;">$model</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;">$model</span> instanceof Doctrine_Record <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	            <span style="color: #000088;">$model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	        <span style="color: #009900;">&#125;</span>
	        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$model</span> <span style="color: #009900;">&#41;</span>;
	    <span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Sets a model as disposable, so teardown automatically deletes it
	 *
	 * @param Doctrine_record $model
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _setDisposable<span style="color: #009900;">&#40;</span> Doctrine_record <span style="color: #000088;">$model</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>_disposables<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$model</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Sets the current state as if there is a logged in user
	 *
	 * @param object $identity the idenity to use, otherwise one is generated
	 * @return void
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _doLogin<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$identity</span> <span style="color: #339933;">=</span> <span style="color: #000000; 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;">$identity</span> <span style="color: #339933;">===</span> <span style="color: #000000; font-weight: bold;">null</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	        <span style="color: #000088;">$identity</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_generateFakeIdentity<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	    <span style="color: #009900;">&#125;</span>
&nbsp;
	    Zend_Auth<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;">-&gt;</span><span style="color: #004000;">getStorage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$identity</span> <span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #0000ff; font-style: italic;">/**
	 * Generates a fake identity, usefull for simulating a logged in user
	 *
	 * @param boolean $unique
	 * @return StdClass an identity
	 */</span>
	protected <span style="color: #000000; font-weight: bold;">function</span> _generateFakeIdentity<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$unique</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$identity</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> stdClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
		<span style="color: #000088;">$account</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Account<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">username</span>     <span style="color: #339933;">=</span> <span style="">'AutoTest'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">emailAddress</span> <span style="color: #339933;">=</span> <span style="">'autotest'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="">'@example.org'</span>;
	        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span>     <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span> <span style="">'password'</span> <span style="color: #009900;">&#41;</span>;
	        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">confirmed</span>    <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
	        <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enabled</span>      <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
	        <span style="color: #000088;">$account</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setDisposable<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
	    	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</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: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$val</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	        	<span style="color: #000088;">$identity</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$val</span>;
	    	<span style="color: #009900;">&#125;</span>
	    	<span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$identity</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
	    	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$identity</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> assertNotLoggedIn<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;">assertFalse</span><span style="color: #009900;">&#40;</span> Zend_Auth<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;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="">'Login assertion failed'</span> <span style="color: #009900;">&#41;</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> assertLoggedIn<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;">assertTrue</span><span style="color: #009900;">&#40;</span> Zend_Auth<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;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="">'Login assertion failed'</span> <span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3 id="toc-writing-our-controller-test">Writing Our Controller Test</h3>
<p>Now that our groundwork has been laid, we can finally start writing our controller test.</p>
<p>Our first set of test cases cover the requirement <cite>&#8220;when a user registers, they must confirm their email address before they can access their account&#8221;</cite>.  To do this, we need to simulate a user posting their valid registration details to our controller, and verify that the account created is not set as confirmed.  We then need to test that submitting login information for a non-confirmed account to our login action does not result in an authenticated user.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testRegisterCreatesNewUnconfirmedAccount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$email</span> <span style="color: #339933;">=</span> <span style="">'autotest'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="">'@example.org'</span>;
    <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'emailAddress'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$email</span><span style="color: #339933;">,</span>
        <span style="">'password'</span>		  <span style="color: #339933;">=&gt;</span> <span style="">'testpassw0rd'</span><span style="color: #339933;">,</span>
        <span style="">'passwordconfirm'</span> <span style="color: #339933;">=&gt;</span> <span style="">'testpassw0rd'</span>
    <span style="color: #009900;">&#41;</span>;
&nbsp;
    <span style="color: #000088;">$_POST</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$data</span>;
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dispatch</span><span style="color: #009900;">&#40;</span> <span style="">'/account/register'</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #666666; font-style: italic;">//try to find the account record</span>
    <span style="color: #000088;">$table</span> <span style="color: #339933;">=</span> Doctrine_Table<span style="color: #339933;">::</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span> <span style="">'Account'</span> <span style="color: #009900;">&#41;</span> ;
    <span style="color: #000088;">$account</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$table</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findOneByEmailAddress</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$email</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setDisposable<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertNotNull</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertFalse</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">confirmed</span><span style="color: #339933;">,</span> <span style="">'Account was not marked as unconfirmed'</span> <span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * Asserts that a user that hasn't been confirmed cannot login
 *
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testUnconfirmedUserCannotLogin<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$email</span> <span style="color: #339933;">=</span> <span style="">'autotest'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="">'@example.org'</span>;
&nbsp;
    <span style="color: #000088;">$account</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Account<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">username</span>     <span style="color: #339933;">=</span> <span style="color: #000088;">$email</span>;
    <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span>     <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span> <span style="">'password'</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">emailAddress</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$email</span>;
    <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">confirmed</span>    <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span>;
    <span style="color: #000088;">$account</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enabled</span>      <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
    <span style="color: #000088;">$account</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>;
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setDisposable<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$account</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
    <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="">'username'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$email</span>;
    <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="">'password'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="">'password'</span>;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dispatch</span><span style="color: #009900;">&#40;</span> <span style="">'/account/login'</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertFalse</span><span style="color: #009900;">&#40;</span> Zend_Auth<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;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertNotRedirect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Our first test simply uses the $_POST global variable to simulate submitting our registration form with some test data.  After dispatch(), we use Doctrine_Table to find the model created by AccountController::registerAction(), then assert that the record was found and that it was not marked as confirmed.</p>
<p>The second test works by manually inserting a record that&#8217;s not confirmed, and making sure no user is authorized when attempting to login with that user&#8217;s account information.  As an added bonus, we also use <cite>assertNotRedirect()</cite> to make sure our controller didn&#8217;t redirect.  Our controller should only redirect if login was successful, otherwise it would be confusing to a user.</p>
<h3 id="toc-conclusion">Conclusion</h3>
<p>Automated testing of your controllers is relatively simple using the combined power of PHPUnit and Zend Framework&#8217;s Zend_Test component.  We can add additional functionality to allow our tests to simulate authentication, create fake identities, and even clean up our database after our tests have run.  I showed you how you can put this all together to test a registration and confirmation process in your controllers.</p>
<p>In part 2, I&#8217;ll cover more areas of testing in our AccountsController, including testing our actions that require an authorized user in order to access them.</p>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-157-1'>Of course, if tearDown() is never run for some reason the models won&#8217;t be deleted either, but we have more control over this.  A third way that isn&#8217;t discussed is creating an on_shutdown procedure, but that seems a little overkill <span class='footnotereverse'><a href='#fnref-157-1'>&#8617;</a></span></li>
<li id='fn-157-2'>I&#8217;m actually using ZendX_Doctrine_Auth_Adapter from the extras incubator <span class='footnotereverse'><a href='#fnref-157-2'>&#8617;</a></span></li>
<li id='fn-157-3'>Taknig this further, we should actually create new PHPUnit criteria instead of wrapping the assertTrue() criteria so that our failure message is different.  That&#8217;s something for later, though <span class='footnotereverse'><a href='#fnref-157-3'>&#8617;</a></span></li>
</ol>
</div>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/BTnsUdE4qqg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=157</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=157</feedburner:origLink></item>
		<item>
		<title>Quick Doctrine ORM Tip: Hydration Using Doctrine_Table</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/3U6IjYMBUgQ/</link>
		<comments>http://ajbrown.org/blog/?p=120#comments</comments>
		<pubDate>Wed, 31 Dec 2008 12:00:53 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Doctrine ORM]]></category>

		<category><![CDATA[Doctrine_Record]]></category>

		<category><![CDATA[Doctrine_Table]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=120</guid>
		<description><![CDATA[Did you know you can have what Propel calls "Peers" in Doctrine PHP?  A peer is basically an object which is responsible for hydrating (populating) a model.  From the documentation, you might think this can only be done using DQL, but you can actually use Doctrine_Table to do the work for you.]]></description>
			<content:encoded><![CDATA[<p>Did you know you can have what Propel calls &#8220;Peers&#8221; in <a href="">Doctrine ORM</a>?  A peer is basically an object which is responsible for hydrating (populating) a model.  From the documentation, you might think this can only be done using DQL, but you can actually use Doctrine_Table to do the work for you.</p>
<p>The first thing you must do is define the model you want to be hydratable.  I&#8217;ll use &#8220;Article&#8221; as my model.   This step is important because it gives Doctrine an object to hydrate when we perform operations against our Doctrine_Table object.  It also, of course, allows Doctrine to do alias translation and automatically detect relationships (I.E., so you don&#8217;t have to manually perform joins.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Article <span style="color: #000000; font-weight: bold;">extends</span> Doctrine_Record
<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> setTableDefinition<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span> <span style="">'title'</span><span style="color: #339933;">,</span> <span style="">'string'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span>
			<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'notblank'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#41;</span>;
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span> <span style="">'author'</span><span style="color: #339933;">,</span> <span style="">'string'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span>
			<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'notblank'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#41;</span>;
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span> <span style="">'body'</span><span style="color: #339933;">,</span> <span style="">'clob'</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span> <span style="">'published'</span><span style="color: #339933;">,</span> <span style="">'boolean'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">null</span><span style="color: #339933;">,</span>
			<span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'default'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#41;</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> setUp<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;">hasMany</span><span style="color: #009900;">&#40;</span> <span style="">'Comment'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
			<span style="">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="">'id'</span><span style="color: #339933;">,</span>
            		<span style="">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="">'article_id'</span><span style="color: #339933;">,</span>
		<span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><sup>*It&#8217;s good practice to make all of your models <cite>Timestampable</cite>, but I left that out of this example for simplicity</sup></p>
<p>Now that our models have been defined, lets move on to our Peer, the <cite>Doctrine_Table</cite>.  In it&#8217;s simplest form, our Peer only needs to extend Doctrine_Table.  In order to harness the power of Doctrine out of the box, we need to <strong>make sure the 3rd parameter of the Doctrine_Table constructor is set to &#8220;<em>true</em>&#8220;</strong>.  This allows Doctrine to bind our model (defined above) to the Table that this Doctrine_Table instance is representing.   Without it, we would have to manually bind the model.</p>
<p><strong>TIP:</strong>  Instead of doing this for every Peer, create a base class which does it for you.  I haven&#8217;t run into a case yet where I didn&#8217;t want to let Doctrine do it&#8217;s work for me.  As long as the models exist, it should work fine.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> ArticlePeer <span style="color: #000000; font-weight: bold;">extends</span> Doctrine_Table
<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> __construct<span style="color: #009900;">&#40;</span> Doctrine_Connection <span style="color: #000088;">$oDbCon</span> <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span>  <span style="">'Article'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$oDbCon</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Now that our peer is defined, we can save ourselves the trouble of writing any DQL.  Doctrine_Table makes available some magic functions, allowing you to do simple queries against any field defined in the model you&#8217;re peering.  For example, we can easily retrieve a collection of Articles by &#8220;A.J. Brown&#8221;:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$peer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArticlePeer<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$connection</span> <span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$articles</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$peer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findByAuthor</span><span style="color: #009900;">&#40;</span> <span style="">'A.J. Brown'</span> <span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>or all published articles: </p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$peer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArticlePeer<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$connection</span> <span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$articles</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$peer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findByPublished</span><span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>The advantage of this approach might not be obvious at first.  After all, you could just as easily instanciate a new Doctrine_Table, passing the correct parameters, right?</p>
<p>Most applications won&#8217;t use the simple findBy<field> methods made availble through the Doctrine_Table API.   We&#8217;ll typically need to do lookups that will require custom DQL to return the objects we need.  It&#8217;s a good practice to make these queries reusable, and place them at a lower level in your code.  In fact, If you follow the &#8220;Fat Model, Skinny Controller&#8221; philosophy,  you would never be writing DQL at any level of your application outside of the model / data access layer. </field></p>
<p>With that said, any query that hydrates Article models (or agregate data of Article models, such as counts and averages) should be performed within a method of our ArticlePeer: </p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> ArticlePeer <span style="color: #000000; font-weight: bold;">extends</span> Doctrine_Table
<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> __construct<span style="color: #009900;">&#40;</span> Doctrine_Connection <span style="color: #000088;">$oDbCon</span> <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span>  <span style="">'Article'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$oDbCon</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</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> findArticlesForReview<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createQuery</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="">'Article.pendingReview = true'</span> <span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">-&gt;</span><span style="color: #004000;">addWhere</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Article.status != 'draft' &quot;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderBy</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Article.title&quot;</span> <span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
			;  
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Now our user code doesn&#8217;t have to know the query needed for the data, it only needs to know what the method returns.  If your definition of an article pending review changes later, you won&#8217;t need to grep through all of your code for the related queries.</p>
<p><strong>TIP:</strong> An added benefit of placing your DQL queries inside Doctrine_Table objects is caching.  The ArticlePeer above makes a great place to implement <a href="http://ajbrown.org/blog/tags/memcached">Memcached caching</a>, since it would be completely transparent to the user.</p>
<p>Happy Doctrine&#8230;ing?</p>
<p>For more basic information on using Doctrine, check the <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/one-page#working-with-objects:fetching-data">Doctrine ORM Online Manual</a>.</p>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/3U6IjYMBUgQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=120</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=120</feedburner:origLink></item>
		<item>
		<title>New Doctrine Patch: BETWEEN relation alias parsing</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/bQWAsx2NhSA/</link>
		<comments>http://ajbrown.org/blog/?p=151#comments</comments>
		<pubDate>Tue, 30 Dec 2008 21:44:30 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Doctrine ORM]]></category>

		<category><![CDATA[Doctrine_Query]]></category>

		<category><![CDATA[Doctrine_Query_Where]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=151</guid>
		<description><![CDATA[Issue
BETWEEN clauses with relational alias operands do not parse, resulting in an exception &#8220;could not find short alias&#8221;.
Example
The following code will throw an exception.  User hasOne Subscription.

1
2
3
$q1 = Doctrine_Query::create&#40;&#41;
    -&#62;select&#40;'u.id'&#41; -&#62;from&#40;'User u'&#41; -&#62;where&#40;&#34;CURRENT_DATE() BETWEEN u.Subscription.begin AND u.Subscription.end&#34;&#41;
    -&#62;addWhere&#40; 'u.id != 5' &#41;;

Since the between operands are relational aliases, [...]]]></description>
			<content:encoded><![CDATA[<h4 id="toc-issue">Issue</h4>
<p>BETWEEN clauses with relational alias operands do not parse, resulting in an exception &#8220;could not find short alias&#8221;.</p>
<h4 id="toc-example">Example</h4>
<p>The following code will throw an exception.  User hasOne Subscription.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$q1</span> <span style="color: #339933;">=</span> Doctrine_Query<span style="color: #339933;">::</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span><span style="">'u.id'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="">'User u'</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;">&quot;CURRENT_DATE() BETWEEN u.Subscription.begin AND u.Subscription.end&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addWhere</span><span style="color: #009900;">&#40;</span> <span style="">'u.id != 5'</span> <span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>Since the between operands are relational aliases, and not literals or short aliases, Doctrine does not attempt to parse correctly.  I modified the behavior to do extra parsing on the expressions when BETWEEN is encountered as the operation.</p>
<h4 id="toc-the-goods">The Goods</h4>
<ul>
<li><a href="http://trac.doctrine-project.org/attachment/ticket/1792/fix-parse-between.diff">The Patch</a></li>
<li><a href="http://trac.doctrine-project.org/ticket/1792">The Ticket</a></li>
</ul>
<p>Guilherme from the team messaged me last night to let me know he&#8217;s going to commit the patch.  I just checked and it&#8217;s not there yet, so if you need this fix immediately, you can apply the patch above.</p>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/bQWAsx2NhSA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=151</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=151</feedburner:origLink></item>
		<item>
		<title>Four Reasons to Love CouchDB, Part 2</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/cZhaCUmEuXE/</link>
		<comments>http://ajbrown.org/blog/?p=109#comments</comments>
		<pubDate>Tue, 30 Dec 2008 11:09:08 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[CouchDB]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=109</guid>
		<description><![CDATA[In "Four Reasons to Love CouchDB, Part 1" I expressed how easy CouchDB is to implement and learn, despite being different than what you'd be used to using any of the many popular database platforms out there.  I even suggested that you don't even have to learn a server-side language to interact with it.  Now, lets move on to our next reason.]]></description>
			<content:encoded><![CDATA[<ul>Other articles in this series:</p>
<li><a href="http://ajbrown.org/blog/2008/12/28/four-reasons-to-love-couchdb-part-1.html">Part 1</a></li>
</ul>
<p>In &#8220;<a href="http://ajbrown.org/blog/2008/12/28/four-reasons-to-love-couchdb-part-1.html">Four Reasons to Love CouchDB, Part 1</a>&#8221; I expressed how easy CouchDB is to implement and learn, despite being different than what you&#8217;d be used to using any of the many popular database platforms out there.  I even suggested that you don&#8217;t even have to learn a server-side language to interact with it.  Now, lets move on to our next reason:</p>
<p></p>
<h3 id="toc-reason-2-its-not-a-rdbms">Reason #2: It&#8217;s not a RDBMS</h3>
<p></p>
<p>Relational database persist data in a very complex manner.  One of my professors a while ago (do they call them that at Community College?) used an analogy of a garage to show why they don&#8217;t always make sense.  &#8220;If your garage was a RDBMS, and you wanted to store your car in it, you would remove the engine, wheels, steering wheel, gas tank, etc and insert them individually in a neat manner.  When you wanted your car back, you&#8217;d select all of the parts and reassemble them.&#8221;  This works well if you ever want to quickly find the serial number and displacement of your engine,   or want to share tires with another car, but doesn&#8217;t work well when you (more commonly) just want to drive your car.  Lets not forget to mention the schema changes that would need to be made if you brought home a motorcycle! </p>
<p>
<blockquote>CouchDB is a Document-Oriented Database</p></blockquote>
<p> In MySQL, we&#8217;re often taught to normalize data to increase performance and reduce data duplication.  This results in lots of &#8220;JOIN category ON category.id = article.id, JOIN author ON author.id = article.id&#8221; just to fetch all of the useful information for a single object.  CouchDB is a Document-oriented database &#8212;  All data for a specific object is self-contained, within the same document.  This results in data being persisted in the same way that we think of it, with sacrifice for data duplication.</p>
<p>But that doesn&#8217;t mean that ALL data is duplicated of course.  We can still retain the concept of &#8220;foreign keys&#8221;, but we use them minimally.  The idea is to be <em>semi</em>structured.</p>
<h4 id="toc-a-real-world-example">A real world example.</h4>
<p>We want to store articles, each with an article and collection of comments.  We want to be able to show an article on a page, along with it&#8217;s comments.  We also want to be able to get all comments across all posts for a &#8220;latest comments&#8221; page.</p>
<p>In MySQL, we would normally normalize all of this data into separate tables, and create foreign key references.  There would be a single table for <cite>authors</cite>, a table for <cite>articles</cite>, and a table for <cite>comments</cite>.  With this complex schema, we&#8217;d end up with queries such as the following</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> articles <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> author <span style="color: #993333; font-weight: bold;">ON</span> author<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> article<span style="color: #66cc66;">.</span>author_id <span style="color: #993333; font-weight: bold;">WHERE</span> article<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> $articleId</pre></td></tr></table></div>

<p>To show the article information, and then a second query to show all comments for that article: </p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> comments <span style="color: #993333; font-weight: bold;">WHERE</span> article_id <span style="color: #66cc66;">=</span> $articleId</pre></td></tr></table></div>

<p>In CouchDB, we can easily store all of this data within the same document, without hindering out ability to query it.  Although schema-less, CouchDB does have the concept of &#8220;views&#8221;, which are similar to the concept of Views in RDBMS.  Views are functions stored within special documents called &#8220;design documents&#8221;.  They contain a field named &#8220;views&#8221; which is an array of  JavaScript (the default language) functions used to filter (map) and sort (key) document data, and to generate aggregate results (reduce). </p>
<p>The following document represents all of the data we stored in our MySQL schema above, except that it&#8217;s all stored within one object.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;id&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;article_id_2&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;type&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;article&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;title&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Some Title&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;author&quot;</span> <span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #3366CC;">&quot;name&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;A.J. Brown&quot;</span><span style="color: #339933;">,</span> 
          <span style="color: #3366CC;">&quot;email&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;nospam@ajbrown.org&quot;</span> 
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    . . . 
    <span style="color: #3366CC;">&quot;comments&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
        <span style="color: #009900;">&#123;</span> 
            <span style="color: #3366CC;">&quot;name&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;John Smith&quot;</span><span style="color: #339933;">,</span> 
            <span style="color: #3366CC;">&quot;text&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;A.J. Brown is the best, ever&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;created&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2008-12-21 01:23:24 AM&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#123;</span> 
            <span style="color: #3366CC;">&quot;name&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Jane Applebees&quot;</span><span style="color: #339933;">,</span> 
            <span style="color: #3366CC;">&quot;text&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;I totally agree with John&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;created&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2008-12-21 02:55:24 AM&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#93;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Although everything is stored within the structure of a single document, We can still get all of the data we need easily. We just need a view that will key our documents on the article id:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> map <span style="color: #009900;">&#40;</span> doc <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> doc.<span style="color: #660066;">type</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'article'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          emit<span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> doc <span style="color: #009900;">&#41;</span>; 
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This function says <em>&#8220;Show me all documents with a field named &#8220;type&#8221; that has a value of &#8220;article&#8221;, and sort and collate (key) them by their document id&#8221;</em>.  Now we can call the view and get all articles and their comments. By adding &#8220;?key=<document_id>&#8221; to the URL for our view, we can retrieve only 1 post. </document_id></p>
<p>To retrieve only all comments of all posts, we&#8217;ll need to create a second view.  This view will extract the comments from every document has a type=article, and collate them by them by the comment&#8217;s created field.</p>
<p></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> map <span style="color: #009900;">&#40;</span> doc <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> doc.<span style="color: #660066;">comments</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		emit<span style="color: #009900;">&#40;</span>doc.<span style="color: #660066;">comments</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">created</span><span style="color: #339933;">,</span> doc.<span style="color: #660066;">comments</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>
</p>
<p>Our resultset would look something like this: (note, view result sets have key and id information.  I&#8217;ve left those out for simplicity sake): </p>
<p></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="javascript javascript" style="font-family:monospace;">        <span style="color: #009900;">&#123;</span> 
            <span style="color: #3366CC;">&quot;name&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;John Smith&quot;</span><span style="color: #339933;">,</span> 
            <span style="color: #3366CC;">&quot;text&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;A.J. Brown is the best, ever&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;created&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2008-12-21 01:23:24 AM&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#123;</span> 
            <span style="color: #3366CC;">&quot;name&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Jane Applebees&quot;</span><span style="color: #339933;">,</span> 
            <span style="color: #3366CC;">&quot;text&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;I totally agree with John&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;created&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2008-12-21 02:55:24 AM&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<p></p>
<p>Since we keyed our view on the comments created field,we can easily narrow our results by date by specifying a <cite>startKey</cite> and an <cite>endKey</cite> in our request URI:</p>
<p><cite>http://couchserver/database/_view/articles/comments?startkey=["2008-12-21 02:00:00 AM"]</cite></p>
<p>This would only return &#8220;Jane Applebee&#8217;s&#8221; comment, since the specified start key come sequentially after the rest of the results.</p>
<p>
<blockquote>Handling the custom fields is simple with CouchDB</p></blockquote>
<h4 id="toc-conclusion">Conclusion</h4>
<p>Storing data this way makes a lot of sense in a lot of cases.  For example, my newest project needs to be able to store system events.  Every event has (and enforces) a standard set of fields, but there may be additional custom (unpredictable) fields as well, as defined by whatever process sends the event.  Those custom fields must be available for querying by any program that does know of them.  Handling the custom fields is simple with CouchDB &#8212; I just add them to the document being stored.  A relational database schema for this data model would be complex and hard to follow.</p>
<p>RDMS&#8217;s are powerful, but sometimes they&#8217;re overkill for our applications.  I&#8217;ve seen some hypothesis suggesting that CouchDB&#8217;s document oriented strategy would work for  90% of web applications today.  Who knows how accurate that is, but it definitely makes you think.  After all, you can&#8217;t get any more cutting edge than a database engine asking us to rethink how we model data which is written in a language that asks us to rethink parallel processing.</p>
<p>Check back tomorrow for Reason #3</p>
<p>Special thanks to the following blogs for helping me get started with CouchDb:</p>
<ul>
<li><a href="http://www.cmlenz.net/">about:cmlenz</a></li>
<li><a href="http://horicky.blogspot.com/2008/10/couchdb-implementation.html">Ricky Ho</a></li>
<li><a href="http://barkingiguana.com/2008/06/28/installing-couchdb-080-on-ubuntu-804">Barking Ignuana</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/cZhaCUmEuXE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=109</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=109</feedburner:origLink></item>
		<item>
		<title>Four Reasons to Love CouchDB, Part 1</title>
		<link>http://feedproxy.google.com/~r/ajbrowns_blog/~3/SZAllWoDTck/</link>
		<comments>http://ajbrown.org/blog/?p=114#comments</comments>
		<pubDate>Mon, 29 Dec 2008 06:14:22 +0000</pubDate>
		<dc:creator>A.J. Brown</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[CouchDB]]></category>

		<guid isPermaLink="false">http://ajbrown.org/blog/?p=114</guid>
		<description><![CDATA[This is a multi-part series on why you should consider CouchDB for your next project.  CouchDB is a distributed, fault-tolerant and schema-free document-oriented database accessible via a RESTful HTTP/JSON API.  It redefines the typical relational database storage schema by using a schema-less Document oriented storage strategy, better fitting for most web applications.]]></description>
			<content:encoded><![CDATA[<ul>Other articles in this series:</p>
<li><a href="http://ajbrown.org/blog/2008/12/30/four-reasons-to-love-couchdb-part-2.html">Part 2</a></li>
</ul>
<p>I&#8217;ve been sensing a lot of hype around <a href="http://couchdb.apache.org">CouchDB</a> lately, and I recently decided to give it a try.  After about ~30 hours of working with it, and a successful prototype of a project driven by CouchDB (and special shout-out to <a href="http://ajbrown.org/blog/topics/php/zend-framework">Zend Framework</a> and <a href="http://weierophinney.net/phly/">Phly</a>),  I think I may have found a favorite new toy to share it with you.</p>
<p>This will be a multi-part series with each article touching on a single aspect of CouchDB.  I enjoy MySQL and PostgreSQL as well, so I hope these posts aren&#8217;t taken as a knock on them, but more of a thumbs up to CouchDB. </p>
<h4 id="toc-what-is-couchdb">What is CouchDB</h4>
<p>Taken straight from their website, &#8220;Apache CouchDB is a distributed, fault-tolerant and schema-free document-oriented database accessible via a RESTful HTTP/JSON API.&#8221;  It&#8217;s designed to drive today&#8217;s rich internet applications with scalability and even offline-operation in mind.  If you&#8217;re interested in reading technical inforamtion about CouchDB, check out:</p>
<ul>
<li><a href="http://couchdb.apache.org/index.html">Apache CouchDb&#8217;s Website</a></li>
<li><a href="http://books.couchdb.org/relax/why-couchdb">Why CouchDB?</a></li>
<li><a href="http://damienkatz.net/">Damien Katz, Creator and Project Lead</a></li>
</ul>
<p></p>
<h3 id="toc-reason-1-its-easy-to-learn">Reason #1:  It&#8217;s Easy To Learn</h3>
<p></p>
<p>My first experience with databases was Microsoft Access.  I remember writing a Maxis fan site in ASP using an Access database which I manually updated every so often to store all of my content.  I was able to leverage the &#8220;power&#8221; of Access (note: I was 13 or so at the time.), but it took a bit for me to really comprehend the features, and how my data should best be stored.</p>
<p>Fast forward to now.  Companies are paying database administrators pretty good salaries for their database engineering skills.  Even companies with rather simple data-structures need an experienced and talented database developer to keep their data schema scalable.  It&#8217;s becoming a very specialized skill, such as the multi-hat of &#8220;Webmaster&#8221; has nearly vanished and split into &#8220;Graphics Designer&#8221;, &#8220;Web Programmer&#8221;, and &#8220;Systems Administrator&#8221; (in the simplest of cases).  Writing queries can be the simplest thing you&#8217;ve ever done, or can cause you to pull out your hair, depending on the data needed.  Lets not get into replication and clustering.</p>
<p>
<blockquote>Database systems aren&#8217;t simple bread baskets.</p></blockquote>
<p>CouchDB is very easy to learn.  That&#8217;s actually a two-part reason, depending on your expertise.  If you&#8217;re a developer or database expert, It&#8217;s not that MySQL or PostgreSQL are hard to learn, but rather that CouchDB is easy to pick up and run with despite being philosophically different.  Thinking outside of the box of relational data that has been etched into my brain for the past 8 years was tough at first, but within a few hours of reading examples and playing around with it, I was able to start harnessing the full feature-suite.</p>
<p>
<blockquote>Who needs a server-side language, anyway?</p></blockquote>
<p>If you&#8217;re a front-end developer who&#8217;s never worked with a programming language other than JavaScript or Flex, there&#8217;s no SQL or complex protocol to learn.  In fact, you don&#8217;t need any application layer whatsoever to start playing around with it:  CouchDB operates completely over HTTP.  It cuts out the &#8220;middle man&#8221; by serving data in JSON.  Hell, the administration tools is completely AJAX based.  Creating databases and views, querying data, and modifying data is done all through a RESTful interface.  Imagine a world where Flex developers don&#8217;t even have to talk to PHP developers <img src='http://ajbrown.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I encourage you to start playing around with CouchDB.  Keep in mind that CouchDB is still in an incubation phase, so it hasn&#8217;t even met its full potential yet.  This project is very exciting to me, and I will continue to watch it&#8217;s progress.</p>
<img src="http://feeds.feedburner.com/~r/ajbrowns_blog/~4/SZAllWoDTck" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ajbrown.org/blog/?feed=rss2&amp;p=114</wfw:commentRss>
		<feedburner:origLink>http://ajbrown.org/blog/?p=114</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 2.103 seconds --><!-- Cached page generated by WP-Super-Cache on 2009-09-28 16:30:01 --><!-- Compression = gzip -->
