<?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>Ezzatron &#187; IT</title>
	<atom:link href="http://ezzatron.com/category/it/feed/" rel="self" type="application/rss+xml" />
	<link>http://ezzatron.com</link>
	<description>Bringing together the fine arts of programming and death metal.</description>
	<lastBuildDate>Fri, 19 Nov 2010 06:37:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Filesystem fixtures for symfony</title>
		<link>http://ezzatron.com/2010/11/19/filesystem-fixtures-for-symfony/</link>
		<comments>http://ezzatron.com/2010/11/19/filesystem-fixtures-for-symfony/#comments</comments>
		<pubDate>Fri, 19 Nov 2010 06:27:16 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[environment]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[filesystem]]></category>
		<category><![CDATA[fixtures]]></category>
		<category><![CDATA[initial]]></category>
		<category><![CDATA[prod]]></category>
		<category><![CDATA[system]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=349</guid>
		<description><![CDATA[This is just a quick post to provide a landing page for a new symfony plugin I&#8217;ve created: sfFilesystemFixturesPlugin. I&#8217;m not going to explain the plugin in detail here, all the information you need is on the plugin&#8217;s readme page. In a nutshell, the plugin lets you populate a symfony project with filesystem data like [...]]]></description>
			<content:encoded><![CDATA[<p><a title="symfony | Web PHP Framework" href="http://www.symfony-project.org/"></a><a href="http://www.symfony-project.org/"><img class="alignnone" title="symfony" src="http://www.symfony-project.org/downloads/logos/symfony.gif" alt="" width="448" height="122" /></a></p>
<p>This is just a quick post to provide a landing page for a new symfony plugin I&#8217;ve created: <a title="sfFilesystemFixturesPlugin" href="http://www.symfony-project.org/plugins/sfFilesystemFixturesPlugin">sfFilesystemFixturesPlugin</a>. I&#8217;m not going to explain the plugin in detail here, all the information you need is on the plugin&#8217;s <a title="sfFilesystemFixturesPlugin readme page" href="http://www.symfony-project.org/plugins/sfFilesystemFixturesPlugin?tab=plugin_readme">readme page</a>.</p>
<p>In a nutshell, the plugin lets you populate a symfony project with filesystem data like images and thumbnails in much the same way as you would populate a database using regular symfony fixtures.</p>
<p>Feel free to leave questions, comments, and bug reports in the comments.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2010%2F11%2F19%2Ffilesystem-fixtures-for-symfony%2F';
  addthis_title  = 'Filesystem+fixtures+for+symfony';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2010/11/19/filesystem-fixtures-for-symfony/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Per-environment fixtures in symfony</title>
		<link>http://ezzatron.com/2010/06/10/per-environment-fixtures-in-symfony/</link>
		<comments>http://ezzatron.com/2010/06/10/per-environment-fixtures-in-symfony/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 14:50:53 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[env]]></category>
		<category><![CDATA[environment]]></category>
		<category><![CDATA[fixture]]></category>
		<category><![CDATA[fixtures]]></category>
		<category><![CDATA[initial]]></category>
		<category><![CDATA[prod]]></category>
		<category><![CDATA[production]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[yaml]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=311</guid>
		<description><![CDATA[UPDATE: I have now packaged this script into a symfony plugin called sfEnvironmentFixturesPlugin. Check it out and hit the &#8216;I use it&#8217; link if you find it useful! Feel free to leave questions, comments, and bug reports in the comments. &#8230; Symfony&#8216;s fixtures are a great way to set up initial data and/or test data [...]]]></description>
			<content:encoded><![CDATA[<p><a title="symfony | Web PHP Framework" href="http://www.symfony-project.org/"></a><a href="http://www.symfony-project.org/"><img class="alignnone" title="symfony" src="http://www.symfony-project.org/downloads/logos/symfony.gif" alt="" width="448" height="122" /></a></p>
<p><strong>UPDATE:</strong></p>
<p>I have now packaged this script into a symfony plugin called <a href="http://www.symfony-project.org/plugins/sfEnvironmentFixturesPlugin">sfEnvironmentFixturesPlugin</a>. Check it out and hit the &#8216;I use it&#8217; link if you find it useful!</p>
<p>Feel free to leave questions, comments, and bug reports in the comments.</p>
<p>&#8230;</p>
<p><a title="symfony | Web PHP Framework" href="http://www.symfony-project.org/">Symfony</a>&#8216;s <a title="Practical symfony | Day 3: The Data Model | symfony | Web PHP Framework" href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/03#chapter_03_the_initial_data">fixtures</a> are a great way to set up initial data and/or test data for a system. Whenever I create a new symfony project however, I always find myself wishing there was an easy way to specify which fixtures contain data required for production systems (the &#8216;initial&#8217; data) and which contain data that I only need when developing (the &#8216;test&#8217; data).</p>
<p>I recently started such a project and came across a reasonably elegant solution. With a simple <a title="The Official YAML Web Site" href="http://www.yaml.org/">YAML</a> file placed in your fixtures directory, you too can have such a set up if so desired.</p>
<p><span id="more-311"></span>The beauty of symfony&#8217;s fixtures (at least in the case of <a title="Doctrine - PHP Object Persistence Libraries and More" href="http://www.doctrine-project.org/">Doctrine</a>, not sure about Propel) is that they are interpreted as <a title="PHP: Hypertext Preprocessor" href="http://www.php.net/">PHP</a>. This allows us to do nice things like generating large amounts of test data by using iteration instead of writing out each entry individually. It also allows us to exploit it with a small script that can pull in other fixture files.</p>
<p>And now for the script itself:</p>
<p><strong>byEnv.yml:</strong></p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<br />
<span style="color: #000088;">$_currentEnv</span> <span style="color: #339933;">=</span> sfApplicationConfiguration<span style="color: #339933;">::</span><span style="color: #004000;">getActive</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEnvironment</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$_envFixturesDir</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_data_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/fixtures_'</span><span style="color: #339933;">.</span><span style="color: #000088;">$_currentEnv</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_dir"><span style="color: #990000;">is_dir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_envFixturesDir</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; taskMessage<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Loading data fixtures for environment <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #006699; font-weight: bold;">$_currentEnv</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; taskMessage<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Loading data fixtures from <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #006699; font-weight: bold;">$_envFixturesDir</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span>findFixtures<span style="color: #009900;">&#40;</span><span style="color: #000088;">$_envFixturesDir</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$_envFixture</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_envFixture</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009933; font-style: italic;">/**<br />
* @return array<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">function</span> findFixtures<span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000088;">$fixtures</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/is_dir"><span style="color: #990000;">is_dir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/scandir"><span style="color: #990000;">scandir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$fixture</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$subPath</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$path</span>/<span style="color: #006699; font-weight: bold;">$fixture</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/substr"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fixture</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'.'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_dir"><span style="color: #990000;">is_dir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$subPath</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; findFixtures<span style="color: #009900;">&#40;</span><span style="color: #000088;">$subPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/strtolower"><span style="color: #990000;">strtolower</span></a><span style="color: #009900;">&#40;</span><a href="http://www.php.net/substr"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fixture</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'.yml'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000088;">$fixtures</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$subPath</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$fixtures</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> taskMessage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000088;">$maxLineSize</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/ctype_digit"><span style="color: #990000;">ctype_digit</span></a><span style="color: #009900;">&#40;</span><a href="http://www.php.net/trim"><span style="color: #990000;">trim</span></a><span style="color: #009900;">&#40;</span><a href="http://www.php.net/shell_exec"><span style="color: #990000;">shell_exec</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tput cols 2&gt;&amp;1'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #009900;">&#40;</span>integer<span style="color: #009900;">&#41;</span> <a href="http://www.php.net/shell_exec"><span style="color: #990000;">shell_exec</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tput cols'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #cc66cc;">78</span><span style="color: #339933;">;</span><br />
&nbsp; <br />
&nbsp; sfApplicationConfiguration<span style="color: #339933;">::</span><span style="color: #004000;">getActive</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notify</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">new</span> sfEvent<span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'command.log'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&gt;&gt; doctrine &nbsp;'</span><span style="color: #339933;">.</span>messageExcerpt<span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #000088;">$maxLineSize</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">12</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009933; font-style: italic;">/**<br />
* @return string<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">function</span> messageExcerpt<span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #000088;">$size</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">66</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/strlen"><span style="color: #990000;">strlen</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$size</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$text</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000088;">$subsize</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/floor"><span style="color: #990000;">floor</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$size</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">return</span> <a href="http://www.php.net/substr"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$subsize</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'...'</span><span style="color: #339933;">.</span><a href="http://www.php.net/substr"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #000088;">$subsize</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Place this script in your fixtures directory, then create a <strong>fixtures_dev</strong> sub-directory in your project&#8217;s <strong>data</strong> directory. Any fixtures placed in this directory will be included when you run the relevant symfony task using the <strong>dev</strong> environment.</p>
<p>You can use this system for any environment, including custom ones. For example, to load the fixtures needed for a production environment you could run the following:</p>
<pre lang="text">symfony doctrine:data-load --env=prod</pre>
<p>To load initial data, and test data stored in the development fixtures folder:</p>
<pre lang="text">symfony doctrine:data-load --env=dev</pre>
<p>To load initial data, and special data for the foo environment:</p>
<pre lang="text">symfony doctrine:data-load --env=foo</pre>
<p><strong>IMPORTANT!</strong></p>
<p>Be VERY careful when using this in a production environment. The default environment for the <strong>doctrine:data-load</strong> task is <strong>dev</strong>. This means if you don&#8217;t specify an environment, all your test data will be loaded.</p>
<p>The script includes some nice features too. It will search through directories recursively, just like the original fixture loading system, so you can organise your fixtures how you please. The script will also output messages to the console to notify you of which directories have actually been processed.</p>
<p>Hopefully someone will find this as useful as I do. Enjoy!</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2010%2F06%2F10%2Fper-environment-fixtures-in-symfony%2F';
  addthis_title  = 'Per-environment+fixtures+in+symfony';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2010/06/10/per-environment-fixtures-in-symfony/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Why I avoid using Subversion externals</title>
		<link>http://ezzatron.com/2010/04/29/why-i-avoid-using-subversion-externals/</link>
		<comments>http://ezzatron.com/2010/04/29/why-i-avoid-using-subversion-externals/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 01:11:10 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[externals]]></category>
		<category><![CDATA[revision control]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=293</guid>
		<description><![CDATA[I&#8217;ve been using Subversion for a few years now and one of the tricks I&#8217;ve picked up on is avoiding the use of externals like the plague. I first stumbled upon this idea when including a large code base as an external in one of my own projects. Subversion operations on the project in question [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using <a title="Subversion" href="http://subversion.tigris.org/">Subversion</a> for a few years now and one of the tricks I&#8217;ve picked up on is avoiding the use of <a title="Externals Definitions" href="http://svnbook.red-bean.com/nightly/en/svn.advanced.externals.html">externals</a> like the plague. I first stumbled upon this idea when including a large code base as an external in one of my own projects.</p>
<p>Subversion operations on the project in question were lightning fast. I could make a code change, and the <a title="svn commit" href="http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.commit.html">commit</a> operation would take only the blink of an eye. Likewise, <a title="svn update" href="http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.update.html">updating</a> other working copies with my changes was similarly instantaneous.</p>
<p>Then I included a large dependency as a Subversion external. From that point on, Subversion operations were very sluggish and it soon became a chore to update my working copies.</p>
<p><span id="more-293"></span>It quickly occurred to me that it was the externals definition that was the cause of the slowdown. Essentially, including another working copy as an external causes a huge amount of excess work for Subversion each time you perform an operation, particularly updates.</p>
<h2>The problem</h2>
<p>When you run an update, Subversion will contact the server hosting the external repository, asking for any updates, downloading them, and applying them as necessary. If you watch your Subversion client when you do this, it takes a good few seconds for Subversion to make the initial connection even when there are no changes. In addition to this, if you have a large number of directories and files in your external, the time it takes to traverse these can also have a sizeable impact on Subversion&#8217;s responsiveness.</p>
<p>So what are the benefits to externals?</p>
<p>Well, for one thing, if a third party wants to include your code in their own project, they ensure that all the dependencies are automatically satisfied upon checkout. But if you&#8217;re not writing a framework or some other kind of software library intended to be included within another system, then this is not such an important point. In fact if you&#8217;re like me and usually make one-time projects, the only time you would even use externals is during development, since it&#8217;s generally considered best practice not to use Subversion in a production environment at all.</p>
<h2>The solution</h2>
<p>Here is what I do in my projects to keep Subversion responsive and fast. I would typically have a directory for my dependencies; let&#8217;s use the symfony convention and call it lib/vendor:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">project/<br />
&nbsp; lib/<br />
&nbsp; &nbsp; vendor/<br />
&nbsp; &nbsp; &nbsp; software_library_1/<br />
&nbsp; &nbsp; &nbsp; software_library_2/</div></div>
<p>In a typical Subversion externals situation you might set the following for the svn:externals property of the vendor directory:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">software_library_1 svn://software.example.com/library_1/branches/version_1_0<br />
software_library_2 http://svn.software.example.org/library_2/trunk</div></div>
<p>Instead of doing the above, I would simply set the svn:ignore property of the vendor directory by running the following command (from the root of the project):</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">svn propset svn:ignore &quot;*&quot; lib/vendor</div></div>
<p>&#8230;and then run the following commands from the root of the project to create the individual working copies for each dependency:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">svn co svn://software.example.com/library_1/branches/version_1_0 lib/vendor/software_library_1<br />
svn co http://svn.software.example.org/library_2/trunk lib/vendor/software_library_2</div></div>
<p>The end result is largely the same, except that Subversion will completely ignore your dependencies when performing an update, resulting in a drastically reduced amount of time needed to perform the operation.</p>
<p>Of course there is a slight disadvantage here, in that you must manually update all your dependencies when required. Realistically, this is not a problem most of the time unless you are including a software library that undergoes rapid changes. With that said, I usually write a small script to handle the work for me, like so (example in PHP):</p>
<p><strong>update_repos.php:</strong></p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<br />
<a href="http://www.php.net/set_time_limit"><span style="color: #990000;">set_time_limit</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<a href="http://www.php.net/define"><span style="color: #990000;">define</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SVN_CMD'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'svn'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/dirname"><span style="color: #990000;">dirname</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/repos.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$return_var</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$repositories</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$repository</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <a href="http://www.php.net/list"><span style="color: #990000;">list</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #339933;">,</span> <span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$repository</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/dirname"><span style="color: #990000;">dirname</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$path</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/file_exists"><span style="color: #990000;">file_exists</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <a href="http://www.php.net/mkdir"><span style="color: #990000;">mkdir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/is_dir"><span style="color: #990000;">is_dir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'creation of WC directory failed'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>dir_is_empty<span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$cmds</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; SVN_CMD<span style="color: #339933;">.</span><span style="color: #0000ff;">' revert -R '</span><span style="color: #339933;">.</span><a href="http://www.php.net/escapeshellarg"><span style="color: #990000;">escapeshellarg</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; SVN_CMD<span style="color: #339933;">.</span><span style="color: #0000ff;">' up '</span><span style="color: #339933;">.</span><a href="http://www.php.net/escapeshellarg"><span style="color: #990000;">escapeshellarg</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #b1b100;">else</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$cmds</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; SVN_CMD<span style="color: #339933;">.</span><span style="color: #0000ff;">' co '</span><span style="color: #339933;">.</span><a href="http://www.php.net/escapeshellarg"><span style="color: #990000;">escapeshellarg</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">.</span><a href="http://www.php.net/escapeshellarg"><span style="color: #990000;">escapeshellarg</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmds</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$cmd</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.php.net/passthru"><span style="color: #990000;">passthru</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmd</span><span style="color: #339933;">,</span> <span style="color: #000088;">$return_var</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$return_var</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'execution of SVN command failed'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009933; font-style: italic;">/**<br />
* @return boolean<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">function</span> dir_is_empty<span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/scandir"><span style="color: #990000;">scandir</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$item</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'.'</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$item</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'..'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p><strong>repos.php:</strong></p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<br />
<span style="color: #000088;">$repositories</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><br />
<span style="color: #009900;">&#40;</span><br />
&nbsp; <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lib/vendor/software_library_1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'svn://software.example.com/library_1/branches/version_1_0'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lib/vendor/software_library_2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'http://svn.software.example.org/library_2/trunk'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Place these two files in the root of your project, configure repos.php and you&#8217;re all set. You&#8217;ll never need to use an externals definition again! Well, maybe&#8230; <img src='http://ezzatron.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2010%2F04%2F29%2Fwhy-i-avoid-using-subversion-externals%2F';
  addthis_title  = 'Why+I+avoid+using+Subversion+externals';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2010/04/29/why-i-avoid-using-subversion-externals/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Creating web thumbnails with PHP Imagick</title>
		<link>http://ezzatron.com/2010/03/17/creating-web-thumbnails-with-php-imagick/</link>
		<comments>http://ezzatron.com/2010/03/17/creating-web-thumbnails-with-php-imagick/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 00:13:25 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[aspect]]></category>
		<category><![CDATA[BMP]]></category>
		<category><![CDATA[CMYK]]></category>
		<category><![CDATA[color]]></category>
		<category><![CDATA[colour]]></category>
		<category><![CDATA[format]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[ICC]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[ImageMagick]]></category>
		<category><![CDATA[Imagick]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[JPEG]]></category>
		<category><![CDATA[JPG]]></category>
		<category><![CDATA[maintain]]></category>
		<category><![CDATA[PNG]]></category>
		<category><![CDATA[profile]]></category>
		<category><![CDATA[ratio]]></category>
		<category><![CDATA[resize]]></category>
		<category><![CDATA[RGB]]></category>
		<category><![CDATA[sRGB]]></category>
		<category><![CDATA[thumbnail]]></category>
		<category><![CDATA[thumbnailing]]></category>
		<category><![CDATA[TIF]]></category>
		<category><![CDATA[TIFF]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=283</guid>
		<description><![CDATA[It may seem like a subject that has been done to death, but creating thumbnails from images can be a complex and frustrating task, especially when you&#8217;re faced with a wide variety of formats in your source images. The script below uses PHP&#8217;s Imagick extension to create a thumbnail from pretty much any source image. [...]]]></description>
			<content:encoded><![CDATA[<p>It may seem like a subject that has been done to death, but creating thumbnails from images can be a complex and frustrating task, especially when you&#8217;re faced with a wide variety of formats in your source images.</p>
<p>The script below uses PHP&#8217;s <a title="PHP: ImageMagick - Manual" href="http://php.net/manual/en/book.imagick.php">Imagick extension</a> to create a thumbnail from pretty much any source image. It can handle RGB &amp; CMYK images, TIFFs, PNGs, JPEGs, GIFs, BMPs and just about any other format in just about any size, and it can also handle images with embedded colour profiles (this is very helpful when converting images created in Adobe software).</p>
<p><span id="more-283"></span></p>
<p>You&#8217;ll firstly need to grab the standard <a title="sRGB profiles" href="http://www.color.org/srgbprofiles.xalter">sRGB colour profile</a> from the <a title="International Color Consortium" href="http://www.color.org/">International Color Consortium</a> (ICC) website. Place this somewhere accessible to your script and you&#8217;re ready to go.</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// the location of your image</span><br />
<span style="color: #000088;">$imagePath</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/path/to/source_image'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// these are treated as maximums and aspect ratio is maintained</span><br />
<span style="color: #000088;">$thumbnailWidth</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$thumbnailHeight</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// path to the sRGB ICC profile</span><br />
<span style="color: #000088;">$srgbPath</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/path/to/sRGB_v4_ICC_preference.icc'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// load the original image</span><br />
<span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Imagick<span style="color: #009900;">&#40;</span><span style="color: #000088;">$imagePath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// get the original dimensions</span><br />
<span style="color: #000088;">$width</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getImageWidth</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$height</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getImageHeight</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// set colour profile</span><br />
<span style="color: #666666; font-style: italic;">// this step is necessary even though the profiles are stripped out in the next step to reduce file size</span><br />
<span style="color: #000088;">$srgb</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/file_get_contents"><span style="color: #990000;">file_get_contents</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$srgbPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">profileImage</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'icc'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$srgb</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// strip colour profiles</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">stripImage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// set colorspace</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setImageColorspace</span><span style="color: #009900;">&#40;</span>Imagick<span style="color: #339933;">::</span><span style="color: #004000;">COLORSPACE_SRGB</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// determine which dimension to fit to</span><br />
<span style="color: #000088;">$fitWidth</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$thumbnailWidth</span> <span style="color: #339933;">/</span> <span style="color: #000088;">$width</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$thumbnailHeight</span> <span style="color: #339933;">/</span> <span style="color: #000088;">$height</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// create thumbnail</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">thumbnailImage</span><span style="color: #009900;">&#40;</span><br />
&nbsp; <span style="color: #000088;">$fitWidth</span> ? <span style="color: #000088;">$thumbnailWidth</span> <span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #000088;">$fitWidth</span> ? <span style="color: #cc66cc;">0</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$thumbnailHeight</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// generate a thumbnail filename</span><br />
<span style="color: #000088;">$imagePathParts</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/pathinfo"><span style="color: #990000;">pathinfo</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$imagePath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$thumbnailPath</span> <span style="color: #339933;">=</span><br />
&nbsp; <span style="color: #000088;">$imagePathParts</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'dirname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><br />
&nbsp; <span style="color: #000088;">$imagePathParts</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'filename'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'_'</span><span style="color: #339933;">.</span><br />
&nbsp; <span style="color: #000088;">$thumbnailWidth</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'x'</span><span style="color: #339933;">.</span><span style="color: #000088;">$thumbnailHeight</span><span style="color: #339933;">.</span><br />
&nbsp; <span style="color: #0000ff;">'.jpg'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// save thumbnail and free up memory</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">writeImage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$thumbnailPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clear</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">destroy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2010%2F03%2F17%2Fcreating-web-thumbnails-with-php-imagick%2F';
  addthis_title  = 'Creating+web+thumbnails+with+PHP+Imagick';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2010/03/17/creating-web-thumbnails-with-php-imagick/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Expanding forms with symfony 1.2 and Doctrine</title>
		<link>http://ezzatron.com/2009/12/03/expanding-forms-with-symfony-1-2-and-doctrine/</link>
		<comments>http://ezzatron.com/2009/12/03/expanding-forms-with-symfony-1-2-and-doctrine/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 04:19:32 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[band]]></category>
		<category><![CDATA[degradation]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[dynamic]]></category>
		<category><![CDATA[enhancement]]></category>
		<category><![CDATA[expanding]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[graceful]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[many]]></category>
		<category><![CDATA[member]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[object]]></category>
		<category><![CDATA[one]]></category>
		<category><![CDATA[oriented]]></category>
		<category><![CDATA[progressive]]></category>
		<category><![CDATA[to]]></category>
		<category><![CDATA[validation]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=177</guid>
		<description><![CDATA[I recently started learning how to use the forms system in symfony 1.2 and for the most part I was impressed with its simplicity and flexibility. Unfortunately I was thrown in the deep end somewhat when a project I was working on had a requirement for an &#8220;expanding&#8221; form &#8211; that is, one where a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.symfony-project.org/"><img class="alignnone" title="symfony" src="http://www.symfony-project.org/downloads/logos/symfony.gif" alt="" width="448" height="122" /></a></p>
<p>I recently started learning how to use the <a title="symfony Forms in Action" href="http://www.symfony-project.org/forms/1_2/en/">forms system</a> in <a title="symfony" href="http://www.symfony-project.org/">symfony</a> 1.2 and for the most part I was impressed with its simplicity and flexibility. Unfortunately I was thrown in the deep end somewhat when a project I was working on had a requirement for an &#8220;expanding&#8221; form &#8211; that is, one where a certain section of a form should be able to be repeated as many times as necessary to accommodate the user&#8217;s needs.</p>
<p>In the case of the project in question, the specific situation was an application form where the user could fill out any number of team members involved in their project. Each team member consisted of a name and a role, both free-form text fields. Team members were to be stored in the database, linked to the application in a one to many relationship.</p>
<p>Circumstances conspired that this must be achieved in a single form, so full of confidence in symfony&#8217;s design decisions regarding the forms system, a bit of light Googling revealed the answer &#8211; symfony&#8217;s <a title="Call the expert: Nested forms - A real implementation" href="http://www.symfony-project.org/blog/2008/11/10/call-the-expert-nested-forms-a-real-implementation">embedded forms</a> system. Great, so you just plonk in a few embedded forms and away you go, right? Wrong.</p>
<p>The good news is, I managed to find a solution that satisfied the requirements, <em>eventually</em>. The bad news is that it is not easy, elegant, or particularly reusable.</p>
<p>What follows is a loose guide to implementing such a system. Being a relative newcomer to symfony I cannot guarantee that this is the best way to do things, so tread with caution, and if you think of a better way to achieve the same outcome, please please let me know! Read on if you dare&#8230;<span id="more-177"></span></p>
<h2>Introduction</h2>
<p>I&#8217;m going to assume the following in this guide:</p>
<ul>
<li>You have a solid working knowledge of <a title="symfony" href="http://www.symfony-project.org/">symfony</a>, <a title="PHP: Hypertext Preprocessor" href="http://php.net/">PHP</a> and <a title="Doctrine - PHP Object Relational Mapper" href="http://www.doctrine-project.org/">Doctrine</a>.</li>
<li>You have a blank symfony 1.2 project, set up to use Doctrine rather than Propel (although I&#8217;m sure the same could be achieved with Propel with a bit of tweaking).</li>
<li>You have the symfony executable in your system path or in the root of your project.</li>
<li>You are using a relational database such as MySQL to store your data.</li>
<li>You have entered your database connection details into your <strong>config/databases.yml</strong> file and set up all the appropriate database permissions.</li>
<li>You have completed any web server setup as required to access the project.</li>
<li>You are aware that you need to clear the symfony cache (by running <code class="codecolorer text vibrant"><span class="text">symfony cc</span></code>) when new classes are created and when configuration changes are made.</li>
</ul>
<p>I&#8217;m also going to move fairly quickly as there is a lot to cover, so please feel free to ask for any clarification in the comments and I will update as necessary.</p>
<p>For help with installing and setting up symfony 1.2, check out <a title="Getting Started with symfony" href="http://www.symfony-project.org/getting-started/1_2/en/">Getting started with symfony</a>. I chose to use Doctrine 1.1 for this tutorial, however the version that comes with symfony should also be fine. For instructions on upgrading to Doctrine 1.1 see <a title="Using Doctrine 1.1 with Symfony 1.2" href="http://www.brandonturner.net/blog/2009/05/doctrine11-with-symfony12/">Using Doctrine 1.1 with Symfony 1.2</a>.</p>
<p>You can also see a live demo and get an idea of what we are trying to achieve by visiting <a href="http://expandingform.sf.ezzatron.com/">http://expandingform.sf.ezzatron.com/</a>.</p>
<h2>Step 1: Setting up</h2>
<p>Here is the Doctrine schema we will be using. I went for something a bit more cheery than the above situation, namely bands and band members:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Band:<br />
&nbsp; columns:<br />
&nbsp; &nbsp; name:<br />
&nbsp; &nbsp; &nbsp; type: string(200)<br />
&nbsp; &nbsp; &nbsp; notnull: true<br />
&nbsp; &nbsp; &nbsp; notblank: true<br />
&nbsp; &nbsp; formed: date<br />
<br />
BandMember:<br />
&nbsp; columns:<br />
&nbsp; &nbsp; band_id:<br />
&nbsp; &nbsp; &nbsp; type: integer<br />
&nbsp; &nbsp; &nbsp; notnull: true<br />
&nbsp; &nbsp; name:<br />
&nbsp; &nbsp; &nbsp; type: string(200)<br />
&nbsp; &nbsp; &nbsp; notnull: true<br />
&nbsp; &nbsp; &nbsp; notblank: true<br />
&nbsp; &nbsp; role: string(200)<br />
&nbsp; relations:<br />
&nbsp; &nbsp; Band:<br />
&nbsp; &nbsp; &nbsp; foreignAlias: Members<br />
&nbsp; &nbsp; &nbsp; onUpdate: cascade<br />
&nbsp; &nbsp; &nbsp; onDelete: cascade</div></div>
<p>Place this in your <strong>config/doctrine/schema.yml</strong> file, and then create a data fixture so we have some test data to work with:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Band:<br />
&nbsp; hnd:<br />
&nbsp; &nbsp; name: Hesitate &amp; Die<br />
&nbsp; &nbsp; formed: '2006-06-06'<br />
<br />
BandMember:<br />
&nbsp; andrew:<br />
&nbsp; &nbsp; name: Andrew<br />
&nbsp; &nbsp; role: Guitar<br />
&nbsp; &nbsp; Band: hnd<br />
&nbsp; erin:<br />
&nbsp; &nbsp; name: Erin<br />
&nbsp; &nbsp; role: Bass<br />
&nbsp; &nbsp; Band: hnd<br />
&nbsp; richie:<br />
&nbsp; &nbsp; name: Richie<br />
&nbsp; &nbsp; role: Vocals<br />
&nbsp; &nbsp; Band: hnd<br />
&nbsp; rowan:<br />
&nbsp; &nbsp; name: Rowan<br />
&nbsp; &nbsp; role: Drums<br />
&nbsp; &nbsp; Band: hnd</div></div>
<p>Place the above in <strong>data/fixtures/fixtures.yml</strong> and run:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ symfony doctrine:build-all-reload --no-confirmation</div></div>
<p>This will generate all the model classes and forms we will need, create the database, and populate it with some test data for us. Next we need to create an application, and we&#8217;ll use the standard symfony app name &#8220;frontend&#8221;:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ symfony generate:app --escaping-strategy=on --csrf-secret=randomstring frontend</div></div>
<p>Replacing &#8220;randomstring&#8221; with whatever you like. Now let&#8217;s generate a module from our model classes as a base to start from:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ symfony doctrine:generate-module --non-verbose-templates frontend band Band</div></div>
<p>Now if you visit <strong>http://&lt;project url&gt;/frontend_dev.php/band/edit/id/1</strong> you should be presented with the following:</p>
<p><img class="alignnone size-full wp-image-190" title="Generated band form" src="http://ezzatron.com/wp-content/uploads/2009/12/end_step_1.png" alt="Generated band form" width="450" height="170" /></p>
<p>We now have a basic form for entering band details. Thus concludes step 1. Moving on to&#8230;</p>
<h2>Step 2: Building the form</h2>
<p>OK let&#8217;s dive right in. We are going to embed forms for editing band members inside of the band form itself. To add a single member form you would simply add:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'members'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> BandMemberForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>to our <strong>lib/form/doctrine/BandForm.class.php</strong>&#8216;s <strong>configure()</strong> method. But what we want is to structure the form in such a way that the form data, when posted to the update action, will contain an array of band members. The way to do so in the symfony forms system is to wrap the embedded forms in another form, then embed this wrapper form itself into the main form. Confused? Don&#8217;t worry, everything will become clearer once we actually create the forms.</p>
<p>Firstly, we need to make a small modification to the band member form to allow it to slot into our band form better. The generated form includes a field for the related band ID, which we will not need as all band members will relate to the band represented in the parent band form.</p>
<p>We could modify the <strong>BandMemberForm</strong> class itself, but it&#8217;s possible we may want to use the form outside of a band context, so let&#8217;s harness the power of the forms system and extend the form instead. Create a file at <strong>lib/form/doctrine/EmbeddedBandMemberForm.class.php</strong> with the following class definition (PHP opening tag excluded for brevity):</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> EmbeddedBandMemberForm <span style="color: #000000; font-weight: bold;">extends</span> BandMemberForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'band_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Next, let&#8217;s create the &#8220;container&#8221; form. Create a file at <strong>lib/form/doctrine/BandMembersForm.class.php</strong> containing the following class:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandMembersForm <span style="color: #000000; font-weight: bold;">extends</span> sfForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">3</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedBandMemberForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>This creates three blank forms for inputting band members. Now to actually embed the container form into our main band form, it&#8217;s actually very simple. Simply edit <strong>lib/form/doctrine/BandForm.class.php</strong> so that it looks like the following:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'members'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> BandMembersForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Now when we reload our band form (did you remember to clear your cache?), we will see the following:</p>
<p><img class="alignnone size-full wp-image-195" title="Band form with 3 empty member forms" src="http://ezzatron.com/wp-content/uploads/2009/12/band_with_blank_members.png" alt="Band form with 3 empty member forms" width="450" height="348" /></p>
<p>Looks promising, and that wasn&#8217;t <em>too</em> painful so far, right?</p>
<p>There next obvious step would be displaying the existing band members. We want to be able to see and edit the existing band members and still have the option of inputting new members also. To do this we need to pass the <strong>Band</strong> object to our container form so that it can access the existing members. Let&#8217;s update the container form so that it looks like:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandMembersForm <span style="color: #000000; font-weight: bold;">extends</span> sfForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$band</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Band <span style="color: #000088;">$band</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">band</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$band</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">band</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Members</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$member</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedBandMemberForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$member</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$i</span> <span style="color: #339933;">++;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">3</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedBandMemberForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Now we have to change the main form so that we pass the Band object when we instantiate the container form:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'members'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> BandMembersForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Reloading the form should now show the existing members:</p>
<p><img class="alignnone size-full wp-image-198" title="Band form with existing members" src="http://ezzatron.com/wp-content/uploads/2009/12/band_with_existing_members.png" alt="Band form with existing members" width="450" height="581" /></p>
<p>So now we have a form that can display the band with all of its members and still provide room for new ones. Time for the next step.</p>
<h2>Step 3: Getting the form to save</h2>
<p>Try saving the form without making any changes to the data. You should get validation errors because the band member name is a required field:</p>
<p><img class="alignnone size-full wp-image-202" title="Member names incorrectly required" src="http://ezzatron.com/wp-content/uploads/2009/12/member_name_required.png" alt="Member names incorrectly required" width="433" height="379" /></p>
<p>This won&#8217;t do at all because we want to be able to leave a band member blank and have the system ignore it. We also want to be able to delete an existing member by clearing their name and role. So let&#8217;s remove the requirement for now, and we&#8217;ll add it back in later. Edit your <strong>EmbeddedBandMemberForm</strong> class so that it looks like this:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> EmbeddedBandMemberForm <span style="color: #000000; font-weight: bold;">extends</span> BandMemberForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'band_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</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><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Now when we try to save the form again, we get an exception thrown:</p>
<p><img class="alignnone size-full wp-image-249" title="Database constraint violated" src="http://ezzatron.com/wp-content/uploads/2009/12/constraint_violated.png" alt="Database constraint violated" width="433" height="262" /></p>
<p>As you can see, Doctrine is not happy with us, but why? The answer is that symfony is trying to create new band members from the blank band member forms, but it has no idea which band the new members should belong to. We&#8217;ll deal with this issue shortly, but in the meantime let&#8217;s start by making symfony ignore any band member forms which are left blank.</p>
<p>Firstly, how do we decide if a band member form is &#8220;blank&#8221;? Let&#8217;s write a couple of custom methods in our form classes. Some of this functionality is reusable, so we&#8217;ll place the main body of the code in <strong>lib/form/doctrine/BaseFormDoctrine.class.php</strong> which is the base class for all of our generated forms:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">abstract <span style="color: #000000; font-weight: bold;">class</span> BaseFormDoctrine <span style="color: #000000; font-weight: bold;">extends</span> sfFormDoctrine<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> _formValuesAreBlank<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$fieldNames</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$fieldNames</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$fieldName</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$fieldName</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">formValueIsBlank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$fieldName</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> formValueIsBlank<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$subValue</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">formValueIsBlank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$subValue</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$value</span> ? <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>These two methods essentially traverse an array recursively looking for any non-blank values, and returns false as soon as one is found. The method needs to be recursive because some fields like dates are passed as an array. Now we can write a simple method in our <strong>EmbeddedBandMemberForm</strong> class to check whether the fields that constitute a band member have been filled out:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> EmbeddedBandMemberForm <span style="color: #000000; font-weight: bold;">extends</span> BandMemberForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> formValuesAreBlank<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$fieldNames</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array_diff"><span style="color: #990000;">array_diff</span></a><span style="color: #009900;">&#40;</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'BandMember'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFieldNames</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'band_id'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span>_formValuesAreBlank<span style="color: #009900;">&#40;</span><span style="color: #000088;">$fieldNames</span><span style="color: #339933;">,</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>We are simply grabbing the field names directly from our model class, and excluding the ones we don&#8217;t care about. This is more robust that explicitly specifying <em>name</em> and <em>role</em> as the important fields, as it allows for further fields to be added to the band member form as requirements change.</p>
<p>Now we need to actually change the way the form is processed by overriding some methods in our main band form:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> updateObjectEmbeddedForms<span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span> instanceof EmbeddedBandMemberForm<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$formValues</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>EmbeddedBandMemberForm<span style="color: #339933;">::</span><span style="color: #004000;">formValuesAreBlank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$formValues</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">updateObjectEmbeddedForms</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> saveEmbeddedForms<span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span> instanceof EmbeddedBandMemberForm<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &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;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isModified</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">saveEmbeddedForms</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>These methods doubtless require some explanation. Firstly let&#8217;s look at <strong>updateObjectEmbeddedForms()</strong>. This method uses the custom method we wrote to check whether the band members passed to the form for processing are blank. If a blank band member is encountered, the related form is removed from the forms array to prevent symfony from attempting to update the related band member object.</p>
<p>The next method, <strong>saveEmbeddedForms()</strong> works in tandem with the above. It runs through each of the forms and checks whether the related object has been modified. If an unmodified object is encountered, the related form is once again removed from the forms array to prevent symfony from attempting to save an unmodified object.</p>
<p>OK so now we should be able to save our form without any validation warnings or exceptions cropping up. If you can&#8217;t, it&#8217;s probably time to double check everything, and perhaps clear your cache. On to the next step&#8230;</p>
<h2>Step 4: Adding and deleting members</h2>
<p>Our form now saves without errors, but what does it actually <em>do</em>? Not much at the moment. Let&#8217;s try adding another band member. Ladies and gentlemen, may I present Steven on second guitar!:</p>
<p><img class="alignnone size-full wp-image-210" title="Attempting to add a member" src="http://ezzatron.com/wp-content/uploads/2009/12/adding_a_member_fail.png" alt="Attempting to add a member" width="433" height="301" /></p>
<p>What happens when we save the form? Ah, it seems we have the same issue we encountered before:</p>
<p><img class="alignnone size-full wp-image-249" title="Database constraint violated" src="http://ezzatron.com/wp-content/uploads/2009/12/constraint_violated.png" alt="Database constraint violated" width="433" height="262" /></p>
<p>As we found out in the previous step, this is caused by symfony not knowing to link our new band member to the band we are editing. We can fix this by making a simple change to our <strong>BandForm</strong> class, in the <strong>saveEmbeddedForms()</strong> method:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> saveEmbeddedForms<span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span> instanceof EmbeddedBandMemberForm<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isModified</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Band</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">saveEmbeddedForms</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Now when we try again, the new member is saved correctly and appears in the list of band members as expected:</p>
<p><img class="alignnone size-full wp-image-212" title="New member successfully saved" src="http://ezzatron.com/wp-content/uploads/2009/12/new_member_saved.png" alt="New member successfully saved" width="450" height="638" /></p>
<p>Awesome! We now have 2 guitarists and all the glory that comes with duelling guitar solos. But wait; oh no! Steven has decided to get married and move to Norway! Well, it&#8217;s time to remove him from the band I guess, so let&#8217;s try setting his name and role to blank and see what happens when we save&#8230;</p>
<p>Oh dear, it seems Steven is not keen on leaving without a fight. He still appears in the list of band members. So what&#8217;s happening here? In short, we simply haven&#8217;t told Doctrine to dispose of the unwanted band member yet! Let&#8217;s go ahead and do that now by modifying the <strong>BandForm</strong> class&#8217; <strong>updateObjectEmbeddedForms()</strong> method:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> updateObjectEmbeddedForms<span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span> instanceof EmbeddedBandMemberForm<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$formValues</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>EmbeddedBandMemberForm<span style="color: #339933;">::</span><span style="color: #004000;">formValuesAreBlank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$formValues</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #339933;">-&gt;</span><a href="http://www.php.net/unlink"><span style="color: #990000;">unlink</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Members'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$forms</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">updateObjectEmbeddedForms</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Now we can try again to delete Steven, and it seems to have worked:</p>
<p><img class="alignnone size-full wp-image-224" title="Member successfully deleted" src="http://ezzatron.com/wp-content/uploads/2009/12/member_delete_success.png" alt="Member successfully deleted" width="450" height="580" /></p>
<p>So now we have a fully functional form, which is great! But there are some important things we still need to consider, which leads us to the next step&#8230;</p>
<h2>Step 5: Validation</h2>
<p>That&#8217;s right, you forgot, didn&#8217;t you? Back in step 3 we disabled important validation for the band member form, which means, for example, if you try to enter a band member with a role but no name, you get this nasty validation exception:</p>
<p><img class="alignnone size-full wp-image-225" title="Validation error when saving a band member with only a role" src="http://ezzatron.com/wp-content/uploads/2009/12/validation_error.png" alt="Validation error when saving a band member with only a role" width="433" height="219" /></p>
<p><strong>NOTE:</strong> You may find that you do not encounter this exception, there seems to be a bug somewhere where the &#8220;notblank&#8221; validator we specified in the schema is being ignored. Nevertheless, we still need to prevent blank names from being entered.</p>
<p>We can&#8217;t leave things as they stand, so let&#8217;s create a custom wrapper for the validator schema that we can use to validate band members that have not been left blank. Create a file at <strong>lib/validator/EmbeddedBandMemberValidatorSchema.class.php</strong> and enter this class definition:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> EmbeddedBandMemberValidatorSchema <span style="color: #000000; font-weight: bold;">extends</span> sfValidatorSchema<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$validatorSchema</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>sfValidatorSchema <span style="color: #000088;">$validatorSchema</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$validatorSchema</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doClean<span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>EmbeddedBandMemberForm<span style="color: #339933;">::</span><span style="color: #004000;">formValuesAreBlank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">doClean</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$values</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>All this class does is check whether the passed VALUES<br />
are considered &#8220;blank&#8221; before applying the existing validation rules. This increases robustness by allowing us to keep all of the validation rules defined in the <strong>BandMemberForm</strong> class, and freeing us from having to duplicate their logic in the <strong>EmbeddedBandMemberForm</strong> class.</p>
<p>Now it&#8217;s simply a matter of making a small change to the <strong>EmbeddedBandMemberForm</strong> class&#8217; <strong>configure()</strong> method to allow us to take advantage of our new wrapper class:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> EmbeddedBandMemberForm <span style="color: #000000; font-weight: bold;">extends</span> BandMemberForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <a href="http://www.php.net/unset"><span style="color: #990000;">unset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'band_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedBandMemberValidatorSchema<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>With those changes made, we can try again to save a band member with only a role and this time we are presented with the appropriate form errors:</p>
<p><img class="alignnone size-full wp-image-226" title="Form validation working correctly" src="http://ezzatron.com/wp-content/uploads/2009/12/form_errors_working.png" alt="Form validation working correctly" width="433" height="236" /></p>
<p>OK, that&#8217;s validation taken care of, let&#8217;s make some usability improvements.</p>
<h2>Step 6: Usability</h2>
<p>We&#8217;re going to add extra functionality to our form for users with JavaScript support, namely the ability to add additional spaces for band members without the need to save the form. What&#8217;s more we&#8217;re going to do it without preventing non-JavaScript enabled users from using the form. This is known as <em>progressive enhancement</em> and is generally considered a best-practice in web development.</p>
<p>The first thing we need to do is set up an action to render the additional band member forms so that we can fetch them via an AJAX call. Open up your <strong>apps/frontend/modules/band/actions/actions.class.php</strong> file and add the following method:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> bandActions <span style="color: #000000; font-weight: bold;">extends</span> sfActions<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeMemberForm<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isXmlHttpRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'count'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> BandForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNumMembers</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$count</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">member</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'members'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$count</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLayout</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>The template for this action is very simple. Create a file at <strong>apps/frontend/modules/band/templates/memberFormSuccess.php</strong> with the following contents:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$sf_data</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRaw</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'member'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderRow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<p>You may have noticed the call to <strong>BandForm::setNumMembers()</strong> in the above action. We still need to add this method, so let&#8217;s do that now. Edit your <strong>BandForm</strong> class and add the following method definition:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setNumMembers<span style="color: #009900;">&#40;</span><span style="color: #000088;">$numMembers</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'members'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> BandMembersForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #339933;">,</span> <span style="color: #000088;">$numMembers</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>This in turn means a change to the <strong>BandMembersForm</strong> class, which should be edited to look like this:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandMembersForm <span style="color: #000000; font-weight: bold;">extends</span> sfForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$band</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Band <span style="color: #000088;">$band</span><span style="color: #339933;">,</span> <span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">band</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$band</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><a href="http://www.php.net/count"><span style="color: #990000;">count</span></a> <span style="color: #339933;">=</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">band</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Members</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$member</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedBandMemberForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$member</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$i</span> <span style="color: #339933;">++;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/max"><span style="color: #990000;">max</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> EmbeddedBandMemberForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>What the above changes do are allow us to insert extra blank band members as we please. We then use this to recreate the &#8220;extra&#8221; band member form exactly as it would appear if it were rendered as part of the whole form.</p>
<p>All that is left to do is create the AJAX handler and some unobtrusive JavaScript to fetch and insert the new member form. Open <strong>apps/frontend/modules/band/templates/_form.php</strong> and update the contents to the following:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> use_helper<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Javascript'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span> include_stylesheets_for_form<span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span> include_javascripts_for_form<span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
<br />
&lt;form action=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'band/'</span><span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isNew</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">'create'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">'update'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</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;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isNew</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">'?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; method=&quot;post&quot; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isMultipart</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> and <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">'enctype=&quot;multipart/form-data&quot; '</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&gt;<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</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;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isNew</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&lt;input type=&quot;hidden&quot; name=&quot;sf_method&quot; value=&quot;put&quot; /&gt;<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; &lt;table id=&quot;band&quot;&gt;<br />
&nbsp; &nbsp; &lt;tfoot&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;tr&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;td colspan=&quot;2&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;noscript&gt;&lt;p&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;strong&gt;NOTE:&lt;/strong&gt; To add more members, please save this form, and more spaces will be presented.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/p&gt;&lt;/noscript&gt;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;nbsp;&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'band/index'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;Cancel&lt;/a&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;?php</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;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isNew</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;nbsp;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Delete'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'band/delete?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'method'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'delete'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'confirm'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Are you sure?'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type=&quot;submit&quot; value=&quot;Save&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/td&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;/tr&gt;<br />
&nbsp; &nbsp; &lt;/tfoot&gt;<br />
&nbsp; &nbsp; &lt;tbody&gt;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; &nbsp; &lt;/tbody&gt;<br />
&nbsp; &lt;/table&gt;<br />
&lt;/form&gt;<br />
<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> javascript_tag<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; $$('#band table').each(function(e)<br />
&nbsp; {<br />
&nbsp; &nbsp; if (e.select('table').length)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; e.select('tbody')[0].id = 'band_members';<br />
<br />
&nbsp; &nbsp; &nbsp; e.insert('<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> escape_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;tfoot&gt;&lt;tr&gt;&lt;td colspan=<span style="color: #000099; font-weight: bold;">\&quot;</span>2<span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;&quot;</span><span style="color: #339933;">.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; button_to_remote<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Add member'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'url'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'band/memberForm'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'with'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;'count='+$$('#band_members table').length&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'update'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'band_members'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'position'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'bottom'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&lt;/td&gt;&lt;/tr&gt;&lt;/tfoot&gt;<br />
&nbsp; &nbsp; &nbsp; &quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>');<br />
&nbsp; &nbsp; }<br />
&nbsp; });<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span> end_javascript_tag<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<p>It&#8217;s important to note that this code is somewhat ugly because I wanted to avoid manually changing the form&#8217;s layout. In a production situation you could implement a much more elegant solution by customising the form layout or writing a custom form renderer.</p>
<p>This point aside, your form should now look like the image below when JavaScript is enabled (when JavaScript is disabled a message will be displayed informing the user of how to add additional members):</p>
<p><img class="alignnone size-full wp-image-242" title="Form with add member button added" src="http://ezzatron.com/wp-content/uploads/2009/12/form_with_ajax.png" alt="Form with add member button added" width="433" height="608" /></p>
<p>We&#8217;re now able to add additional slots for new members dynamically using the &#8220;Add member&#8221; button. We&#8217;re facing one last hurdle unfortunately; when we add a new member slot and hit the save button we&#8217;re presented with a form error:</p>
<p><img class="alignnone size-full wp-image-245" title="Validation error when adding members dynamically" src="http://ezzatron.com/wp-content/uploads/2009/12/dynamic_validation_error.png" alt="Validation error when adding members dynamically" width="433" height="165" /></p>
<p>Thankfully this is fairly easy to remedy. The issue is that when the update action handles the posted data, it creates a fresh instance of <strong>BandForm</strong> which has no knowledge of our &#8220;extra&#8221; band member form. To fix this we can override the <strong>BandForm</strong> class&#8217; <strong>bind()</strong> method to detect the number of band members passed and expand the form as needed:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> BandForm <span style="color: #000000; font-weight: bold;">extends</span> BaseBandForm<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> bind<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$taintedValues</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$taintedFiles</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$taintedValues</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'members'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$taintedValues</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'members'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNumMembers</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$taintedValues</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'members'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$taintedValues</span><span style="color: #339933;">,</span> <span style="color: #000088;">$taintedFiles</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>And hey presto, our form now works perfectly!</p>
<h2>Conclusion</h2>
<p>If you got this far I&#8217;m sure you&#8217;ll agree that this was not by any means an easy exercise. The symfony forms system <em>is </em>powerful and flexible, but it seems like perhaps this type of situation was not really brought into consideration when it was designed. I would love to see the symfony architects consider ways that the implementation of expanding forms could be simplified, or at least better documented.</p>
<p>Once again if you have any suggestions on how to improve this implementation I&#8217;d really love to hear them. I&#8217;m sure there are aspects of the symfony forms system that I don&#8217;t understand fully which could make this whole exercise somewhat simpler, and that would certainly be valuable knowledge.</p>
<p>If you are interested, there is a guide to implementing a similar system <a title="How to Embed AJAX(!) Forms in Symfony 1.2 Admin Generator" href="http://israelwebdev.wordpress.com/2009/05/04/how-to-embed-ajax-forms-in-symfony-12-admin-generator/">here</a>, however it seems to deal with the symfony admin generator specifically, and it also seems to have the disadvantage that the parent object must exist before child objects can be added.</p>
<p>Good luck with your own implementations, let me know how they go!</p>
<h2>Source code</h2>
<ul>
<li><a href="http://expandingform.sf.ezzatron.com/source/_form.phps">_form.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/actions.class.phps">actions.class.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/BandForm.class.phps">BandForm.class.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/BandMembersForm.class.phps">BandMembersForm.class.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/BaseFormDoctrine.class.phps">BaseFormDoctrine.class.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/EmbeddedBandMemberForm.class.phps">EmbeddedBandMemberForm.class.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/EmbeddedBandMemberValidatorSchema.class.phps">EmbeddedBandMemberValidatorSchema.class.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/fixtures.yml">fixtures.yml</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/memberFormSuccess.phps">memberFormSuccess.php</a></li>
<li><a href="http://expandingform.sf.ezzatron.com/source/schema.yml">schema.yml</a></li>
</ul>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2009%2F12%2F03%2Fexpanding-forms-with-symfony-1-2-and-doctrine%2F';
  addthis_title  = 'Expanding+forms+with+symfony+1.2+and+Doctrine';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2009/12/03/expanding-forms-with-symfony-1-2-and-doctrine/feed/</wfw:commentRss>
		<slash:comments>47</slash:comments>
		</item>
		<item>
		<title>Automatically signing .jar files in NetBeans</title>
		<link>http://ezzatron.com/2009/09/29/automatically-signing-jar-files-in-netbeans/</link>
		<comments>http://ezzatron.com/2009/09/29/automatically-signing-jar-files-in-netbeans/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 09:03:41 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[applet]]></category>
		<category><![CDATA[automatic]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[netbeans]]></category>
		<category><![CDATA[permissions]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[signing]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=143</guid>
		<description><![CDATA[Just a quick article on something I struggled to find a good example for &#8211; configuring NetBeans to sign a .jar file after compilation is complete. This is very handy, for example, when developing an applet that requires permission to access the file system. This requires the applet to be &#8220;signed&#8221; using the jarsigner utility, [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick article on something I struggled to find a good example for &#8211; configuring <strong>NetBeans </strong>to sign a .jar file after compilation is complete.</p>
<p>This is very handy, for example, when developing an <strong>applet </strong>that requires permission to access the file system. This requires the applet to be <strong>&#8220;signed&#8221;</strong> using the <strong>jarsigner </strong>utility, and this quickly becomes a tedious step when testing changes made in your applet in the browser itself.</p>
<p><span id="more-143"></span></p>
<p>I&#8217;m assuming that since you&#8217;re reading this article you have basic knowledge of <strong>Java </strong>and the <strong>keytool </strong>and <strong>jarsigner</strong> utilities. If not, there is a good introduction <a title="JAR Signing" href="http://www.cs.princeton.edu/introcs/85application/jar/sign.html">here</a>.</p>
<p>Please note that this how-to is intended for a development environment situation only. Before deploying to a production environment you should read up on the best practices and security implications of the .jar signing process.</p>
<h2>Step 1: Setting up your keystore</h2>
<p>For this step we will be using the <strong>keytool </strong>utility distributed with your <strong><acronym title="Java Development Kit">JDK</acronym></strong>. This will most likely be in the <strong>bin </strong>directory of your <strong><acronym title="Java Development Kit">JDK</acronym></strong> installation.</p>
<p>Assuming <strong>keytool </strong>is in your system path, run the command:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">keytool -genkey -alias &lt;alias name&gt; -keystore &lt;keystore path&gt; -validity 36500</div></div>
<p>Replacing <em>&lt;alias name&gt;</em> with a suitable alias, and <em>&lt;keystore path&gt;</em> with the filename you&#8217;d like for your <strong>keystore</strong>.</p>
<p>You will then be prompted for a number of inputs. For a test setup, use the following answers:</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Enter keystore password: &lt;keystore password&gt; &lt;enter&gt;<br />
Re-enter new password: &lt;keystore password&gt; &lt;enter&gt;<br />
What is your first and last name?<br />
&nbsp; [Unknown]: &lt;enter&gt;<br />
What is the name of your organizational unit?<br />
&nbsp; [Unknown]: &lt;enter&gt;<br />
What is the name of your organization?<br />
&nbsp; [Unknown]: &lt;enter&gt;<br />
What is the name of your City or Locality?<br />
&nbsp; [Unknown]: &lt;enter&gt;<br />
What is the name of your State or Province?<br />
&nbsp; [Unknown]: &lt;enter&gt;<br />
What is the two-letter country code for this unit?<br />
&nbsp; [Unknown]: &lt;enter&gt;<br />
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?<br />
&nbsp; [no]:  y &lt;enter&gt;<br />
<br />
Enter key password for &lt;&lt;alias name&gt;&gt;<br />
&nbsp; (RETURN if same as keystore password): &lt;key password&gt; &lt;enter&gt;</div></div>
<p>This will create a <strong>keystore</strong> file at <em>&lt;keystore path&gt;</em> which we will use in the next step to sign .jar files. Remember the passwords you used in this step as you&#8217;ll need them very soon.</p>
<p>The <em>-validity 36500</em> section simply specifies that we want this key to last for a very long time (100 years to be exact). This is fine in a <strong>development</strong> environment as you probably don&#8217;t want to have to regenerate new keys all the time, but in a <strong>production</strong> environment this would obviously be much shorter. The <em>-validity</em> value is specified in <strong>days</strong>.</p>
<h2>Step 2: Configuring your NetBeans project</h2>
<p>In this step we will be editing two configuration files from your NetBeans project; <strong>project.properties</strong> and <strong>build.xml</strong>.</p>
<p>The project.properties file should be located in the <strong>nbproject</strong> directory of your NetBeans project, and the build.xml should be in the main project folder itself.</p>
<p>You can edit these files by hand, or you can do so in <strong>NetBeans</strong> itself by switching to the <strong>Files</strong> window.</p>
<p>Add the following lines somewhere in your <strong>project.properties</strong> file, substituting the relevant paths etc. (hint: your <strong>jarsigner</strong> utility should be in the <strong>bin</strong> directory of your <strong><acronym title="Java Development Kit">JDK</acronym></strong> installation):</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">jarsign.jarsigner=&lt;path to the jarsigner utility&gt;<br />
jarsign.keystore=&lt;keystore path&gt;<br />
jarsign.storepass=&lt;keystore password&gt;<br />
jarsign.keypass=&lt;key password&gt;<br />
jarsign.signedjar=&lt;path to create signed jar file at&gt;<br />
jarsign.alias=&lt;alias name&gt;</div></div>
<p>Add the following <em>inside</em> the <strong>&lt;project&gt;</strong> block in your <strong>build.xml</strong> file:</p>
<div class="codecolorer-container xml vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;-post-jar&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exec</span> <span style="color: #000066;">executable</span>=<span style="color: #ff0000;">&quot;${jarsign.jarsigner}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;-keystore&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${jarsign.keystore}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;-storepass ${jarsign.storepass}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;-keypass ${jarsign.keypass}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;-signedjar&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${jarsign.signedjar}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${dist.jar}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;${jarsign.alias}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exec<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;echo<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Signed Jar '${jarsign.signedjar}' created<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/echo<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>And that&#8217;s it. The next time you <strong>build</strong> your project, a signed copy of the .jar file should be created automatically at the path you specified. You should also see a confirmation message in the build output.</p>
<p><strong>Enjoy!</strong></p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2009%2F09%2F29%2Fautomatically-signing-jar-files-in-netbeans%2F';
  addthis_title  = 'Automatically+signing+.jar+files+in+NetBeans';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2009/09/29/automatically-signing-jar-files-in-netbeans/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Revisited: foreachif()</title>
		<link>http://ezzatron.com/2009/07/22/foreachif-revisited/</link>
		<comments>http://ezzatron.com/2009/07/22/foreachif-revisited/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 07:39:28 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[wish list]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=107</guid>
		<description><![CDATA[A while ago I blogged about my desire for a foreachif() construct in PHP. A recent comment from a reader made me re-think the concept and consider ways in which it could be implemented elegantly, without the need for changes to PHP&#8216;s syntax. Why implement it in PHP code rather than make a change to [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I blogged about <a title="PHP wish list - part 1: foreachif()" href="http://ezzatron.com/2008/12/04/php-wishlist-part-1-foreachif/">my desire for a foreachif() construct in PHP</a>. A <a href="http://ezzatron.com/2008/12/04/php-wishlist-part-1-foreachif/comment-page-1/#comment-94">recent comment</a> from a reader made me re-think the concept and consider ways in which it could be implemented elegantly, without the need for changes to <a title="PHP: Hypertext Preprocessor" href="http://php.net/">PHP</a>&#8216;s syntax.</p>
<p><span id="more-107"></span></p>
<p>Why implement it in PHP code rather than make a change to the syntax itself? Well, the reason is fairly simple; having too many syntaxes for the same thing can make code very difficult to read and understand unless the reader is a guru in that particular language. Anyone who has been forced to use <a title="Perl" href="http://www.perl.org/">Perl</a> will know what I mean.</p>
<p>The above comment suggested the use of the <strong>eval()</strong> function. Whilst this would work, I don&#8217;t particularly like the idea for a number of reasons:</p>
<ul>
<li>If there is an error in the eval&#8217;d code, this will show up in a back-trace as occurring in eval&#8217;d code rather than pointing to the actual problem itself &#8211; messy.</li>
<li>If like me, you are used to a nice, cushy IDE, you&#8217;ll know that almost all of your code completion / highlighting immediately goes out the window inside of a string.</li>
<li>I try to avoid <strong>eval()</strong> as a rule of thumb. It just makes me feel <em>dirty</em>.</li>
</ul>
<p>I thought I might try a similar solution however, using PHP 5.3&#8242;s new <a title="PHP: Anonymous functions - Manual" href="http://php.net/closures">closures</a> feature. Closures (A.K.A. <em>anonymous functions</em>) will most likely be familiar to anyone who has used JavaScript in any serious fashion, so I will not go into them here. If you are unfamiliar with the concept, please <a title="PHP: Anonymous functions - Manual" href="http://php.net/closures">RTFM</a>.</p>
<p>In order to make this work there are a few things we need:</p>
<ul>
<li>An array to iterate over</li>
<li>A condition of some sort to evaluate on each loop</li>
<li>A callback to execute if the condition evaluates to true</li>
<li>Some measure of control over variable names passed to the callback would also be nice</li>
</ul>
<p>The bottom line is that it is possible, but it&#8217;s nowhere near as nice, or elegant as I had hoped.</p>
<h2>Method 1: using closures</h2>
<p>Using nothing but the new closures syntax I was able to come up with the following reasonable-looking foreachif() function:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> foreachif<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$condition</span><span style="color: #339933;">,</span> <span style="color: #000088;">$callback</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/is_callable"><span style="color: #990000;">is_callable</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$condition</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'condition must be a valid callback'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/is_callable"><span style="color: #990000;">is_callable</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$callback</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'callback must be a valid callback'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$condition</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$callback</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>This seemed fine until the time came to actually <em>use</em> the thing. Reproducing one of the examples from the aforementioned article resulted in this mess:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
foreachif <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$value</span> <span style="color: #339933;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Not particularly readable huh? Downright horrible is more like it.</p>
<h2>Method 2: mixed closures and eval&#8217;d strings</h2>
<p>The above mess made me think perhaps I could just use eval() for the condition &#8211; perhaps this would help remove some clutter from the statement? Well, yes it does, but it also presents its own problems. Here is the new function:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> foreachif<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value_name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$condition</span><span style="color: #339933;">,</span> <span style="color: #000088;">$callback</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/is_callable"><span style="color: #990000;">is_callable</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$callback</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'callback must be a valid callback'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$$value_name</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/eval"><span style="color: #990000;">eval</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>run = <span style="color: #006699; font-weight: bold;">$condition</span>;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$run</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$callback</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$$value_name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>In order to retain flexibility in naming the variable used to store the current iteration value, I was forced to pass the variable name as a string. I didn&#8217;t like this at all, and the situation would only get worse if you wanted to be able to choose the name of the array <em>key </em>inside the condition also.</p>
<p>For the sake of completeness, here is an example the utilises the above function:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
foreachif <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'this_value'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'$this_value % 2 == 0'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this_value</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this_value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Then suddenly I realised I was forgetting a very, very important point; <em>variable scope</em>.</p>
<h2>The big problem</h2>
<p>What neither of the above implementations give you is access to any variables defined outside of the closure / eval&#8217;d code itself. Granted this could be worked around by grabbing <em>every</em> defined variable and re-defining them within the scope of the loop content, but this would almost certainly have major performance issues when used in any real-world situation.</p>
<p>At this point I basically abandoned the search for a function-based implementation and started considering PHP syntax alternatives, which turned out to be a much more elegant solution in the end&#8230;</p>
<h2>Method 3: using existing PHP syntax in alternative ways</h2>
<p>Starting with the ultra-obvious solution gives us the following:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<br />
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$value</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;">$value</span> <span style="color: #339933;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span></div></div>
<p>There is also PHP&#8217;s alternate syntax for these structures to consider, and I think the following actually comes out looking quite nice:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span></div></div>
<p>The main area in which I intended to use this structure was in native PHP templating. In line with this thinking, here is the above restated as I would present it in a template:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$value</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>,<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<p>As you can see, these last three examples are actually quite readable (the last one as much so as native PHP templating can be). The big bonus of course is that they still allow access to all variables in their scope and have no significant performance impact (provided of course that your condition is not intensive on resources).</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2009%2F07%2F22%2Fforeachif-revisited%2F';
  addthis_title  = 'Revisited%3A+foreachif%28%29';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2009/07/22/foreachif-revisited/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Help stop the Great Firewall of Oz!</title>
		<link>http://ezzatron.com/2008/12/15/help-stop-the-great-firewall-of-oz/</link>
		<comments>http://ezzatron.com/2008/12/15/help-stop-the-great-firewall-of-oz/#comments</comments>
		<pubDate>Sun, 14 Dec 2008 22:16:00 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[censorship]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[internet]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=63</guid>
		<description><![CDATA[This is just a quick post to try and rally a few signatures against the ridiculous mandatory internet filter proposed for Australia. There are so many reasons why this should not go ahead. I won&#8217;t go into detail here, but you should learn more if you don&#8217;t know what I&#8217;m on about. Try Horus Kol&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>This is just a quick post to try and rally a few signatures against the ridiculous <a title="Internet censorship in Australia - Wikipedia" href="http://en.wikipedia.org/wiki/Internet_censorship_in_Australia">mandatory internet filter proposed for Australia</a>.</p>
<p>There are so many reasons why this should not go ahead. I won&#8217;t go into detail here, but you <strong>should</strong> learn more if you don&#8217;t know what I&#8217;m on about. Try Horus Kol&#8217;s <a title="Great Firewall of Oz - Horus Kol" href="http://www.horuskol.co.uk/great-firewall-of-oz-20081202">article</a>, or <a title="No Clean Feed" href="http://nocleanfeed.com/">No Clean Feed</a> for some good information.</p>
<p>Please use this nifty form to show your support for the fight against mandatory internet censorship:</p>
<div><object width="300" height="250" data="http://www.getup.org.au/flash/widget.swf" type="application/x-shockwave-flash"><param name="quality" value="high" /><param name="src" value="http://www.getup.org.au/flash/widget.swf" /></object></div>
<p>In addition, there is another petition you can sign at <a title="top Australian Internet Censorship - TakingITGlobal" href="http://petitions.takingitglobal.org/oznetcensorship">TakingITGlobal</a>.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2008%2F12%2F15%2Fhelp-stop-the-great-firewall-of-oz%2F';
  addthis_title  = 'Help+stop+the+Great+Firewall+of+Oz%21';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2008/12/15/help-stop-the-great-firewall-of-oz/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP wish list &#8211; part 2: reverse combined operators</title>
		<link>http://ezzatron.com/2008/12/12/php-wish-list-part-2-reverse-combined-operators/</link>
		<comments>http://ezzatron.com/2008/12/12/php-wish-list-part-2-reverse-combined-operators/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 06:38:39 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[wish list]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=40</guid>
		<description><![CDATA[It&#8217;s time for part 2 of my PHP wish list! In this instalment I&#8217;ll detail another feature that I would love to see in PHP: reverse combined operators. If you missed part 1 (you probably did), you can read it here. &#8220;What the hell is a reverse combined operator?&#8221; I hear you scream. Well, technically [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s time for part 2 of my <strong>PHP wish list! </strong>In this instalment I&#8217;ll detail another feature that I would love to see in PHP: <strong>reverse combined operators</strong>.</p>
<p>If you missed part 1 (you probably did), you can read it <a title="PHP wish list - part 1: foreachif()" href="http://ezzatron.com/2008/12/04/php-wishlist-part-1-foreachif/">here</a>.</p>
<p><em>&#8220;What the hell is a reverse combined operator?&#8221;</em> I hear you scream. Well, technically they probably don&#8217;t exist yet, so I&#8217;m sure a better name could be found, but bear with me and I&#8217;ll try to explain&#8230;</p>
<p><span id="more-40"></span></p>
<p>If you&#8217;ve ever done any programming, then you&#8217;ve almost certainly used <strong>operators</strong> whether you realise it or not. Basically, they are some of the most basic building blocks of a programming language, things like <strong>+</strong>, <strong>-</strong>, <strong>=</strong> and <strong>==</strong> are all <strong>operators</strong>. For a more detailed description, see the <a title="PHP Manual - Operators" href="http://php.net/operators">PHP manual</a>.</p>
<p>One of the most commonly used operators in any language is the <strong>assignment operator</strong> (=). This operator is used to assign a <strong>value </strong>to a <a href="http://php.net/variables">variable</a>. Here is a simple example:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$variable</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$variable</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// outputs &quot;2&quot;</span></div></div>
<p>In the above example, PHP first uses the <a title="PHP Manual - Arithmetic Operators" href="http://www.php.net/manual/en/language.operators.arithmetic.php">addition operator</a> to get the sum of 1 and 1. It then stores the result in <strong>$variable</strong> using the <strong>assignment operator</strong>.</p>
<p>Now consider the following situation; you have a variable that you want to add a certain amount to. Rather than writing the whole expression out like this:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$variable</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$variable</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span></div></div>
<p>PHP allows you to shorten the above to just:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$variable</span> <span style="color: #339933;">+=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span></div></div>
<p>This is called a <strong>combined operator</strong> because it is effectively a combination of the <strong>+</strong> and <strong>=</strong> operators. This combining of operators is only ever done with the assignment operator and one other operator. Here are all the combined operators that I am aware of:</p>
<table style="text-align: left;" border="0" width="477">
<tbody>
<tr>
<th>Operator</th>
<th>Equivalent to</th>
<th>Description</th>
</tr>
<tr>
<td>$a += $b</td>
<td>$a = $a + $b</td>
<td>Addition / array union</td>
</tr>
<tr>
<td>$a -= $b</td>
<td>$a = $a &#8211; $b</td>
<td>Subtraction</td>
</tr>
<tr>
<td>$a *= $b</td>
<td>$a = $a * $b</td>
<td>Multiplication</td>
</tr>
<tr>
<td>$a /= $b</td>
<td>$a = $a / $b</td>
<td>Division</td>
</tr>
<tr>
<td>$a %= $b</td>
<td>$a = $a % $b</td>
<td>Modulus</td>
</tr>
<tr>
<td>$a .= $b</td>
<td>$a = $a . $b</td>
<td>Concatenation</td>
</tr>
<tr>
<td>$a &amp;= $b</td>
<td>$a = $a &amp; $b</td>
<td>Bitwise and</td>
</tr>
<tr>
<td>$a |= $b</td>
<td>$a = $a | $b</td>
<td>Bitwise or</td>
</tr>
<tr>
<td>$a ^= $b</td>
<td>$a = $a ^ $b</td>
<td>Bitwise xor</td>
</tr>
<tr>
<td>$a &lt;&lt;= $b</td>
<td>$a = $a &lt;&lt; $b</td>
<td>Left shift</td>
</tr>
<tr>
<td>$a &gt;&gt;= $b</td>
<td>$a = $a &gt;&gt; $b</td>
<td>Right shift</td>
</tr>
</tbody>
</table>
<p>What I would like to see are <strong>reverse combined operators</strong>. Essentially these would be the same as regular combined operators, except with the order of operands <strong>reversed</strong>. This would produce the following options:</p>
<table style="text-align: left;" border="0" width="477">
<tbody>
<tr>
<th>Operator</th>
<th>Equivalent to</th>
<th>Description</th>
</tr>
<tr>
<td>$a =+ $b</td>
<td>$a = $b + $a</td>
<td>Array union</td>
</tr>
<tr>
<td>$a =- $b</td>
<td>$a = $b &#8211; $a</td>
<td>Subtraction</td>
</tr>
<tr>
<td>$a =/ $b</td>
<td>$a = $b / $a</td>
<td>Division</td>
</tr>
<tr>
<td>$a =% $b</td>
<td>$a = $b % $a</td>
<td>Modulus</td>
</tr>
<tr>
<td>$a =. $b</td>
<td>$a = $b . $a</td>
<td>Concatenation</td>
</tr>
<tr>
<td>$a =&lt;&lt; $b</td>
<td>$a = $b &lt;&lt; $a</td>
<td>Left shift</td>
</tr>
<tr>
<td>$a =&gt;&gt; $b</td>
<td>$a = $b &gt;&gt; $a</td>
<td>Right shift</td>
</tr>
</tbody>
</table>
<p>Note that not every combined operator would imply the need for a reverse version because the order of operands has no effect on the result in some cases.</p>
<p>I&#8217;ll now provide you with a couple of examples where something like this could come in handy.</p>
<p><strong>Inverting a number</strong>:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$v</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$v</span> <span style="color: #339933;">=/</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$v</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// would output &quot;0.01&quot;</span></div></div>
<p><strong>Controlling which array takes precedence</strong> when merging arrays using the <strong>array union operator</strong> (basically just the <strong>+</strong> operator, but when used on arrays you get the union of the two):</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$v</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'one'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'two'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'three'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$v</span> <span style="color: #339933;">+=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'apple'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'banana'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'orange'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// this would output &quot;one,two,three,orange,&quot;</span><br />
<br />
<span style="color: #000088;">$v</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'one'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'two'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'three'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$v</span> <span style="color: #339933;">=+</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'apple'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'banana'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'orange'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// this would output &quot;one,apple,banana,orange,&quot;</span></div></div>
<p>I&#8217;m sure if you racked your brain you could come up with dozens of other handy little uses for this feature. Let me know if you can think of any others!</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2008%2F12%2F12%2Fphp-wish-list-part-2-reverse-combined-operators%2F';
  addthis_title  = 'PHP+wish+list+%26%238211%3B+part+2%3A+reverse+combined+operators';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2008/12/12/php-wish-list-part-2-reverse-combined-operators/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>PHP wish list &#8211; part 1: foreachif()</title>
		<link>http://ezzatron.com/2008/12/04/php-wishlist-part-1-foreachif/</link>
		<comments>http://ezzatron.com/2008/12/04/php-wishlist-part-1-foreachif/#comments</comments>
		<pubDate>Thu, 04 Dec 2008 13:16:30 +0000</pubDate>
		<dc:creator>Erin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[wish list]]></category>

		<guid isPermaLink="false">http://ezzatron.com/?p=3</guid>
		<description><![CDATA[PHP is a great programming language. Honestly, I&#8217;ve worked with it almost every day for 5 or so years and I still love it. I haven&#8217;t even considered trying Python, promise! *looks guiltily at Andi and Zeev* Sometimes though, I do wish for something more. Never enough to switch teams (sorry Python), but there are [...]]]></description>
			<content:encoded><![CDATA[<p><a title="PHP" href="http://php.net/">PHP</a> is a great programming language. Honestly, I&#8217;ve worked with it almost every day for 5 or so years and I still love it. I haven&#8217;t even <em>considered</em> trying <a title="Python" href="http://python.org/">Python</a>, promise! <em>*looks guiltily at Andi and Zeev*</em></p>
<p>Sometimes though, I do wish for something more. Never enough to switch teams (sorry Python), but there are a few points I keep coming back to. This, in fact, is at the present moment the sole reason for this blog&#8217;s existence &#8211; I simply don&#8217;t have anywhere else to voice my frustration.</p>
<p>So, without further ado I give you part 1 of my PHP wish list: the <strong>foreachif() construct!</strong></p>
<p><span id="more-3"></span></p>
<p>The <a title="foreach() contruct" href="http://php.net/foreach">foreach()</a> construct is a feature of many modern programming languages, including PHP. In PHP&#8217;s case, there are two syntaxes:</p>
<pre>foreach (array_expression as $value)
    statement
foreach (array_expression as $key =&gt; $value)
    statement</pre>
<p>Basically it will iterate over every value in an array but it has advantages over a regular <strong>for()</strong> loop in cases where the array keys are non-sequential (and it can also iterate over an object&#8217;s member variables).</p>
<p>Whilst <strong>foreach()</strong> is a very useful construct in itself, I too often find myself wrapping everything inside the foreach() loop in one big <strong>if()</strong> statement:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #666666; font-style: italic;">/* some condition */</span><span style="color: #009900;">&#41;</span><br />
   <span style="color: #009900;">&#123;</span><br />
      <span style="color: #666666; font-style: italic;">// do something</span><br />
   <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Now, imagine if there were a new construct formed by combining the above <strong>foreach()</strong> with PHP&#8217;s basic <strong>if()</strong> construct&#8230;</p>
<pre>if (expr)
    statement</pre>
<p>&#8230;to form a new construct, <strong>foreachif()</strong> with the following syntaxes:</p>
<pre>foreachif (array_expression as $value; expr)
    statement
foreachif (array_expression as $key =&gt; $value; expr)
    statement</pre>
<p>Where statement would be executed for each value in <em>array_expression</em> where <em>expr</em>&#8216;s Boolean value equates to TRUE.</p>
<p>The <em>expr</em> part of the syntax would have to be evaluated last so that the logic of <em>expr</em> could involve the use of <em>$value</em> (and <em>$key</em> in the second form).</p>
<p>For example, the following code (which will echo only even number VALUES<br />
from an array):</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Could be written much more concisely using <strong>foreachif()</strong>:</p>
<div class="codecolorer-container php vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
foreachif <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span> <span style="color: #000088;">$value</span> <span style="color: #339933;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$value</span><span style="color: #339933;">.</span><span style="color: #0000ff;">','</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Of course some people would call this lazy, but to me it feels natural. In any case, don&#8217;t hold your breath, due to a clear lack of any real <em>need</em> for this feature it&#8217;s doubtful this will ever make into <a title="Taking a look at PHP 6" href="http://jero.net/articles/php6">PHP 6</a>. Perhaps <a title="PHP 10.0 Blog" href="http://php100.wordpress.com/">PHP 10</a>?</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fezzatron.com%2F2008%2F12%2F04%2Fphp-wishlist-part-1-foreachif%2F';
  addthis_title  = 'PHP+wish+list+%26%238211%3B+part+1%3A+foreachif%28%29';
  addthis_pub    = 'ezzatron';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://ezzatron.com/2008/12/04/php-wishlist-part-1-foreachif/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>

