<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jeremykendall.net</title>
	<atom:link href="http://www.jeremykendall.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeremykendall.net</link>
	<description>{web developer, entrepreneur }</description>
	<lastBuildDate>Fri, 15 Jan 2010 12:39:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>DIY Network Monitoring and Logging with Perl</title>
		<link>http://www.jeremykendall.net/2009/10/27/network-monitoring-and-logging-with-perl/</link>
		<comments>http://www.jeremykendall.net/2009/10/27/network-monitoring-and-logging-with-perl/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 04:12:17 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[att]]></category>
		<category><![CDATA[dsl]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=223</guid>
		<description><![CDATA[The Problem
I&#8217;ve been having trouble with my AT&#038;T DSL installation here at the new place.  My internet connection will come and go, seemingly at random, and for random amounts of time.  I tweeted about it once already, hoping that sharing my frustration with the world might make me feel a little better.  [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The Problem</strong></p>
<p>I&#8217;ve been having trouble with my AT&#038;T DSL installation here at the new place.  My internet connection will come and go, seemingly at random, and for random amounts of time.  I <a href="http://twitter.com/JeremyKendall/status/5193232511">tweeted about it</a> once already, hoping that sharing my frustration with the world might make me feel a little better.  Nope.  Didn&#8217;t work.</p>
<p>I&#8217;ve had this problem before with AT&#038;T, when I got DSL installed at my last place.  Things were rough for a while, and then somehow they seemed to straighten out on their own.  I&#8217;m not crossing my fingers that I&#8217;ll have such luck again.</p>
<p><strong>What&#8217;s Really Going On?</strong></p>
<p>I decided to try and log the bounces so that I could get a better feel for what was going on.  I couldn&#8217;t find exactly what I wanted online (and I couldn&#8217;t always get online), so I whipped up a <a href="http://en.wikipedia.org/wiki/Perl">Perl</a> script to keep an eye on my connection for me.</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Test AT&amp;T DSL connectivity. If network is down, log to file</span>
<span style="color: #666666; font-style: italic;"># Will use log info as ammo when I call tech support.</span>
<span style="color: #666666; font-style: italic;">#</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> warnings<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> strict<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Log<span style="color: #339933;">::</span><span style="color: #006600;">Handler</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Net<span style="color: #339933;">::</span><span style="color: #006600;">Ping</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Sys<span style="color: #339933;">::</span><span style="color: #006600;">HostIP</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$log</span> <span style="color: #339933;">=</span> Log<span style="color: #339933;">::</span><span style="color: #006600;">Handler</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">new</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #0000ff;">$log</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">add</span><span style="color: #009900;">&#40;</span>
    file <span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#123;</span>
        filename <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;/var/log/testNetwork.log&quot;</span><span style="color: #339933;">,</span>
        mode     <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;append&quot;</span><span style="color: #339933;">,</span>
        maxlevel <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;info&quot;</span><span style="color: #339933;">,</span>
        minlevel <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;warning&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$ipAddress</span>          <span style="color: #339933;">=</span> Sys<span style="color: #339933;">::</span><span style="color: #006600;">HostIP</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">ip</span><span style="color: #339933;">;</span> 
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$matchHomeNetworkIp</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$ipAddress</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^192\.168\.10\.\d{1,3}$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$matchHomeNetworkIp</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #0000ff;">$log</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">debug</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Current IP $ipAddress does not appear to be on your home network. Exiting&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$router</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;192.168.10.1&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$modem</span>  <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;192.168.1.254&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$host</span>   <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;www.yahoo.com&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$p</span> <span style="color: #339933;">=</span> Net<span style="color: #339933;">::</span><span style="color: #006600;">Ping</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">new</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;icmp&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">ping</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$router</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #0000ff;">$log</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">warning</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Router $router is unreachable. Exiting.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">ping</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$modem</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #0000ff;">$log</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">warning</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Modem $modem is unreachable. Exiting.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">ping</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$host</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #0000ff;">$log</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">info</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;$host is reachable&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #0000ff;">$log</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">warning</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;$host is NOT reachable&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Code Review</strong></p>
<p>While the code is simple, there are a couple of things to note.  First, you&#8217;ll notice I&#8217;ve baked my router&#8217;s IP range into a <a href="http://en.wikipedia.org/wiki/Regular_expressions">regex</a> that will tell me if I can even get that far.  If not, there&#8217;s no point in checking anything else, so I exit.</p>
<p>Next I fire up <a href="http://search.cpan.org/~smpeters/Net-Ping-2.36/lib/Net/Ping.pm">Net::Ping</a>.  While there are six different options for Net::Ping->new(), the only one that worked for me was icmp.  Icmp requires root privileges to run, so keep that in mind. </p>
<p>Next I <a href="http://en.wikipedia.org/wiki/Ping">ping</a> important parts of the home network.  I want to be sure that my wireless router and the DSL modem are both online before I try and ping an external site.</p>
<p>If everything looks good on the inside, I&#8217;ll ping an external site and see if I get anything back.  You&#8217;ll notice that I&#8217;ve added a second parameter to ping this time.  That&#8217;s the number of seconds I&#8217;ll wait for a response before failing (of course, it is possible that Yahoo! won&#8217;t respond to a ping request here and there, making it appear as if the network is down, but I&#8217;m not so worried about a false positive or two).</p>
<p><strong>Implementation</strong></p>
<p>Now that I&#8217;ve got this nifty script to tell me about the health of my network, I need a way to run it on a regular basis.  It&#8217;s important to run it as root because of the icmp ping.  <a href="http://en.wikipedia.org/wiki/Cron">Cron</a> was the obvious solution, as it&#8217;s purpose is to run commands on a predetermined schedule. As long as I add the script to root&#8217;s cron file, it&#8217;ll run with root permissions.  Sweet!</p>
<p>Adding my script to the root cron file was as easy as issuing</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">sudo crontab -e</pre></div></div>

<p> and adding the following line:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">*/1 * * * * perl /home/jkendall/dev/perl/util/testNetwork.pl</pre></div></div>

<p>With my cron file in place, my script fires off every minute.  As long as I&#8217;m on my home network, I&#8217;ll get a log entry telling me whether or not the network is up.</p>
<p><strong>Keeping an Eye on the Results</strong></p>
<p>Now that my script is actually doing something, I need to be able to parse the results.  A quick</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">tail -f /var/log/testNetwork.log</pre></div></div>

<p> allows me to keep track of the results as they come in.  I&#8217;m also using grep to pull all of the &#8220;NOT reachable&#8221; lines out of the log file with</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">grep -n --color &quot;NOT reachable&quot; /var/log/testNetwork.log</pre></div></div>

<p>  I could always just open the log file and read through it from top to bottom, but what fun is that?  A decent tool to parse the fail log is going to be necessary, but I haven&#8217;t whipped it up yet. </p>
<p><strong>Teh Suck</strong></p>
<p>As I&#8217;ve been writing this blog post, I&#8217;ve been running this script in the background.  Here are the results of an hour or so of logging (all times are CDT):</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">Oct 27 21:03:33 [INFO] www.yahoo.com is reachable
Oct 27 21:04:03 [WARNING] Router 192.168.10.1 is unreachable. Exiting.
Oct 27 21:05:02 [INFO] www.yahoo.com is reachable
Oct 27 21:06:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:07:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:08:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:09:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:10:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:11:02 [INFO] www.yahoo.com is reachable
Oct 27 21:12:01 [INFO] www.yahoo.com is reachable
Oct 27 21:13:01 [INFO] www.yahoo.com is reachable
Oct 27 21:14:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:15:32 [INFO] www.yahoo.com is reachable
Oct 27 21:16:01 [INFO] www.yahoo.com is reachable
Oct 27 21:17:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:18:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:19:11 [INFO] www.yahoo.com is reachable
Oct 27 21:20:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:21:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:22:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:23:03 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:24:01 [INFO] www.yahoo.com is reachable
Oct 27 21:25:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:26:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:27:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:28:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:29:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:30:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:31:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:32:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:33:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:34:21 [INFO] www.yahoo.com is reachable
Oct 27 21:35:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:36:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:37:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:38:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:39:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:40:12 [INFO] www.yahoo.com is reachable
Oct 27 21:41:01 [INFO] www.yahoo.com is reachable
Oct 27 21:42:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:43:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:44:31 [INFO] www.yahoo.com is reachable
Oct 27 21:45:01 [INFO] www.yahoo.com is reachable
Oct 27 21:46:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:47:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:48:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:49:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:50:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:51:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:52:42 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:53:41 [WARNING] www.yahoo.com is NOT reachable
Oct 27 21:54:01 [INFO] www.yahoo.com is reachable</pre></div></div>

<p>Weak sauce, man.  Weak sauce.</p>
<p><strong>Wrapping Up</strong></p>
<p>Having this script handy doesn&#8217;t make the <a href="http://failblog.org/">fail</a> any better, but at least I know a little more about what&#8217;s happening.  I&#8217;d like to think it&#8217;ll give me some leverage when I try to get this worked out with AT&#038;T, but who knows.  I&#8217;ll let you know how it goes.</p>
<p>[<strong>Update</strong>: post title change to better reflect content]</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F10%2F27%2Fnetwork-monitoring-and-logging-with-perl%2F&amp;linkname=DIY%20Network%20Monitoring%20and%20Logging%20with%20Perl"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/10/27/network-monitoring-and-logging-with-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZF-7984 &#8211; Zend_Tool Exits with Fatal Errors after installing PHPUnit 3.4.0+</title>
		<link>http://www.jeremykendall.net/2009/10/21/zf-7984-zend_tool-exits-with-fatal-errors-after-installing-phpunit-3-4-0/</link>
		<comments>http://www.jeremykendall.net/2009/10/21/zf-7984-zend_tool-exits-with-fatal-errors-after-installing-phpunit-3-4-0/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 15:28:14 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=197</guid>
		<description><![CDATA[I&#8217;m lucky enough to have made it to ZendCon again this year, and I&#8217;m having a blast learning new stuff, hanging out with old friends, making new friends, and generally grabbing up as much schwag as possible.
One of the topics that I&#8217;m most interested in is unit testing, specifically unit testing Zend Framework MVC apps.  [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m lucky enough to have made it to <a href="http://zendcon.com/">ZendCon</a> again this year, and I&#8217;m having a blast learning new stuff, hanging out with old friends, making new friends, and generally grabbing up as much schwag as possible.</p>
<p>One of the topics that I&#8217;m most interested in is unit testing, specifically unit testing <a href="http://framework.zend.com/">Zend Framework</a> MVC apps.  While there&#8217;s a lot I have yet to learn on that topic, I ran into a bug last night that I wanted to let you know about.</p>
<p>In preparation to dig into ZF unit testing, I updated my install of <a href="http://www.phpunit.de/">PHPUnit</a> to the latest version (currently 3.4.1, installed via <a href="http://pear.php.net/">PEAR</a>).  When I tried to create a new ZF project using <a href="http://framework.zend.com/manual/en/zend.application.quick-start.html#zend.application.quick-start.zend-tool">Zend_Tool</a>, I received the following error:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">jkendall@san-diego:~/dev/www$ zf create project asplode
&nbsp;
Fatal error: Cannot redeclare class phpunit_framework_testsuite_dataprovider in /usr/share/php/PHPUnit/Framework/TestSuite/DataProvider.php on line 64
&nbsp;
Call Stack:
    0.0020     111440   1. {main}() /usr/share/phplib/ZendFramework-1.9.3PL1/bin/zf.php:0
    0.0020     111560   2. zf_main() /usr/share/phplib/ZendFramework-1.9.3PL1/bin/zf.php:23
    0.0220     686832   3. zf_run($zfConfig = array ('HOME' =&gt; '/home/jkendall')) /usr/share/phplib/ZendFramework-1.9.3PL1/bin/zf.php:36
    0.0221     686952   4. Zend_Tool_Framework_Client_Console::main($options = array ()) /usr/share/phplib/ZendFramework-1.9.3PL1/bin/zf.php:214
    0.0221     687440   5. Zend_Tool_Framework_Client_Abstract-&gt;dispatch() /usr/share/phplib/ZendFramework-1.9.3PL1/library/Zend/Tool/Framework/Client/Console.php:96
    0.0222     687560   6. Zend_Tool_Framework_Client_Abstract-&gt;initialize() /usr/share/phplib/ZendFramework-1.9.3PL1/library/Zend/Tool/Framework/Client/Abstract.php:209
    0.0296     866600   7. Zend_Tool_Framework_Loader_Abstract-&gt;load() /usr/share/phplib/ZendFramework-1.9.3PL1/library/Zend/Tool/Framework/Client/Abstract.php:118
    0.4100    2729736   8. include_once('/usr/share/php/PHPUnit/Framework/TestSuite/DataProvider.php') /usr/share/phplib/ZendFramework-1.9.3PL1/library/Zend/Tool/Framework/Loader/Abstract.php:90
&nbsp;
jkendall@san-diego:~/dev/www$</pre></div></div>

<p>As it turns out, this is a known bug in version 1.9.0+ of the Zend Framework.  See <a href="http://framework.zend.com/issues/browse/ZF-7894">ZF-7894</a> in the ZF issue tracker for full details.  While this issue is not yet resolved in the tracker, <a href="http://raphaelstolt.blogspot.com/">Raphael Stolt</a> has <a href="http://framework.zend.com/issues/browse/ZF-7894?focusedCommentId=34826&amp;page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_34826">provided a workaround</a> in the form of a diff file attached to the issue.  While your mileage may vary, the patch worked perfectly for me.  I&#8217;m able to go ahead and dive into unit testing my Zend Framework applications.</p>
<p><strong>UPDATE</strong>: <a href="http://framework.zend.com/issues/browse/ZF-7894">ZF-7894</a> was resolved during Bug Hunt days this week.  Many thanks to Benjamin Eberlei!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F10%2F21%2Fzf-7984-zend_tool-exits-with-fatal-errors-after-installing-phpunit-3-4-0%2F&amp;linkname=ZF-7984%20%26%238211%3B%20Zend_Tool%20Exits%20with%20Fatal%20Errors%20after%20installing%20PHPUnit%203.4.0%2B"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/10/21/zf-7984-zend_tool-exits-with-fatal-errors-after-installing-phpunit-3-4-0/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Help Fight Cancer by Supporting Linda Rambin&#8217;s Art</title>
		<link>http://www.jeremykendall.net/2009/02/23/help-fight-cancer-by-supporting-linda-rambins-art/</link>
		<comments>http://www.jeremykendall.net/2009/02/23/help-fight-cancer-by-supporting-linda-rambins-art/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 13:50:28 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[cancer]]></category>
		<category><![CDATA[etsy]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=188</guid>
		<description><![CDATA[A Louisiana artist, Linda Rambin has been painting for approximately six years. Unfortunately, her painting career has been postponed indefinitely due to the extremely aggressive form of brain cancer she is currently fighting, glioblastoma multiforme. Diagnosed in early October 2008, Linda has had brain surgery, chemotherapy and radiation, and she is currently participating in a [...]]]></description>
			<content:encoded><![CDATA[<p>A Louisiana artist, Linda Rambin has been painting for approximately six years. Unfortunately, her painting career has been postponed indefinitely due to the extremely aggressive form of brain cancer she is currently fighting, <a href="http://en.wikipedia.org/wiki/Glioblastoma_multiforme">glioblastoma multiforme</a>. Diagnosed in early October 2008, Linda has had brain surgery, chemotherapy and radiation, and she is currently participating in a clinical trial that is causing her a great deal of fatigue and a host of other side effects.</p>
<p>The cost of Linda&#8217;s treatment and care are exorbitant.  Just one of the medications for the clinical trial costs $4,500 per month, and that&#8217;s the co-pay!  You can help support Linda and the Rambin family by spreading the word about <a href="http://lindarambin.etsy.com">Paintings by Linda</a>, a collection of Linda&#8217;s original paintings on <a href="http://www.etsy.com">Etsy.com</a>.  The more people that visit <a href="http://lindarambin.etsy.com">Paintings by Linda</a>, the more of her paintings will sell, helping the family to defray the cost of her treatment. (If you&#8217;re sharing about Linda&#8217;s store on <a href="http://www.twitter.com">Twitter</a>, please use the hashtag <a href="http://search.twitter.com/search?q=%23charlysmom">#charlysmom</a>. Linda&#8217;s daughter <a href="http://twitter.com/CharlyRambin">Charly</a> has worked tirelessly on both Linda&#8217;s Etsy store and Linda&#8217;s Caring Bridge website.)</p>
<p>If you are interested in learning more about her story, please visit <a href="http://www.caringbridge.org/visit/lindarambin">Linda&#8217;s Caring Bridge website.</a> There you will find a more detailed account of her struggle, a daily blog, a guestbook for comments, and a photos page.</p>
<p>Please keep Linda in your thoughts as you enjoy her unique and vivid paintings. They have brought her much joy, and we hope they will do the same for you.</p>
<table style="text-align: center;">
<tr>
<td><object type="application/x-shockwave-flash" data="http://www.etsy.com/flash/spots/etsy_mini.swf?user_id=6963380&#038;user_name=lindarambin&#038;item_source=shop&#038;item_size=gallery&#038;rows=3&#038;columns=3" width="538" height="546"><param name="movie" value="http://www.etsy.com/flash/spots/etsy_mini.swf?user_id=6963380&#038;user_name=lindarambin&#038;item_source=shop&#038;item_size=gallery&#038;rows=3&#038;columns=3" /></object></td>
</tr>
<tr>
<td><a style="color:#D35701; font-size: 14px; text-decoration: none; font-family:Arial, Helvetica, sans-serif; font-weight:bold" href="http://www.etsy.com">Etsy: Your place to buy &amp; sell all things handmade</a><br/><a style="font-family:Arial, Helvetica, sans-serif; font-size:12px; color:#0192B5; text-decoration: none;" href="http://lindarambin.etsy.com">lindarambin.etsy.com</a></td>
</tr>
</table>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F02%2F23%2Fhelp-fight-cancer-by-supporting-linda-rambins-art%2F&amp;linkname=Help%20Fight%20Cancer%20by%20Supporting%20Linda%20Rambin%26%238217%3Bs%20Art"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/02/23/help-fight-cancer-by-supporting-linda-rambins-art/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Allow Myself to Introduce . . . Myself</title>
		<link>http://www.jeremykendall.net/2009/02/17/allow-myself-to-introduce-myself/</link>
		<comments>http://www.jeremykendall.net/2009/02/17/allow-myself-to-introduce-myself/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 16:16:06 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=186</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><!-- Smart Youtube --><span class="youtube"><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/AOvkcIhzGvI&amp;rel=1&amp;color1=d6d6d6&amp;color2=f0f0f0&amp;border=&amp;fs=1&amp;hl=en&amp;autoplay=&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0" /><param name="allowFullScreen" value="true" /><embed wmode="transparent" src="http://www.youtube.com/v/AOvkcIhzGvI&amp;rel=1&amp;color1=d6d6d6&amp;color2=f0f0f0&amp;border=&amp;fs=1&amp;hl=en&amp;autoplay=&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="355" ></embed><param name="wmode" value="transparent" /></object></span></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F02%2F17%2Fallow-myself-to-introduce-myself%2F&amp;linkname=Allow%20Myself%20to%20Introduce%20.%20.%20.%20Myself"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/02/17/allow-myself-to-introduce-myself/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Win a Case of Blu Frog Energy Drink</title>
		<link>http://www.jeremykendall.net/2009/02/04/win-a-case-of-blu-frog-energy-drink/</link>
		<comments>http://www.jeremykendall.net/2009/02/04/win-a-case-of-blu-frog-energy-drink/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 12:29:30 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blu Frog]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=182</guid>
		<description><![CDATA[[This contest has ended and the winner has been announced. Perhaps you should subscribe to the Gimme Blu Frog! RSS feed so you won't miss any future contest announcements! Visit Gimme Blu Frog! to learn more about Blu Frog.]
Blu Frog Energy Drink, the newest, best tasting energy drink on the market, packed with tons of [...]]]></description>
			<content:encoded><![CDATA[<p>[This contest has ended and the <a href="http://gimmeblufrog.com/2009/02/14/blu-frog-energy-giveaway-winner-announced/">winner has been announced</a>. Perhaps you should subscribe to the Gimme Blu Frog! <a href="http://gimmeblufrog.com/feed/">RSS feed</a> so you won't miss any future contest announcements! Visit Gimme Blu Frog! to learn more about <a href="http://gimmeblufrog.com">Blu Frog</a>.]</p>
<p><a href="http://gimmeblufrog.com">Blu Frog Energy Drink</a>, the newest, best tasting energy drink on the market, packed with tons of natural energy and natural goodness, is taking the nation by storm!  Here&#8217;s your chance to <strong>win a free case of Blu Frog!</strong></p>
<p><strong>Here&#8217;s what you do</strong>: head over to <a href="http://boatinginbeautifulbritishcolumbia.com/">Beautiful British Columbia</a>, blog of the lovely and talented <a href="http://www.twitter.com/heatherinBC">Heather in BC</a>, and read her post &#8220;<a href="http://boatinginbeautifulbritishcolumbia.com/2009/02/03/win-blu-frog-on-valentines-day/">Win Blu Frog on Valentine&#8217;s Day</a>.&#8221;  Follow her directions to the letter (there are two ways to enter!).  Keep a sharp eye on <a href="http://boatinginbeautifulbritishcolumbia.com/">Beautiful British Columbia</a> the to see if you win (make it easy on yourself by subscribing to her <a href="http://boatinginbeautifulbritishcolumbia.com/feed/">RSS feed</a>)!</p>
<p>Once you&#8217;ve read the directions, here are a couple of Gimme Blu Frog! posts you might want to pay special attention to:</p>
<ul>
<li><a href="http://gimmeblufrog.com/2009/01/27/tell-me-what-is-blu-frog/">Tell Me, What Is Blu Frog?</a></li>
<li><a href="http://gimmeblufrog.com/2009/01/30/whats-in-blu-frog/">What’s in Blu Frog?</a></li>
<li><a href="http://gimmeblufrog.com/2009/01/28/seven-ways-to-make-money-sharing-blu-frog-energy/">Seven Ways to Make Money Sharing Blu Frog Energy</a></li>
</ul>
<p><strong>Wrapping up</strong>: what do you need to do to win a case of Blu Frog? Read the <a href="http://boatinginbeautifulbritishcolumbia.com/2009/02/03/win-blu-frog-on-valentines-day/">instructions</a>, enter the contest, and keep checking <a href="http://boatinginbeautifulbritishcolumbia.com/">Beautiful British Columbia</a> to see if you won!  What are you waiting for?  <a href="http://boatinginbeautifulbritishcolumbia.com/2009/02/03/win-blu-frog-on-valentines-day/">Enter now</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F02%2F04%2Fwin-a-case-of-blu-frog-energy-drink%2F&amp;linkname=Win%20a%20Case%20of%20Blu%20Frog%20Energy%20Drink"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/02/04/win-a-case-of-blu-frog-energy-drink/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamically Adding Elements to Zend_Form</title>
		<link>http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/</link>
		<comments>http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 17:44:56 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[zend form]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=154</guid>
		<description><![CDATA[There have been some requests on the Zend Framework mailing lists for information on how to dynamically add elements to Zend_Form.  This is something that I&#8217;ve been looking into myself, and I&#8217;d like to share what I&#8217;ve come up with.
Please note that this code is a proof of concept / request for peer review detailing [...]]]></description>
			<content:encoded><![CDATA[<p>There have been some requests on the Zend Framework mailing lists for information on how to dynamically add elements to Zend_Form.  This is something that I&#8217;ve been looking into myself, and I&#8217;d like to share what I&#8217;ve come up with.</p>
<p>Please note that this code is a proof of concept / request for peer review detailing the work that I&#8217;ve done to date, and not an example of what I might consider the best way to address this use case.  Special thanks go to <a href="http://www.corywiles.com/home/">Cory Wiles</a> who helped me think things through when I first started giving this a go.</p>
<p>First, let&#8217;s do a high level walk through of what the code is going to do, then take a look at the code, and wrap up with a live example.</p>
<p><strong>High Level Overview</strong></p>
<p>The form in this example extends Zend_Form and consists of a hidden element that stores an ID, a single text element, buttons for adding and removing dynamic elements, and a submit button.  The add and remove buttons are used to trigger a jQuery script that adds and removes dynamic elements. The jQuery script uses the value of the hidden ID element to set element order and make the dynamic element names and IDs unique.</p>
<p>The form class consists of the standard init() method for building the form and two custom methods for dealing with dynamic elements.  There is a preValidation() method, called after the form is submitted but before it is validated, that searches the submitted form data for dynamically added fields.  If any new fields are found, the addNewField() method takes care of adding the new fields to the form.</p>
<p>jQuery is used to request the new form element from the form&#8217;s Controller via Ajax, utilizing the AjaxContext action helper. jQuery is also used to find the most recently added dynamic element, allowing for easy removal of dynamically added elements from the form.</p>
<p>The action controller contains the action that displays the form, and it also has a newfieldAction() that utilizes the AjaxContext to return markup for new fields.</p>
<p><strong>The Zend_Form Subclass</strong></p>
<p>Let&#8217;s start with the code for the form.  The most important item here is that each form element has its order property set.  You can see the huge jump in the order between the &#8220;name&#8221; element and the  &#8220;addElement&#8221; button.  This gap occurs so the dynamic elements can be placed exactly where I want them and so they&#8217;ll maintain their position in the form once they&#8217;ve been added to the form object.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<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;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'hidden'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'value'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'name'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'label'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Name'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'order'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'button'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'addElement'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Add'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'order'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">91</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'button'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'removeElement'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Remove'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'order'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">92</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Submit</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'submit'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'submit'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Submit'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'order'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">93</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Action Controller</strong></p>
<p>The action that displays the form is straightforward.  If you&#8217;ve ever done any work with Zend_Form, I&#8217;m sure you recognize what&#8217;s going on here.  The only thing to note is the $form-&gt;preValidation() method.  That&#8217;s where the magic happens.  We&#8217;ll get to that in a bit.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Shows the dynamic form demonstration page
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> dynamicFormElementsAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Code_Form_Dynamic<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Form has not been submitted - pass to view and return</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isPost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// Form has been submitted - run data through preValidation()</span>
  <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">preValidation</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// If the form doesn't validate, pass to view and return</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// Form is valid</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Next comes the controller&#8217;s newfieldAction().  This action utilizes the AjaxContext action helper to pass the new field&#8217;s markup back to the form view.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Ajax action that returns the dynamic form field
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> newfieldAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000088;">$ajaxContext</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHelper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AjaxContext'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$ajaxContext</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addActionContext</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'newfield'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$element</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element_Text<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;newName<span style="color: #006699; font-weight: bold;">$id</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$element</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setRequired</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">field</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$element</span><span style="color: #339933;">-&gt;</span>__toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>jQuery</strong></p>
<p>The jQuery script is also fairly straightforward.  I attach event listeners to the &#8220;Add&#8221; and &#8220;Remove&#8221; buttons that call the ajaxAddField and removeField methods respectively.</p>
<p>The ajaxAddField method makes a post request to the newfieldAction using <a href="http://docs.jquery.com/Ajax/jQuery.ajax#options">jQuery&#8217;s .ajax method</a>, passing in the current value of the hidden ID element.  On success, the new element&#8217;s markup is added to the form, and the ID is incremented and stored in the hidden ID element.</p>
<p>The removeField method finds the last element in the page with the class dynamic, removes it, then decrements the current ID and stores the new value in the hidden ID element.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
&nbsp;
$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#addElement&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span> 
      <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
          ajaxAddField<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#removeElement&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span>
      <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          removeField<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Get value of id - integer appended to dynamic form field names and ids</span>
<span style="color: #003366; font-weight: bold;">var</span> id <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#id&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Retrieve new element's html from controller</span>
<span style="color: #003366; font-weight: bold;">function</span> ajaxAddField<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  $.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span>
    <span style="color: #009900;">&#123;</span>
      type<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;POST&quot;</span><span style="color: #339933;">,</span>
      url<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;&lt;?=$this-&gt;url(array('action' =&gt; 'newfield', 'format' =&gt; 'html'));?&gt;&quot;</span><span style="color: #339933;">,</span>
      data<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;id=&quot;</span> <span style="color: #339933;">+</span> id<span style="color: #339933;">,</span>
      success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>newElement<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// Insert new element before the Add button</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#addElement-label&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">before</span><span style="color: #009900;">&#40;</span>newElement<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// Increment and store id</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#id&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> removeField<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Get the last used id</span>
  <span style="color: #003366; font-weight: bold;">var</span> lastId <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#id&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Build the attribute search string.  This will match the last added  dt and dd elements.  </span>
  <span style="color: #006600; font-style: italic;">// Specifically, it matches any element where the id begins with 'newName&lt;int&gt;-'.</span>
  searchString <span style="color: #339933;">=</span> <span style="color: #3366CC;">'*[id^=newName'</span> <span style="color: #339933;">+</span> lastId <span style="color: #339933;">+</span> <span style="color: #3366CC;">'-]'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Remove the elements that match the search string.</span>
  $<span style="color: #009900;">&#40;</span>searchString<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Decrement and store id</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#id&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">--</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p><strong>Zend_Form: preValidation() and addNewField()</strong></p>
<p>Now on to the fun stuff.  All of the code up to this point is present to support what happens in the form&#8217;s preValidation() method.  Remember that preValidation() is called after the form has been submitted but before the form is validated.  preValidation() searches through the submitted form&#8217;s data for new fields.  If it finds any new fields, it calls addNewField() and adds the new fields to the form object.  By adding the new form fields to the form object before validation, any filters and validators attached to the new fields will be run as if those fields had always existed in the form object.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * After post, pre validation hook
 * 
 * Finds all fields where name includes 'newName' and uses addNewField to add
 * them to the form object
 * 
 * @param array $data $_GET or $_POST
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preValidation<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// array_filter callback</span>
  <span style="color: #000000; font-weight: bold;">function</span> findFields<span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// return field names that include 'newName'</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'newName'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$field</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Search $data for dynamically added fields using findFields callback</span>
  <span style="color: #000088;">$newFields</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_filter</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'findFields'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$newFields</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$fieldName</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// strip the id number off of the field name and use it to set new order</span>
    <span style="color: #000088;">$order</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ltrim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fieldName</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'newName'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addNewField</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fieldName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$fieldName</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * Adds new fields to form
 *
 * @param string $name
 * @param string $value
 * @param int    $order
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> addNewField<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</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;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'required'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'label'</span>          <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Name'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'value'</span>          <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'order'</span>          <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$order</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Live Example</strong></p>
<p>If you&#8217;d like to see working version of this proof of concept, please visit <a href="http://code.jeremykendall.net/forms/dynamic-form-elements">the live example</a> at code.jeremykendall.net.</p>
<p><strong>Summary</strong></p>
<p>The ability to dynamically add form fields to Zend_Form is a feature I&#8217;d really like to see added to Zend_Form.  If I were talented enough, I might attempt to make a formal proposal myself.  In the meantime, what I&#8217;ve come up with can perhaps serve as a starting point for adding very simple elements to very simple forms.</p>
<p>Thanks again to <a href="http://www.corywiles.com/home/">Cory Wiles</a> for helping me work out some of the kinks during the planning phase.  Any mistakes, bad practices, or egregious coding errors are the result of my implementation, not his insight and suggestions.</p>
<p><strong>Request for Comments / Peer Review</strong></p>
<p>If you&#8217;ve made it this far, I&#8217;m grateful to you for hanging in with me.  If you have suggestions for improvements to the code, an implementation of your own, or if you see mistakes I&#8217;ve made or poor practices that I&#8217;ve employed, I&#8217;d appreciate your input.  Thank you in advance for taking the time to discuss this concept with myself and with the ZF community at large.</p>
<p><strong>Full Controller, Form, and View Code</strong></p>
<p>If you&#8217;re interested in the complete code for the controller, form, and views, I&#8217;ve posted them over at pastebin.  Follow the links below to view / grab the code.</p>
<ul>
<li><a href="http://jeremykendall.pastebin.com/f675a1ec1">Action Controller (FormsController)<br />
</a></li>
<li><a href="http://jeremykendall.pastebin.com/f5d408d7b">Form (Code_Form_Dynamic)<br />
</a></li>
<li><a href="http://jeremykendall.pastebin.com/f56ccb1f7">Form view (dynamic-form-elements.phtml)<br />
</a></li>
<li><a href="http://jeremykendall.pastebin.com/f423d0ee3">Ajax view (newfield.ajax.phtml)<br />
</a></li>
</ul>
<p><strong>Further reading:</strong></p>
<ul>
<li><a href="http://framework.zend.com/manual/en/zend.form.html">Zend_Form</a></li>
<li><a href="http://framework.zend.com/manual/en/zend.form.elements.html#zend.form.elements.decorators">Zend_Form Decorators</a></li>
<li><a href="http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch">AjaxContext Action Helper</a></li>
<li><a href="http://jquery.com/">jQuery JavaScript Library</a></li>
<li><a href="http://docs.jquery.com/Events/click">jQuery Events/click</a></li>
<li><a href="http://docs.jquery.com/Manipulation/append">jQuery Manipulation/append</a></li>
<li><a href="http://docs.jquery.com/Manipulation/remove">jQuery Manipulation/remove</a></li>
</ul>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F01%2F19%2Fdynamically-adding-elements-to-zend-form%2F&amp;linkname=Dynamically%20Adding%20Elements%20to%20Zend_Form"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Blu Frog is Here &#8211; Get Some!</title>
		<link>http://www.jeremykendall.net/2009/01/01/blu-frog-is-here-get-some/</link>
		<comments>http://www.jeremykendall.net/2009/01/01/blu-frog-is-here-get-some/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 16:59:38 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blu Frog]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=146</guid>
		<description><![CDATA[Drop the Jolt Cola, get rid of Red Bull, forget about Rock Star &#8211; Blu Frog is here!  The best tasting, fastest acting, healthiest energy drink ever has just hit the market!  Don&#8217;t take my word for it, check out the comparison between Blu Frog and the leading competitors below!

What&#8217;s more, you can [...]]]></description>
			<content:encoded><![CDATA[<p>Drop the Jolt Cola, get rid of Red Bull, forget about Rock Star &#8211; <a href="http://gimmeblufrog.com">Blu Frog</a> is here!  The best tasting, fastest acting, healthiest energy drink ever has just hit the market!  Don&#8217;t take my word for it, check out the comparison between Blu Frog and the leading competitors below!</p>
<p><img class="aligncenter size-full wp-image-147" title="compareblufrog" src="http://www.jeremykendall.net/wp-content/uploads/2009/01/compareblufrog.jpg" alt="compareblufrog" width="403" height="300" /></p>
<p>What&#8217;s more, you can <strong>get paid</strong> for sharing Blu Frog with your friends!  Drink <strong><span style="color: #0000ff;">Blu</span></strong>, make <strong><span style="color: #339966;">Green</span></strong>!</p>
<p>Get more info and sign up to get your own <a href="http://gimmeblufrog.com">Blu Frog</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2009%2F01%2F01%2Fblu-frog-is-here-get-some%2F&amp;linkname=Blu%20Frog%20is%20Here%20%26%238211%3B%20Get%20Some%21"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/01/01/blu-frog-is-here-get-some/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conditional Form Validation with Zend_Form</title>
		<link>http://www.jeremykendall.net/2008/12/24/conditional-form-validation-with-zend_form/</link>
		<comments>http://www.jeremykendall.net/2008/12/24/conditional-form-validation-with-zend_form/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 15:41:06 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=128</guid>
		<description><![CDATA[A question from &#8216;ronny stalker&#8217; in the Zend_Form_Element_Multi &#8211; Tips and Tricks comments:
I need to do different validations for field A depending on the value of field B and (possibly depending on a variable that is not in the form at all &#8211; C ).
in this kind of logic:
if (B ==1)
{
validator_B(A);
}
elseif (C)
{
validator_C(A);
}
else
{
validator_Default(A);
}
I understand that validators [...]]]></description>
			<content:encoded><![CDATA[<p>A question from &#8216;ronny stalker&#8217; in the <a href="http://www.jeremykendall.net/2008/12/04/zend_form_element_multi-tips-and-tricks/">Zend_Form_Element_Multi &#8211; Tips and Tricks</a> comments:</p>
<blockquote><p>I need to do different validations for field A depending on the value of field B and (possibly depending on a variable that is not in the form at all &#8211; C ).</p>
<p>in this kind of logic:</p>
<p>if (B ==1)<br />
{<br />
validator_B(A);<br />
}<br />
elseif (C)<br />
{<br />
validator_C(A);<br />
}<br />
else<br />
{<br />
validator_Default(A);<br />
}</p>
<p>I understand that validators get a secondary argument called $context &#8211; which can be used to check values of other fields, but how can a validator get knowledge of other variables in the environment?</p></blockquote>
<p>While this post may not answer ronny&#8217;s question exactly, hopefully it will give him a good starting point to get over the hump.</p>
<p><strong>If other, please explain &#8211; Conditional Validation Using $context</strong></p>
<p>Many forms have a set of radio buttons, or sometimes a select element, where a user can choose from one of several options.  Sometimes &#8220;other&#8221;  will be one of those options, with a corresponding &#8220;If other, please explain&#8221; text field placed directly after.  If &#8220;other&#8221; is selected, then the accompanying text field is usually required.  Since there&#8217;s not a standard <a href="http://framework.zend.com/manual/en/zend.validate.html">Zend Validate validator</a> for this scenario, I&#8217;ve written a custom validator that seems to do the trick.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * Kendall Extensions
 * 
 * @category Kendall
 * @package  Kendall_Validate
 * @author   Jeremy Kendall 
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * @see Zend_Validate_Abstract
 */</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Validate/Abstract.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * Requires field presence based on provided value of radio element.  
 * 
 * Example would be radio element with Yes, No, Other option, followed by an &quot;If 
 * other, please explain&quot; text area.
 * 
 * IMPORTANT: For this validator to work, allowEmpty must be set to false on 
 * the child element being validated.
 * 
 * From Zend Framework Documentation 15.3: &quot;By default, when an 
 * element is required, a flag, 'allowEmpty', is also true. This means that if 
 * a value evaluating to empty is passed to isValid(), the validators will be 
 * skipped. You can toggle this flag using the accessor setAllowEmpty($flag); 
 * when the flag is false, then if a value is passed, the validators will still 
 * run.&quot;
 * 
 * @uses     Zend_Validate_Abstract
 * @category Kendall
 * @package  Kendall_Validate
 * @author   Jeremy Kendall 
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Kendall_Validate_FieldDepends <span style="color: #000000; font-weight: bold;">extends</span> Zend_Validate_Abstract <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Validation failure message key for when the value of the parent field is an empty string
   */</span>
  <span style="color: #000000; font-weight: bold;">const</span> KEY_NOT_FOUND  <span style="color: #339933;">=</span> <span style="color: #0000ff;">'keyNotFound'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Validation failure message key for when the value is an empty string
   */</span>
  <span style="color: #000000; font-weight: bold;">const</span> KEY_IS_EMPTY   <span style="color: #339933;">=</span> <span style="color: #0000ff;">'keyIsEmpty'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Validation failure message template definitions
   *
   * @var array
   */</span>
  protected <span style="color: #000088;">$_messageTemplates</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">KEY_NOT_FOUND</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Parent field does not exist in form input'</span><span style="color: #339933;">,</span>
    <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">KEY_IS_EMPTY</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Based on your answer above, this field is required'</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Key to test against
   *
   * @var string|array
   */</span>
  protected <span style="color: #000088;">$_contextKey</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * String to test for
   *
   * @var string
   */</span>
  protected <span style="color: #000088;">$_testValue</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * FieldDepends constructor
   *
   * @param string $contextKey Name of parent field to test against
   * @param string $testValue Value of multi option that, if selected, child field required
   */</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: #000088;">$contextKey</span><span style="color: #339933;">,</span> <span style="color: #000088;">$testValue</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTestValue</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$testValue</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContextKey</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Defined by Zend_Validate_Interface
   *
   * Wrapper around doValid()
   *
   * @param  string $value
   * @param  array  $context
   * @return boolean
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isValid<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$contextKey</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContextKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// If context key is an array, doValid for each context key</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$contextKey</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$ck</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;">setContextKey</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ck</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">doValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">doValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Returns true if dependant field value is not empty when parent field value
   * indicates that the dependant field is required
   *
   * @param  string $value
   * @param  array  $context
   * @return boolean
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doValid<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$testValue</span>  <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTestValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$contextKey</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContextKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$value</span>      <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setValue<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contextKey</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_error<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">KEY_NOT_FOUND</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$context</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$parentField</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$parentField</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$testValue</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;">$testValue</span> <span style="color: #339933;">==</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$parentField</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_error<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">KEY_IS_EMPTY</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$parentField</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_error<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">KEY_IS_EMPTY</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @return string
   */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> getContextKey<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>_contextKey<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @param string $contextKey
   */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> setContextKey<span style="color: #009900;">&#40;</span><span style="color: #000088;">$contextKey</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>_contextKey <span style="color: #339933;">=</span> <span style="color: #000088;">$contextKey</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @return string
   */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> getTestValue <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>_testValue<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @param string $testValue
   */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> setTestValue <span style="color: #009900;">&#40;</span><span style="color: #000088;">$testValue</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>_testValue <span style="color: #339933;">=</span> <span style="color: #000088;">$testValue</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The validator above is essentially a conditional NotEmpty validator.  It checks the value of a parent field to see if a child field should be required.  IMPORTANT:  allowEmpty <em>must</em> be set to false on the child field.</p>
<p>Here&#8217;s an example of how to use the validator.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Parent element</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'radio'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flavor'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
  <span style="color: #0000ff;">'required'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'label'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Choose a flavor'</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'multiOptions'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Vanilla'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Vanilla'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Chocolate'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Chocolate'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Other'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Other'</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Child element. IMPORTANT: allowEmpty must be set to false!</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flavorOther'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
  <span style="color: #0000ff;">'allowEmpty'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'If Other, provide flavor here'</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'validators'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Kendall_Validate_FieldDepends<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'flavor'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Other'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Again, please note that allowEmpty has been set to false on the child field.  This is necessary to run the FieldDepends validator even when the &#8220;If other . . .&#8221; element is empty.</p>
<p>While I&#8217;m sure there&#8217;s plenty of room for refactoring, the above code has served me well.</p>
<p><strong>Adding Validators After Submission but Before Validation</strong></p>
<p>Expanding on the example above, what if it became necessary to add additional validators to the &#8220;If other . . .&#8221; field?  Because the &#8220;If other . . .&#8221; field has allowEmpty set to false, and because an empty value is sometimes a valid value, it is not possible to add additional validators that will run only if the field is not empty.  The additional validators will run regardless of the value of the &#8220;If other . . .&#8221; element, throwing errors when the element is empty.  Additional validators will have to be added somewhere else.</p>
<p>In order to work around this issue, I added a custom method called preValidation() to my form class.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preValidation<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'flavorOther'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flavorOther</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> FlavorOther_Validator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The preValidation() method is called after submission but before validation.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Flavor_Form<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isPost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// Display form</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> 
&nbsp;
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">preValidation</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// Failed validation, redisplay form with values and errors</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">// Passed validation</span></pre></div></div>

<p>While the preValidation() code above adds validation depending on the state of an element in the form, it would be trivial to add validation to the form based on any number of conditions, including conditions that exist as a result of business rules rather than the form&#8217;s input.</p>
<p><strong>Wrapping Up</strong></p>
<p>Writing custom validators for the Zend Framework makes server side validation of unique validation scenarios a breeze.  I have yet to encounter a non-standard validation scenario where I haven&#8217;t been able to address it by writing a custom validator.  With the ability to extend Zend Form with a couple of helpful custom methods, adding additional validation after form submission becomes trivial.</p>
<p>Have you ever had to write any custom validators?  Any suggestions on improving the code above?  Jump down to the comments and let us know!</p>
<p><strong>UPDATED</strong> to add code comments to the validator implementation example.  Thanks to reader <a href="http://www.11outof10.com/">Neil</a> for the suggestion.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2008%2F12%2F24%2Fconditional-form-validation-with-zend_form%2F&amp;linkname=Conditional%20Form%20Validation%20with%20Zend_Form"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2008/12/24/conditional-form-validation-with-zend_form/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Zebra Tables with jQuery</title>
		<link>http://www.jeremykendall.net/2008/12/11/zebra-tables-with-jquery/</link>
		<comments>http://www.jeremykendall.net/2008/12/11/zebra-tables-with-jquery/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 13:45:33 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=120</guid>
		<description><![CDATA[I&#8217;ve used the classic A List Apart Zebra Tables technique to stripe my tables for years.  It&#8217;s always worked well, and I never really considered updating the technique until last week.  I&#8217;ve been making heavy use of the jQuery library lately, and I really disliked including another external js file whenever I wanted to stripe [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve used the classic A List Apart <a href="http://www.alistapart.com/articles/zebratables"><em>Zebra Tables</em></a> technique to stripe my tables for years.  It&#8217;s always worked well, and I never really considered updating the technique until last week.  I&#8217;ve been making heavy use of the <a href="http://jquery.com/">jQuery</a> library lately, and I really disliked including another external js file whenever I wanted to stripe a table, so I thought I&#8217;d see if someone had come up with a jQuery friendly table striping technique.  It took about 10 seconds on Google to find what I was looking for, and the solution was so simple and elegant that I wanted to kick myself for not thinking of it, er, myself.</p>
<p>For the whole scoop, head over and <a href="http://15daysofjquery.com/examples/zebra/">read the tutorial</a>.  If you&#8217;re like me, you want to get right to the point, so here goes.</p>
<p>The idea is to use jQuery to select alternate rows from your table and apply a css class to them. In the example below, the table has a class of &#8217;striped&#8217; and jQuery adds the class &#8216;alt&#8217; to the even rows.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.striped tr:even&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;alt&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Whip up a little css that adds a background color to .alt and you&#8217;re done.  Not bad, huh?</p>
<p>The tutorial author also included an example of jQuery code that allows for a nice hover effect when you mouse over the table rows.  I wasn&#8217;t as interested in that, so you&#8217;ll have to <a href="http://15daysofjquery.com/examples/zebra/">head over there</a> for the scoop.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2008%2F12%2F11%2Fzebra-tables-with-jquery%2F&amp;linkname=Zebra%20Tables%20with%20jQuery"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2008/12/11/zebra-tables-with-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend_Form_Element_Multi &#8211; Tips and Tricks</title>
		<link>http://www.jeremykendall.net/2008/12/04/zend_form_element_multi-tips-and-tricks/</link>
		<comments>http://www.jeremykendall.net/2008/12/04/zend_form_element_multi-tips-and-tricks/#comments</comments>
		<pubDate>Thu, 04 Dec 2008 13:46:54 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=87</guid>
		<description><![CDATA[I&#8217;m responsible for creating a lot of forms at my day job.  It seems that any project I get involved in requires at least one form.  The Zend Form component has made my life a lot easier.  After putting together more forms than I can count, I&#8217;ve picked up a couple of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m responsible for creating a lot of forms at my day job.  It seems that any project I get involved in requires at least one form.  The <a href="http://framework.zend.com/manual/en/zend.form.html">Zend Form</a> component has made my life a lot easier.  After putting together more forms than I can count, I&#8217;ve picked up a couple of tricks that I&#8217;d like to share.  Here are some for the Zend_Form_Element_Multi elements.</p>
<p>As noted in the <a href="http://framework.zend.com/apidoc/core/">API documentation</a>, Zend_Form_Element_Multi is the base class for multi-option form elements.  Its direct descendants are the Zend Form <a href="http://framework.zend.com/manual/en/zend.form.standardElements.html#zend.form.standardElements.select">Select</a>, <a href="http://framework.zend.com/manual/en/zend.form.standardElements.html#zend.form.standardElements.radio">Radio</a>, and <a href="http://framework.zend.com/manual/en/zend.form.standardElements.html#zend.form.standardElements.multiCheckbox">MultiCheckbox</a> elements.  Adding options to these elements is possible using the addMultiOptions method.  Most of what I want to cover is about retrieving, creating, and adding options, with a short detour into validation.</p>
<p><strong>Using array_combine</strong></p>
<p>Sometimes you want the displayed element options to be the same options returned by the form (as opposed to displaying a string while returning an id).  Perhaps you&#8217;ll be sending the value(s) along in an email or storing them as strings in a database.  While you can create an associative array with matching keys and values, the process quickly becomes tedious with an array of any appreciable size.  Why not use <a href="http://us.php.net/array_combine">array_combine</a> to make life easier?</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Vanilla'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Chocolate'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Strawberry'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Cookies and Cream'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Chocolate Chip'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_combine</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Using array_merge</strong></p>
<p><a href="http://us.php.net/array_merge">array_merge</a> is helpful when you&#8217;d like to add an item to your options array that isn&#8217;t already a part of the options array.  For example, I frequently add a &#8220;Please make a selection&#8221; option to my select elements.  Extending the above example, I might choose to add the new option like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Please select a flavor'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>One word of caution: array_merge will reindex numerically indexed arrays.  array_merge should never be used in a situation where the original array needs to be preserved, such as a numerically indexed array of id and value pairs pulled from a database.  In those cases, I use the + operator.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// $options is an array of database ids and flavor descriptions</span>
<span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Select a flavor'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$options</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Retrieving options using Zend_Db</strong></p>
<p>I frequently retrieve options from a database, using the record id as the array&#8217;s index and a related string as the array&#8217;s value.  There are a lot of ways retrieve options using <a href="http://framework.zend.com/manual/en/zend.db.html">Zend_Db</a>, but my favorite is the <a href="http://framework.zend.com/manual/en/zend.db.html#zend.db.adapter.select.fetchpairs">fetchPairs</a> method.</p>
<blockquote><p>The <code class="code">fetchPairs()</code> method returns data in an array                 of key-value pairs, as an associative array with a single entry                 per row.  The key of this associative array is taken from the                 first column returned by the SELECT query.  The value is taken                 from the second column returned by the SELECT query.  Any other                 columns returned by the query are discarded.</p></blockquote>
<p>Here&#8217;s what that might look like.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$select</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'SELECT flavor_id, flavor FROM flavors'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchPairs</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$select</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>I especially enjoy using this method with <a href="http://framework.zend.com/manual/en/zend.db.table.html">Zend_Db_Table</a>, using custom table class methods to retrieve my options.  My table class usually looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Flavors <span style="color: #000000; font-weight: bold;">extends</span> Zend_Db_Table_Abstract <span style="color: #009900;">&#123;</span>
&nbsp;
  protected <span style="color: #000088;">$_name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'flavors'</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getFlavorOptions<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000088;">$select</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'flavor_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'flavor'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAdapter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchPairs</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$select</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$result</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Grabbing your options now becomes ridiculously simple.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$flavors</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Flavors<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$flavorOptions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flavors</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlavorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Validation with Zend_Validate_InArray</strong></p>
<p><a href="http://framework.zend.com/manual/en/zend.validate.set.html#zend.validate.set.in_array">Zend_Validate_InArray</a> is the default validator for Multi elements, but the InArray validator can be a little tricky to implement properly.  Below are the two gotchas that I&#8217;ve run into.</p>
<p>Let&#8217;s say you&#8217;ve got a select element in your form.  In order to force the user to select an option, you&#8217;ve added a &#8220;Please Select&#8221; option to the beginning of your options array.  If you use the default InArray validation against the full list of options, &#8220;Please Select&#8221; becomes a valid selection, and you may end up stuck with a lot of bad form submissions.  In order to get around this, I make sure to pass the original array of options to the validator, and use array_merge or the + operator to add the &#8220;Please select&#8221; option before adding the options to the element.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Create list of flavor options</span>
<span style="color: #000088;">$flavorOptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Vanilla'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Chocolate'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Strawberry'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Cookies and Cream'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Chocolate Chip'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$flavorOptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_combine</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$flavorOptions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$flavorOptions</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add &quot;Select a flavor&quot; option</span>
<span style="color: #000088;">$flavorMultiOptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Select a flavor'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$flavorOptions</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add flavor options to flavor select element</span>
<span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flavor</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addMultiOptions</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$flavorMultiOptions</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add validation, validating against original $flavorOptions array</span>
<span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flavor</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Validate_InArray<span style="color: #009900;">&#40;</span><span style="color: #000088;">$flavorOptions</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The second gotcha has to do with option arrays where the keys and values don&#8217;t match.  InArray tests the element&#8217;s selected value against the values of the options array, but what you really want to do is test the element&#8217;s selected value against the keys of the options array.  The trick is to use PHP&#8217;s <a href="http://us.php.net/array_keys">array_keys</a> function.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Get flavor ids and descriptions from database</span>
<span style="color: #000088;">$flavors</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Flavors<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$flavorOptions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flavors</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlavorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add &quot;Select a flavor&quot; option, preserving original array with the + operator</span>
<span style="color: #000088;">$flavorMultiOptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Select a flavor'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$flavorOptions</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add flavor options to flavor select element</span>
<span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flavor</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addMultiOptions</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$flavorMultiOptions</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add validation, validating against array keys of the original $flavorOptions array</span>
<span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flavor</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Validate_InArray<span style="color: #009900;">&#40;</span><span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$flavorOptions</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Do you have any Zend_Form tips or tricks that you&#8217;d like to share?  Have I made any egregious errors above that need to be corrected?  Hit the comments and let me know.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.jeremykendall.net%2F2008%2F12%2F04%2Fzend_form_element_multi-tips-and-tricks%2F&amp;linkname=Zend_Form_Element_Multi%20%26%238211%3B%20Tips%20and%20Tricks"><img src="http://www.jeremykendall.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2008/12/04/zend_form_element_multi-tips-and-tricks/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
