<?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 &#187; zend framework</title>
	<atom:link href="http://www.jeremykendall.net/tag/zend-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeremykendall.net</link>
	<description>{web developer, entrepreneur }</description>
	<lastBuildDate>Fri, 23 Jul 2010 19:18:30 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>From Zero to Zend Framework Project in 10 Minutes</title>
		<link>http://www.jeremykendall.net/2010/04/17/from-zero-to-zend-framework-project-in-10-minutes/</link>
		<comments>http://www.jeremykendall.net/2010/04/17/from-zero-to-zend-framework-project-in-10-minutes/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 19:18:46 +0000</pubDate>
		<dc:creator>Jeremy Kendall</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[zend tool]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=243</guid>
		<description><![CDATA[I first started working with the Zend Framework in July of 2007.  The framework has come a long way since then, and one of my favorite new components is Zend Tool.  Until Zend Tool came on the scene, my least favorite part of any Zend Framework project was getting the project up and [...]]]></description>
			<content:encoded><![CDATA[<p>I first started working with the <a href="http://framework.zend.com">Zend Framework</a> in July of 2007.  The framework has come a long way since then, and one of my favorite new components is <a href="http://framework.zend.com/manual/en/zend.tool.html">Zend Tool</a>.  Until Zend Tool came on the scene, my least favorite part of any Zend Framework project was getting the project up and running, from zero to &#8220;Hello World,&#8221; if you will.  I always left out some important piece of configuration, screwed up the directory structure, or made some other equally foolish, simple mistake that kept me chasing my tail until I finally got everything set up just right.  No longer! Zend Tool does all of that work for me, allowing me to get to work on the meat of my project right away.</p>
<p>Of course, you can&#8217;t use Zend Tool until you&#8217;ve got the framework installed.  Once the framework is installed, there are very specific steps required to fire up Zend Tool.  Once Zend Tool builds the project for you, you&#8217;re going to need a <a href="http://httpd.apache.org/docs/2.0/vhosts/">virtual host</a> set up so that you can actually run the thing. No problem, right?  Well, maybe not.</p>
<p>It can be really challenging for the new guy to get from zero to a Zend Framework project without wanting to chunk his computer out the window (<a href="http://www.urbandictionary.com/define.php?term=headdesk&amp;defid=2569861">headdesk</a> anyone?).  I know it was that way for me.  In the interest of saving his sanity and helping the new gal get going, I&#8217;ve tried to put all the necessary steps together in one place.</p>
<p>Here&#8217;s what we&#8217;re going to do:</p>
<ul>
<li>Install the Zend Framework</li>
<li>Get Zend Tool up and running</li>
<li>Create a new Zend Framework project</li>
<li>Get an virtual host up and running</li>
<li>Celebrate victory!</li>
</ul>
<p><strong>Disclaimer</strong></p>
<p>While I&#8217;m going try to stay true to my &#8220;Zero to Zend Framework Project&#8221; thesis, I am making a few assumptions.  This tutorial is written for <a href="http://www.ubuntu.com/">Ubuntu</a>, <a href="http://php.net/">PHP 5</a>, and <a href="http://httpd.apache.org/">Apache</a>. While I&#8217;d love to be able to address Windows, Mac, and other *nix distros, I can only share what I know.  I&#8217;m also assuming PHP 5 (PHP 5.2.4 at minimum) and Apache are both installed and functioning correctly, and Apache&#8217;s <a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html">mod_rewrite</a> module is up and running.  If that&#8217;s not the case, please refer to the resources section at the end of this post to find instructions on getting everything ready to go.</p>
<p><strong>Installing the Zend Framework</strong></p>
<p>Installing the Zend Framework is as easy as downloading a .zip or .tar.gz file (your choice) and extracting the contents onto your machine.</p>
<ul>
<li>Create a directory named phplib in your home folder.</li>
<li>Head over to <a href="http://framework.zend.com/download/latest">Zend Framework: Downloads</a> and download Zend Framework &lt;version_num&gt; Full.</li>
<li>Double click on the downloaded file, choose &#8220;Extract,&#8221; navigate to the phplib directory, and click &#8220;Extract.&#8221;</li>
</ul>
<p>As of this writing, the most recent version of the Zend Framework is 1.10.3, so the full path to my Zend Framework installation would be</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/home/jkendall/phplib/ZendFramework-1.10.3</pre></div></div>

<p><strong>IMPORTANT</strong>: Make sure that you downloaded Zend Framework &lt;version_num&gt; Full.  That will be important later.</p>
<p><strong>TIP</strong>: As new versions of the framework are released, I like to be able to switch between them easily.  I always make a <a href="http://en.wikipedia.org/wiki/Symbolic_link">soft link (symbolic link, symlink)</a> to the latest release and name it Zend.  You can either right-click on the ZendFramework-1.10.3 folder and select &#8220;Make Link&#8221; (make sure to name the link &#8220;Zend&#8221;), or create a soft link from the command line like so:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">~/phplib/ZendFramework-1.10.3$ ln -s ZendFramework-1.10.3 Zend</pre></div></div>

<p>When a new version of the framework is released, I install the new version to its own folder and switch the soft link to target the directory containing the latest release.  That can come in handy down the road.</p>
<p><strong>Get Zend Tool running</strong></p>
<p>There are a <a href="http://framework.zend.com/manual/en/zend.tool.usage.cli.html">few different ways to get Zend Tool running</a>, perhaps better than mine, but I like to create a <a href="http://www.sucka.net/2009/09/ubuntu-command-line-tip-1-%E2%80%93-aliases/">bash alias</a> for zf.sh (For information on how to get bash aliases working, see this <a href="http://www.sucka.net/2009/09/ubuntu-command-line-tip-1-%E2%80%93-aliases/">bash aliases tutorial</a>.).  My alias looks like <code>alias zf='/usr/share/phplib/Zend/bin/zf.sh'</code>.</p>
<p>Whichever method you use, make sure to test your alias by calling <code>zf --help</code> from the command line.</p>
<p><strong>Creating a new Zend Framework Project</strong></p>
<p>Now we&#8217;re getting to the good stuff.  First, head back to your home directory and create a new directory called public_html.  This is where you&#8217;re going to store your Zend Framework project (and any future web projects, for that matter).</p>
<p>Next, cd into the public_html directory and execute the following command:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">~/public_html$ zf create project ZeroToZF</pre></div></div>

<p>That&#8217;s all there is to it!  You&#8217;ve got your project structure in place, a default IndexController and ErrorController, your application config, the necessary view scripts, etc (See the <a href="http://framework.zend.com/manual/en/zend.application.quick-start.html">Zend Application Quick Start</a> for full rundown of what got created.).</p>
<p><strong>IMPORTANT</strong>: While the full project structure is now in place, the Zend Framework <strong>is not included in your project for you</strong>.  Deciding how the framework should be included in the project is up to the developer.  I like to copy the library out of the Zend Framework install folder into the application&#8217;s library folder.  In our example, I would copy</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/home/jkendall/phplib/ZendFramework-1.10.3/library/Zend</pre></div></div>

<p>into</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/home/jkendall/public_html/ZeroToZF/library</pre></div></div>

<p>When done properly, the full path to Zend/Log.php in your application should be</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/home/&lt;username&gt;/public_html/ZeroToZF/library/Zend/Log.php</pre></div></div>

<p>Sweet!  We&#8217;re almost there.</p>
<p><strong>Creating a Virtual Host</strong></p>
<p>There are a decent number of steps here, but executing them is straightforward, so bear with me.  Also, a lot of these steps need to be executed from the command line.  <a href="http://idioms.thefreedictionary.com/Forewarned+is+forearmed">Forewarned is forearmed</a> and all that.</p>
<p>If you have not done so already, open the terminal application (Applications -&gt; Accessories -&gt; Terminal) and cd into <code>/etc/apache2/sites-available</code>.  Here you&#8217;ll find virtual host definitions.  Most likely you&#8217;ll see a file named default (or possibly 000-default).  Peek at that if you&#8217;d like to see an example of a virtual host, but what we&#8217;re going to put together is a lot simpler.</p>
<p><strong>IMPORTANT</strong>: Since <code>/etc</code> and its subfolders are owned by root, you&#8217;ll need to run all of the following commands as root.  We&#8217;ll be using both the <a href="https://help.ubuntu.com/community/RootSudo#sudo">sudo</a> and the <a href="https://help.ubuntu.com/community/RootSudo#Graphical sudo">gksudo</a> commands to do that.</p>
<p>After using the command line to cd into <code>/etc/apache2/sites-available</code>, execute the following command to create your own vhost file:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/etc/apache2/sites-available$ gksudo gedit ZeroToZf.local</pre></div></div>

<p>The file extension isn&#8217;t important, a lot of people use .conf, but I like to use .local for sites hosted locally.</p>
<p>Once you&#8217;ve got gedit open, the file&#8217;s contents should look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
        ServerName zerotozf.local
        DocumentRoot /home/jkendall/public_html/ZeroToZF/public
&lt;/VirtualHost&gt;</pre></div></div>

<p>Of course, jkendall should be replaced by your username.</p>
<p>Next we need to make your new virtual host file available to Apache.  You can do that by executing</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/etc/apache2/sites-available$ sudo a2ensite ZeroToZF.local</pre></div></div>

<p>If everything worked properly, you should see the following message:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">Enabling site ZeroToZF.local.
Run '/etc/init.d/apache2 reload' to activate new configuration!</pre></div></div>

<p>Next, edit your <code>/etc/hosts</code> file by adding <code>zerotozf.local</code> like so:</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/etc/apache2/sites-available$ gksudo gedit /etc/hosts</pre></div></div>

<p>Add the following line below the entry for localhost</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">127.0.0.1 zerotozf.local</pre></div></div>

<p><strong>NOTE</strong>: When adding a host to /etc/hosts, the case of the hostname is not important.  I like to add hostnames in lowercase, but you can add it as ZeroToZF.local if you like.</p>
<p>Save the file, close gedit, and execute</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">/etc/apache2/sites-available$ sudo /etc/init.d/apache2 reload</pre></div></div>

<p>You should see the message</p>

<div class="wp_syntax"><div class="code"><pre class="code" style="font-family:monospace;">* Reloading web server config apache2                                          [ OK ]</pre></div></div>

<p>Open up your browser and visit <a href="http://zerotozf.local">http://zerotozf.local</a>.  You should see the Zend Framework welcome screen.</p>
<p>Congrats!  You did it!</p>
<p><strong>Next Steps</strong></p>
<p>Now that you&#8217;ve got your first project up and running, you&#8217;re probably going to want to actually do something with it.  I&#8217;d highly recommend heading over to <a href="http://akrabat.com/">Rob Allen&#8217;s site</a> for his excellent <a href="http://akrabat.com/zend-framework-tutorial/">Getting Started with Zend Framework</a> tutorial.  It&#8217;s the same tutorial I followed when I first started with the framework (an earlier version, of course), and I&#8217;ve referred back to it many times since.</p>
<p><strong>Wrapping Up</strong></p>
<p>Getting started with the Zend Framework was a challenging proposition for me.  Just getting to the point where I could start working on a project was sometimes maddening as a result of all the steps involved, many of which had nothing to do with the framework, at least not directly.  I&#8217;ve tried, hopefully successfully, to lay out all the steps you might need to get from zero to a Zend Framework project in (about) 10 minutes.</p>
<p>Working with the Zend Framework has been a rich and rewarding experience for me.  I&#8217;ve learned <em>almost</em> everything I know about best practices, object oriented programming, *nix, and Apache (to name just a few) as a direct or indirect result of the Zend Framework.  I wouldn&#8217;t have been able to do that without the help of the Zend Framework community.  I won&#8217;t name names, as I&#8217;m sure to unintentionally leave out some great folks, so I&#8217;ll throw you a link to the <a href="http://n4.nabble.com/Zend-Framework-Community-f634137.html">Zend Framework Community Forum</a>.  Head over there when you&#8217;ve got a Zend Framework problem you just can&#8217;t solve on your own.  You&#8217;ll meet some great folks and learn a lot in the process.  They&#8217;ve saved my bacon more than once.</p>
<p>If I&#8217;ve left out any steps or made some egregious error, please let me know in the comments.  I&#8217;ll be grateful and post updates and corrections as soon as possible.</p>
<p><strong>Resources</strong></p>
<ul>
<li>How to <a href="https://help.ubuntu.com/9.10/serverguide/C/php5.html">install PHP in Ubuntu</a></li>
<li>How to <a href="https://help.ubuntu.com/9.10/serverguide/C/httpd.html">install Apache in Ubuntu</a></li>
<li><a href="http://www.ghacks.net/2009/12/05/enable-mod_rewrite-in-a-ubuntu-server/">Enabling mod_rewrite</a></li>
<li>A great <a href="http://www.sucka.net/2009/09/ubuntu-command-line-tip-1-%E2%80%93-aliases/">bash aliases</a> tutorial for Ubuntu</li>
<li>Setting up <a href="http://www.armando.ws/2009/05/how-to-set-up-zend_tool-on-windows/comment-page-1/">Zend Tool on Windows</a></li>
<li>The <a href="http://n4.nabble.com/Zend-Framework-Community-f634137.html">Zend Framework Community Forum</a> on Nabble</li>
<li><a href="http://akrabat.com/zend-framework-tutorial/">Getting Started with Zend Framework</a> by Rob Allen</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2010/04/17/from-zero-to-zend-framework-project-in-10-minutes/feed/</wfw:commentRss>
		<slash:comments>9</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 Kendall</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>
]]></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>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 Kendall</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>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/feed/</wfw:commentRss>
		<slash:comments>38</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 Kendall</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>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2008/12/24/conditional-form-validation-with-zend_form/feed/</wfw:commentRss>
		<slash:comments>12</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 Kendall</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>
]]></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>
		<item>
		<title>Dynamic Content on Static Pages using Zend Json and jQuery</title>
		<link>http://www.jeremykendall.net/2008/10/16/dynamic-content-on-static-pages-using-zend-json-and-jquery/</link>
		<comments>http://www.jeremykendall.net/2008/10/16/dynamic-content-on-static-pages-using-zend-json-and-jquery/#comments</comments>
		<pubDate>Thu, 16 Oct 2008 20:48:17 +0000</pubDate>
		<dc:creator>Jeremy Kendall</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.jeremykendall.net/?p=59</guid>
		<description><![CDATA[The Problem
One of the most highly trafficked sites on the intranet where I work is the cafeteria&#8217;s web site.  Employees from all across the enterprise visit daily to see what&#8217;s on the menu.  Maintaining the menu pages on the cafeteria site has been a constant challenge for our content folks.
As the bulk of our intranet [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The Problem</strong></p>
<p>One of the most highly trafficked sites on the intranet where I work is the cafeteria&#8217;s web site.  Employees from all across the enterprise visit daily to see what&#8217;s on the menu.  Maintaining the menu pages on the cafeteria site has been a constant challenge for our content folks.</p>
<p>As the bulk of our intranet is still mostly static (PHP isn&#8217;t even installed on our main intranet box), our content people have to work really hard to keep the menu up-to-date.  The process consists of the cafeteria folks emailing an updated menu over to our content people and our content folks manually updating the menu&#8217;s html.  Since the cafeteria is open seven days a week, that means our content folks have to manage eight separate pages: the cafeteria homepage featuring the current day&#8217;s menu in a side bar and separate menu pages for each day of the week.</p>
<p><strong>The Solution, Almost</strong></p>
<p>The solution to this issue began with a simple Java CRUD app, allowing the cafeteria employees to manage the menu themselves.  The &#8220;Menu Builder&#8221; application spits out an XML document for consumption on the cafeteria website.  During the development process, I extended <a title="Zend Http" href="http://framework.zend.com/manual/en/zend.http.html">Zend_Http_Client</a> and wrote a simple index page to parse the XML for display.  While the PHP solution for displaying the menu was nice, clean, and simple, it turned out to be completely useless.</p>
<p>As I mentioned above, the majority of our intranet is still running on a server without PHP installed.  We&#8217;re working to move away from that server, but the process is slow and painful.  Without the ability to use PHP to serve the daily menu, we had to come up with something else.  AJAX was the obvious choice, but how to deal with the fact that we&#8217;d have to make cross-domain requests in order to retrieve the application&#8217;s XML output?</p>
<p><strong>Cross-Domain JSON with jQuery</strong></p>
<p>After a little digging around, one of my co-workers turned me on to <a title="jQuery" href="http://jquery.com/">jQuery</a> and <a title="JSON with Padding" href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/">JSONP</a>.  As of version 1.2, jQuery provides native support for JSONP, a method of retrieving JSON data across domains.  The implementation can be found in <a title="getJSON" href="http://docs.jquery.com/Ajax/jQuery.getJSON">jQuery.getJSON</a>.</p>
<p>Once the decision was made to utilize jQuery&#8217;s getJSON, I had to come up with a way to convert the menu&#8217;s XML output to JSON.  Since the Menu Builder app was already spitting out XML, there was no way I was going to add a module to the application to support the new JSON requirement.  I needed a simple way to convert XML to JSON, and I didn&#8217;t want to spend any time rolling my own solution.</p>
<p><strong>Zend Framework to the Rescue</strong></p>
<p>Since we&#8217;re already using <a title="Zend Framework" href="http://framework.zend.com/">Zend Framework</a> on our intranet, I decided to look to <a title="Zend Json" href="http://framework.zend.com/manual/en/zend.json.html">Zend Json</a> and see if it could do the job.  Sure enough, there&#8217;s a static <a title="Zend_Json::fromXml()" href="http://framework.zend.com/manual/en/zend.json.xml2json.html">fromXml()</a> method that takes care of the conversion beautifully.</p>
<p>After that, it was fairly quick work to create some JavaScript functions to parse the returned JSON and display it on the cafeteria website.</p>
<p>[Side note: As of ZF 1.6, the <a title="Dojo" href="http://dojotoolkit.org/">Dojo</a> JavaScript library is <a title="Zend Dojo" href="http://framework.zend.com/manual/en/zend.dojo.html">integrated with Zend Framework</a>.  Well before that integration occurred, we made the decision that jQuery would be our library of choice.  That's why I'm using jQuery for this solution rather than Dojo.]</p>
<p><strong>The Code</strong></p>
<p>First is an example of the XML returned from the Menu Builder application.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;menu<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;timeStamp<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Thu Oct 16 13:18:50 CDT 2008<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/timeStamp<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;day<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Thursday<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/day<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;date<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>October 16, 2008<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/date<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meal</span> <span style="color: #000066;">descr</span>=<span style="color: #ff0000;">&quot;Breakfast Feature&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;category</span> <span style="color: #000066;">descr</span>=<span style="color: #ff0000;">&quot;None (will not display to users)&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>French Toast<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>0.45<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Biscuit<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>0.25<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/category<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/meal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meal</span> <span style="color: #000066;">descr</span>=<span style="color: #ff0000;">&quot;Lunch&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;category</span> <span style="color: #000066;">descr</span>=<span style="color: #ff0000;">&quot;Grab &amp;amp; Go&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Garden Vegetables<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>0.89<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/category<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;category</span> <span style="color: #000066;">descr</span>=<span style="color: #ff0000;">&quot;Papa J's Pizza by the Slice&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sausage Egg <span style="color: #ddbb00;">&amp;amp;</span> Cheese Biscuit<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemdescr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.09<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/itemprice<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/category<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/meal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/menu<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Running the above XML through Zend_Json::fromXml() provided me with the JSON representation I needed.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;menu&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;timeStamp&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Thu Oct 16 13:18:50 CDT 2008&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;day&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Thursday&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;date&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;October 16, 2008&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;meal&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #3366CC;">&quot;@attributes&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #3366CC;">&quot;descr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Breakfast Feature&quot;</span>
                <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">&quot;category&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #3366CC;">&quot;@attributes&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #3366CC;">&quot;descr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;None (will not display to users)&quot;</span>
                    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;item&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
                        <span style="color: #009900;">&#123;</span>
                            <span style="color: #3366CC;">&quot;itemdescr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;French Toast&quot;</span><span style="color: #339933;">,</span>
                            <span style="color: #3366CC;">&quot;itemprice&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;0.45&quot;</span>
                        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                        <span style="color: #009900;">&#123;</span>
                            <span style="color: #3366CC;">&quot;itemdescr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Biscuit&quot;</span><span style="color: #339933;">,</span>
                            <span style="color: #3366CC;">&quot;itemprice&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;0.25&quot;</span>
                        <span style="color: #009900;">&#125;</span>
                    <span style="color: #009900;">&#93;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #3366CC;">&quot;@attributes&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #3366CC;">&quot;descr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Lunch&quot;</span>
                <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">&quot;category&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
                    <span style="color: #009900;">&#123;</span>
                        <span style="color: #3366CC;">&quot;@attributes&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                            <span style="color: #3366CC;">&quot;descr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Grab &amp;amp; Go&quot;</span>
                        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                        <span style="color: #3366CC;">&quot;item&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                            <span style="color: #3366CC;">&quot;itemdescr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Garden Vegetables&quot;</span><span style="color: #339933;">,</span>
                            <span style="color: #3366CC;">&quot;itemprice&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;0.89&quot;</span>
                        <span style="color: #009900;">&#125;</span>
                    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                    <span style="color: #009900;">&#123;</span>
                        <span style="color: #3366CC;">&quot;@attributes&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                            <span style="color: #3366CC;">&quot;descr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Papa J's Pizza by the Slice&quot;</span>
                        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                        <span style="color: #3366CC;">&quot;item&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                            <span style="color: #3366CC;">&quot;itemdescr&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Sausage Egg &amp;amp; Cheese Biscuit&quot;</span><span style="color: #339933;">,</span>
                            <span style="color: #3366CC;">&quot;itemprice&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2.09&quot;</span>
                        <span style="color: #009900;">&#125;</span>
                    <span style="color: #009900;">&#125;</span>
                <span style="color: #009900;">&#93;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#93;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As you can see in the samples above, menu items belong to categories and categories belong to meals.  Both meals and categories are described in XML attributes rather than in a description node.</p>
<p>Next is the PHP script that I wrote to get the menu XML, convert it to JSON, and echo it out to the jQuery.getJSON call.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Include required files</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/cafeteria/lib/base.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Set service uri</span>
<span style="color: #000088;">$uri</span>  <span style="color: #339933;">=</span> <span style="color: #000088;">$cafeteriaConfig</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">menu</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">serviceuri</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Valid days of the week</span>
<span style="color: #000088;">$validDays</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'monday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'tuesday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'wednesday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'thursday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'friday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'saturday'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'sunday'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get day from querystring, validate</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'day'</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>
&nbsp;
  <span style="color: #000088;">$getDay</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'day'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$getDay</span><span style="color: #339933;">,</span> <span style="color: #000088;">$validDays</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$day</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$getDay</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$uri</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$uri</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'?day='</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$day</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get xml from cafeteria service</span>
<span style="color: #000088;">$xml</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Encode returned xml as JSON, do not ignore XML attributes</span>
<span style="color: #000088;">$json</span> <span style="color: #339933;">=</span> Zend_Json<span style="color: #339933;">::</span><span style="color: #004000;">fromXml</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$xml</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: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Return response, wrapping response in the requested callback</span>
<span style="color: #666666; font-style: italic;">// @see http://remysharp.com/2007/10/08/what-is-jsonp/</span>
<span style="color: #666666; font-style: italic;">// @see http://docs.jquery.com/Release:jQuery_1.2/Ajax</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'callback'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'('</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$json</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">')'</span><span style="color: #339933;">;</span></pre></div></div>

<p>There are a couple of important things to note in the script above.</p>
<p>First, we keep a lot of code in a base.php file.  This includes <a title="Zend_Loader::registerAutoload()" href="http://framework.zend.com/manual/en/zend.loader.html#zend.loader.load.autoload">Zend_Loader::registerAutoload()</a> and the creation of a <a title="Zend Config" href="http://framework.zend.com/manual/en/zend.config.html">Zend_Config</a> object, among other things, allowing for much <a title="Don't repeat yourself" href="http://en.wikipedia.org/wiki/DRY_code">DRY</a>er code.</p>
<p>Second, you&#8217;ll notice that I&#8217;m using the second, optional parameter for fromXml().  Set to false, fromXml() will return a representation of the XML attributes present in the input.  fromXml() ignores XML attributes by default.</p>
<p>Finally, you can see how the callback name and parentheses are wrapped around the returned JSON before outputting anything back to jQuery.getJSON.  This is required.  Without it, your cross-domain request won&#8217;t return anything at all.</p>
<p>The next bit of code is the JavaScript that parses the returned JSON and outputs the full menu to the web.  Notice that there are two output functions.  This is to allow for two different styles of menu tables: one for the cafeteria homepage (sidebar), and one for the daily menu page (full sized).</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Parses JSON representation of cafeteria menu and returns Menu table</span>
<span style="color: #006600; font-style: italic;">// Requires jQuery</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> menu <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Builds sidebar menu for cafeteria home page</span>
<span style="color: #003366; font-weight: bold;">function</span> outputSidebarMenu<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> day <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">day</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> heading <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;h4&gt;&lt;a href=&quot;'</span> <span style="color: #339933;">+</span> menuLink <span style="color: #339933;">+</span> <span style="color: #3366CC;">'?requestedDay='</span> <span style="color: #339933;">+</span> day.<span style="color: #660066;">toLowerCase</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&quot;&gt;'</span> <span style="color: #339933;">+</span> day <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;'s Menu&lt;/a&gt;&lt;/h4&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	menu <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;table id=&quot;side_datatable&quot;&gt;'</span> <span style="color: #339933;">+</span> getMeals<span style="color: #009900;">&#40;</span>json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">meal</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&lt;/table&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">return</span> timeStampComment<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> heading <span style="color: #339933;">+</span> menu<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Builds table for daily menu page</span>
<span style="color: #003366; font-weight: bold;">function</span> outputDailyMenu<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> day <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">day</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> date <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">date</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> meal <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">meal</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> heading <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;h4 style=&quot;text-align:right; font-weight:normal;&quot;&gt;&lt;span style=&quot;float:left; font-weight:bold;&quot;&gt;'</span> <span style="color: #339933;">+</span> day <span style="color: #339933;">+</span> <span style="color: #3366CC;">'<span style="color: #000099; font-weight: bold;">\'</span>s Menu&lt;/span&gt;'</span> <span style="color: #339933;">+</span> date <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;/h4&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	menu <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;table class=&quot;datatable&quot; width=&quot;400&quot;&gt;'</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #339933;">+</span> getMeals<span style="color: #009900;">&#40;</span>meal<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;/table&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">return</span> timeStampComment<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> heading <span style="color: #339933;">+</span> menu<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Get menu meals</span>
<span style="color: #003366; font-weight: bold;">function</span> getMeals<span style="color: #009900;">&#40;</span>meals<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> mealList <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>meals <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>meals <span style="color: #000066; font-weight: bold;">instanceof</span> Array<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			$.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>meals<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span>meal<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				mealList <span style="color: #339933;">+=</span> buildMealRow<span style="color: #009900;">&#40;</span>meal<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				mealList <span style="color: #339933;">+=</span> getCategories<span style="color: #009900;">&#40;</span>meal.<span style="color: #660066;">category</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: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
			mealList <span style="color: #339933;">+=</span> buildMealRow<span style="color: #009900;">&#40;</span>meals<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			mealList <span style="color: #339933;">+=</span> getCategories<span style="color: #009900;">&#40;</span>meals.<span style="color: #660066;">category</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">return</span> mealList<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Get meal's categories</span>
<span style="color: #003366; font-weight: bold;">function</span> getCategories<span style="color: #009900;">&#40;</span>categories<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> catList <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>categories <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// Is categories an array?</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>categories <span style="color: #000066; font-weight: bold;">instanceof</span> Array<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			$.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>categories<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> category<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				catList <span style="color: #339933;">+=</span> buildCategoryRow<span style="color: #009900;">&#40;</span>category<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			    catList <span style="color: #339933;">+=</span> getItems<span style="color: #009900;">&#40;</span>category.<span style="color: #000066; font-weight: bold;">item</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: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
			catList <span style="color: #339933;">+=</span> buildCategoryRow<span style="color: #009900;">&#40;</span>categories<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			catList <span style="color: #339933;">+=</span> getItems<span style="color: #009900;">&#40;</span>categories.<span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">return</span> catList<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Get category's items</span>
<span style="color: #003366; font-weight: bold;">function</span> getItems<span style="color: #009900;">&#40;</span>items<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> itemList <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
	<span style="color: #006600; font-style: italic;">// Is items an array?</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>items <span style="color: #000066; font-weight: bold;">instanceof</span> Array<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		$.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>items<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			itemList <span style="color: #339933;">+=</span> buildItemRow<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</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: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		itemList <span style="color: #339933;">+=</span> buildItemRow<span style="color: #009900;">&#40;</span>items<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">return</span> itemList<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Build individual meal's table row</span>
<span style="color: #003366; font-weight: bold;">function</span> buildMealRow<span style="color: #009900;">&#40;</span>meal<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> descr <span style="color: #339933;">=</span> meal<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'@attributes'</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">descr</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> mealRow <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;tr&gt;&lt;th colspan=&quot;2&quot;&gt;'</span> <span style="color: #339933;">+</span> descr <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;/th&gt;&lt;/tr&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">return</span> mealRow<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Build individual category's table row</span>
<span style="color: #003366; font-weight: bold;">function</span> buildCategoryRow<span style="color: #009900;">&#40;</span>category<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> catRow <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>category <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> descr <span style="color: #339933;">=</span> category<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'@attributes'</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">descr</span><span style="color: #339933;">;</span>
		<span style="color: #006600; font-style: italic;">// Do not display the 'None' category</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>descr.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/None/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			catRow <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;tr class=&quot;title&quot;&gt;&lt;td colspan=&quot;2&quot;&gt;'</span> <span style="color: #339933;">+</span> descr <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;/td&gt;&lt;/tr&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">return</span> catRow<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Build individual item's table row</span>
<span style="color: #003366; font-weight: bold;">function</span> buildItemRow<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> itemRow <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span> <span style="color: #339933;">!=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
		<span style="color: #003366; font-weight: bold;">var</span> itemDescr <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">itemdescr</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> itemPrice <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">itemprice</span><span style="color: #339933;">;</span>
		itemRow <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;tr&gt;&lt;td&gt;'</span> <span style="color: #339933;">+</span> itemDescr <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&lt;/td&gt;&lt;td&gt;$'</span> <span style="color: #339933;">+</span> itemPrice <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;/td&gt;&lt;/tr&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">return</span> itemRow<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Update Cafeteria Daily Menu page title with &quot;[day]'s Menu&quot;</span>
<span style="color: #003366; font-weight: bold;">function</span> updatePageTitle<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// Get day to use in page title</span>
    <span style="color: #003366; font-weight: bold;">var</span> titleDay <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">day</span><span style="color: #339933;">;</span>
    <span style="color: #006600; font-style: italic;">// Append day to page title</span>
    document.<span style="color: #660066;">title</span> <span style="color: #339933;">=</span> document.<span style="color: #660066;">title</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">' | '</span> <span style="color: #339933;">+</span> titleDay <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;'s Menu&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Output html comment with note on when menu was last cached for troubleshooting</span>
<span style="color: #006600; font-style: italic;">// and debugging</span>
<span style="color: #003366; font-weight: bold;">function</span> timeStampComment<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	  <span style="color: #003366; font-weight: bold;">var</span> day <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">day</span><span style="color: #339933;">;</span>
	  <span style="color: #003366; font-weight: bold;">var</span> cacheTimeStamp <span style="color: #339933;">=</span> json.<span style="color: #660066;">menu</span>.<span style="color: #660066;">timeStamp</span><span style="color: #339933;">;</span>
	  <span style="color: #003366; font-weight: bold;">var</span> timeStampComment <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&lt;!-- &quot;</span> <span style="color: #339933;">+</span> day <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;'s menu last cached: &quot;</span> <span style="color: #339933;">+</span> cacheTimeStamp <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot; --&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
	  <span style="color: #000066; font-weight: bold;">return</span> timeStampComment<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>There&#8217;s one big gotcha in the code above.  Notice how I&#8217;m setting the descr variable in both the buildMenuRow() and the buildCategoryRow() functions.  If you don&#8217;t use array notation with @attributes (['@attributes']), this code will fail in IE.</p>
<p>Finally, let&#8217;s take a look at how I displayed the menu on the cafeteria home page and on the daily menu page.</p>
<p>This first snippet displays the sidebar menu on the cafeteria homepage.  Since the homepage always displays the current day&#8217;s menu, the only parameter that I&#8217;m passing with the querystring is the required callback.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// URL to menu display page</span>
    <span style="color: #003366; font-weight: bold;">var</span> menuLink <span style="color: #339933;">=</span> <span style="color: #3366CC;">'http://www.example.com/cafeteria/dailyMenu.shtml'</span><span style="color: #339933;">;</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: #006600; font-style: italic;">// Get JSON representation of cafeteria menu for today</span>
        $.<span style="color: #660066;">getJSON</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;http://www.cross-domain-example.com/service/cafeteria/json.php?callback=cafeteriaMenu&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// Build html menu table</span>
            <span style="color: #003366; font-weight: bold;">var</span> content <span style="color: #339933;">=</span> outputSidebarMenu<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #006600; font-style: italic;">// Add table to .sidebarMenu div</span>
            $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.sidebarMenu&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>content<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></pre></div></div>

<p>The last snippet displays the full sized menu on the daily menu page.  Since I only want a single daily menu page, rather than a page for each day of the week, I had to have some way to grab a &#8220;requestedDay&#8221; parameter from the querystring.  The jQuery <a title="Query String Object plugin" href="http://plugins.jquery.com/project/query-object">Query String Object plugin</a> solved that problem perfectly.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Menu display requires jQuery and jQuery querystring plugin (jQuery.query.js)</span>
    $<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: #006600; font-style: italic;">// JSON service URL</span>
        <span style="color: #003366; font-weight: bold;">var</span> jsonUrl <span style="color: #339933;">=</span> <span style="color: #3366CC;">'http://www.cross-domain-example.com/service/cafeteria/json.php?callback=?'</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// Get requested day from QueryString</span>
        <span style="color: #006600; font-style: italic;">// @see http://plugins.jquery.com/project/query-object</span>
        <span style="color: #003366; font-weight: bold;">var</span> reqDay <span style="color: #339933;">=</span> $.<span style="color: #660066;">query</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'requestedDay'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        jsonUrl <span style="color: #339933;">=</span> jsonUrl <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&amp;day='</span> <span style="color: #339933;">+</span> reqDay.<span style="color: #660066;">toLowerCase</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;">// Get JSON representation of cafeteria menu for today            </span>
        $.<span style="color: #660066;">getJSON</span><span style="color: #009900;">&#40;</span>jsonUrl<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// Add &quot;[day]'s Menu&quot; to page title</span>
            updatePageTitle<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// Build html menu table</span>
            <span style="color: #003366; font-weight: bold;">var</span> content <span style="color: #339933;">=</span> outputDailyMenu<span style="color: #009900;">&#40;</span>json<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// Add table to #menuBuilder div</span>
            $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#menuBuilder&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>content<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;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Wrapping Up</strong></p>
<p>When you&#8217;re in a situation where you can&#8217;t use PHP (or your programming language of choice) to display dynamic content, AJAX can be an excellent solution.  With the right tools, good documentation, and a little time spent on Google, it&#8217;s relatively simple to overcome the limitations of your environment and deliver rich, up-to-date content to your users.  Combining Zend Framework, the jQuery JavaScript Library, and JSONP made for a nice, lightweight solution to the cafeteria menu problem, saving my clients and co-workers a lot of time and effort they can now expend elsewhere.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2008/10/16/dynamic-content-on-static-pages-using-zend-json-and-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image Upload Issues with Internet Explorer and image/pjpeg</title>
		<link>http://www.jeremykendall.net/2008/02/24/image-upload-issues-with-internet-explorer-and-imagepjpeg-2/</link>
		<comments>http://www.jeremykendall.net/2008/02/24/image-upload-issues-with-internet-explorer-and-imagepjpeg-2/#comments</comments>
		<pubDate>Sun, 24 Feb 2008 16:50:49 +0000</pubDate>
		<dc:creator>Jeremy Kendall</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[jpeg]]></category>
		<category><![CDATA[upload]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://dev.jeremykendall.net/wp/?p=4</guid>
		<description><![CDATA[I&#8217;m working on a project that uses Zend_Gdata, specifically Zend_Gdata_Photos, to manage photos in Google&#8217;s Picasa Web Albums.  When the application went into its testing phase, the image upload functionality began to throw exceptions.  While I could upload photos to Picasa without issue, my business partner John couldn&#8217;t upload any photos at all. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on a project that uses <a href="http://framework.zend.com/manual/en/zend.gdata.html">Zend_Gdata</a>, specifically <a href="http://framework.zend.com/manual/en/zend.gdata.photos.html">Zend_Gdata_Photos</a>, to manage photos in Google&#8217;s <a href="http://picasaweb.google.com/">Picasa Web Albums</a>.  When the application went into its testing phase, the image upload functionality began to throw exceptions.  While I could upload photos to Picasa without issue, my business partner <a href="http://www.jandbchildress.com/">John</a> couldn&#8217;t upload any photos at all.  The application kept throwing the following error:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Error Message: Exception Message: Expected response code 200, got 400</pre></div></div>

<p>Since the app worked fine for me, the issue didn&#8217;t seem to be with the code.  After some frustrating, unproductive troubleshooting, I finally built a file upload mockup and ran the $_FILES array through <a href="http://framework.zend.com/manual/en/zend.debug.html">Zend_Debug::dump()</a>.  I discovered that while Firefox reports the MIME type of a jpg as &#8220;image/jpeg&#8221;, Internet Explorer reports the MIME type as &#8220;image/pjpeg.&#8221;  Thanks a lot, Redmond.</p>
<p>As it turned out, the problem occurred when I tried to set the upload content type to &#8220;image/pjpeg&#8221;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$fd</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_service<span style="color: #339933;">-&gt;</span><span style="color: #004000;">newMediaFileSource</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;tmp_name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$fd</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContentType</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;type&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>I resolved the issue by adding a test for the pjpeg MIME type before setting the content type.  The new code looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/** Resolves issue where IE changes jpg MIME type to image/pjpeg, breaking upload */</span>
<span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;type&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;type&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #0000ff;">&quot;image/pjpeg&quot;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">&quot;image/jpeg&quot;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;type&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$fd</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_service<span style="color: #339933;">-&gt;</span><span style="color: #004000;">newMediaFileSource</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;tmp_name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$fd</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContentType</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;type&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The code snippets above come from an image upload helper method that I built (borrowing heavily from <a href="http://www.corywiles.com/">Cory Wiles</a>) to make working with Zend_Gdata_Photos a little easier.</p>
<p>If you&#8217;re having similar problems uploading images, regardless of the method that you&#8217;re using, check that MIME type and see if that&#8217;s not the issue.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremykendall.net/2008/02/24/image-upload-issues-with-internet-explorer-and-imagepjpeg-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
