<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>TBNL</title>
	
	<link>http://www.tibobeijen.nl</link>
	<description>...another view on the web and how it's built</description>
	<lastBuildDate>Wed, 06 Jul 2011 19:28:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/tbnl" /><feedburner:info uri="tbnl" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>DDD using Doctrine 2: A case study</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/7sqX7cNqbcE/</link>
		<comments>http://www.tibobeijen.nl/blog/2011/06/27/ddd-using-doctrine-2-a-case-study/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 13:06:57 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[Doctrine 2]]></category>
		<category><![CDATA[Domain Driven Design]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=704</guid>
		<description><![CDATA[Nowadays developing web applications usually requires a flexible process due to changing business logic, shifting priorities or new insights. Besides choosing the right methodology this also requires designing the application in such a way that this flexibility can be achieved. Domain Driven Design fits this process as it isolates business logic in the Domain layer [...]]]></description>
			<content:encoded><![CDATA[<p>Nowadays developing web applications usually requires a flexible process due to changing  business logic, shifting priorities or new insights. Besides choosing the right methodology this also requires designing the application in such a way that this flexibility can be achieved. </p>
<p><a href="http://domaindrivendesign.org/">Domain Driven Design</a> fits this process as it isolates business logic in the Domain layer and separates it from infrastructure and presentation layers. Questions like where or how to store data or what to build (website, mobile app, API) can be addressed separately. </p>
<p><a href="http://www.doctrine-project.org/projects/orm/2.0/docs/en">Doctrine 2</a> provides PHP developers with a powerful tool to create a Domain layer that contains business logic that is easy to unit test and therefore easy to expand upon in iterations.</p>
<p>In this article I will show how to implement a specific case using Doctrine 2. Full code accompanying this article can be <a href="https://github.com/TBeijen/DDD-HRM/tree/v001">found on GitHub</a>.<br />
<span id="more-704"></span></p>
<h3>In this article</h3>
<ul>
<li><a href="#caseOutline">Case outline</a></li>
<li><a href="#descriptionOfEntities">Description of Entities</a>
<ul>
<li><a href="#entUser">User</a></li>
<li><a href="#entTimeSheet">TimeSheet</a></li>
<li><a href="#entTimeSheetStatusChange">TimeSheetStatusChange</a></li>
<li><a href="#entNotIncluded">What&#8217;s not included</a></li>
</ul>
</li>
<li><a href="#implementing">Implementing requirements using Doctrine 2</a>
<ul>
<li><a href="#req1">User should have an e-mail address that is unique</a></li>
<li><a href="#req2">A TimeSheet should always belong to a user which, once specified, cannot be changed</a></li>
<li><a href="#req3">A new TimeSheet by default should have a status ‘open’</a></li>
<li><a href="#req4">Status changes should only be allowed in specific order</a></li>
<li><a href="#req5">A new TimeSheetStatusChange should have a dateApplied that is equal or more recent than the most recent TimeSheetStatusChange</a></li>
<li><a href="#req6">TimeSheetStatusChanges must have reference to a TimeSheet but at the same time must be valid.</a></li>
</ul>
</li>
<li><a href="#beyondDatabase">Where the domain model goes beyond the database model</a></li>
<li><a href="#concluding">Concluding</a></li>
</ul>
<h3 id="caseOutline">Case outline</h3>
<p>The application developed is a time registration tool that allows users to enter per-day time sheets and submit them for approval. A manager will approve or disapprove the time sheet. The business requirement this iteration focuses on is the tracking of time sheet status history and only allowing specific status changes. In subsequent iterations features like registrations, tasks, projects and permissions will be implemented.</p>
<h3 id="descriptionOfEntities">Description of entities</h3>
<p><a href="http://www.tibobeijen.nl/blog/wp-content/uploads/2011/06/yuml-ddd-hrm-001.21.png"><img src="http://www.tibobeijen.nl/blog/wp-content/uploads/2011/06/yuml-ddd-hrm-001.21-500x46.png" alt="" title="User, TimeSheet and TimeSheetStatusChange entities" width="500" height="46" class="aligncenter size-medium wp-image-723" /></a></p>
<h4 id="entUser">User</h4>
<p>A User can login, has attributes and &#8211; interesting for this case &#8211; can have timesheets. A user’s email address can be changed at any time but should be unique as it serves as the login name.</p>
<h4 id="entTimeSheet">TimeSheet</h4>
<p>A TimeSheet holds registrations of a single user, the registrant. Those registrations will be reviewed by a manager who will approve or disapprove them on a per-timesheet basis. The timesheet therefore can have the following statuses:</p>
<ul>
<li>Open &#8211; The default status of every new timesheet</li>
<li>Submitted &#8211; The timesheet has been submitted for approval</li>
<li>Approved &#8211; The manager has approved the timesheet</li>
<li>Disapproved &#8211; The manager has disapproved the timesheet</li>
<li>Final &#8211; The timesheet’s registrations have been processed and therefore can never be changed. Examples of processing are periodic business reports or salary payment.</li>
</ul>
<p>Status changes will be stored to allow a history of status changes to be shown. The most recent status change reflects the timesheet’s ‘current’ status.</p>
<p>Status changes are only allowed to be added in a specific order.</p>
<h4 id="entTimeSheetStatusChange">TimeSheetStatusChange</h4>
<p>Each subsequent status of a timesheet is represented by a TimeSheetStatusChange. Properties of a status change are the status and the date the new status has been applied. Once stored, the status and date properties of a status change are not allowed to change to prevent ‘breaking’ the history of status changes a timesheet went through.</p>
<h4 id="entNotIncluded">What is not included</h4>
<p>As mentioned in the case outline, some obvious entities or properties are out of scope, such as the registrations themselves and the date the timesheet applies to. For the business requirements described previously they are not relevant so, in true Agile fashion, they will be implemented in subsequent iterations.</p>
<h3 id="implementing">Implementing requirements using Doctrine 2</h3>
<h4 id="req1">User should have an e-mail address that is unique</h4>
<p>This is achieved by requiring an e-mail address in the constructor and by setting the column definition of the property to be unique.</p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/User.php">Domain/Entity/User.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> User
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @Column(type=&quot;string&quot;, length=128, unique=true)
     * @var string
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$email</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span></pre></div></div>

<h4 id="req2">A TimeSheet should always belong to a user which, once specified, cannot be changed</h4>
<p>This is enforced by requiring a User entity to be supplied in the constructor. As there’s no point in changing the registrant of an existing TimeSheet, the registrant can only be specified on creation. Therefore there is no setter for the registrant property.</p>
<p>(See next code example)</p>
<h4 id="req3">A new TimeSheet by default should have a status ‘open’</h4>
<p>In the TimeSheet constructor, a new TimeSheetStatusChange is created and added to the status changes. </p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/TimeSheet.php">Domain/Entity/TimeSheet.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TimeSheet
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Constructor requiring a registrant user instance
     * 
     * @param User $registrant
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>User <span style="color: #000088;">$registrant</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
    	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registrant</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$registrant</span><span style="color: #339933;">;</span>
&nbsp;
    	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">statusChanges</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayCollection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addStatusChange</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> TimeSheetStatusChange<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'open'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// no setRegistrant()</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span></pre></div></div>

<div class="sidenote">
<p>One might think that adding a default status change to a new instance would result in a duplicate first status change when the persisted status changes are loaded while fetching the TimeSheet from the database. This is not the case as Doctrine 2 does not instantiate the constructor of entities. Read more on: <a href="http://www.doctrine-project.org/blog/doctrine-2-give-me-my-constructor-back">Doctrine 2: Give me my constructor back</a></p>
</div>
<h4 id="req4">Status changes should only be allowed in specific order</h4>
<p>This is achieved by validating each TimeSheetStatusChange that is added via the addStatusChange method. Only specific transitions are allowed.</p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/TimeSheet.php">Domain/Entity/TimeSheet.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TimeSheet
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Performs status change validation logic
     * 
     * @param string $statusChange
     * @return boolean
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _validateNextStatus<span style="color: #009900;">&#40;</span><span style="color: #000088;">$nextStatus</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
    	<span style="color: #666666; font-style: italic;">// make exception for initial adding of open status</span>
    	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$nextStatus</span> <span style="color: #339933;">===</span> <span style="color: #0000ff;">'open'</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">statusChanges</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span>
&nbsp;
    	<span style="color: #666666; font-style: italic;">// validate status changes map</span>
    	<span style="color: #000088;">$allowedChangeMap</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    		<span style="color: #0000ff;">'open'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'submitted'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    		<span style="color: #0000ff;">'submitted'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'approved'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'disapproved'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    		<span style="color: #0000ff;">'approved'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'final'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'disapproved'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    		<span style="color: #0000ff;">'disapproved'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'submitted'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'approved'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    		<span style="color: #0000ff;">'final'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    	<span style="color: #000088;">$currentStatus</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$nextStatus</span><span style="color: #339933;">,</span> <span style="color: #000088;">$allowedChangeMap</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$currentStatus</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span>
&nbsp;
    	<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h4 id="req5">A new TimeSheetStatusChange should have a dateApplied that is equal or more recent than the most recent TimeSheetStatusChange</h4>
<p>The dateApplied property is settable because it can’t be assumed that the time at which the change is entered into the application reflects the actual time of the change (An example would be paper forms that are collected and entered once a week). Therefore the dateApplied property is validated at the same time the status is validated. Furthermore, once added, the dateApplied property cannot be changed so there is no setter. When loading a TimeSheet, the TimeSheetStatusChanges are fetched in order by specifying the <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/annotations-reference.html#orderby">orderBy</a> attribute in the association.</p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/TimeSheet.php">Domain/Entity/TimeSheet.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TimeSheet
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @OneToMany(targetEntity=&quot;Domain\Entity\TimeSheetStatusChange&quot;, mappedBy=&quot;timeSheet&quot;, cascade={&quot;persist&quot;}, orphanRemoval=true)
     * @OrderBy({&quot;dateApplied&quot; = &quot;ASC&quot;, &quot;id&quot; = &quot;ASC&quot;})
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$statusChanges</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Validates if the date of the statusChange given is later than the date
     * of the last statusChange present
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _validateNextStatusChangeDate<span style="color: #009900;">&#40;</span>TimeSheetStatusChange <span style="color: #000088;">$statusChange</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
    	<span style="color: #666666; font-style: italic;">// if no statusChanges present yet any date is valid</span>
    	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">statusChanges</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span>
&nbsp;
    	<span style="color: #000088;">$currentDate</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLastStatusChange</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDateApplied</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #000088;">$nextDate</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$statusChange</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDateApplied</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    	<span style="color: #666666; font-style: italic;">// enable once tests finish</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$nextDate</span> <span style="color: #339933;">&gt;=</span> <span style="color: #000088;">$currentDate</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h4 id="req6">TimeSheetStatusChanges must have reference to a TimeSheet but at the same time must be valid.</h4>
<p>It can be prevented to store a TimeSheetStatusChange without reference to a TimeSheet by explictly specifying the joinColumn and setting the nullable attribute to false.</p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/TimeSheetStatusChange.php">Domain/Entity/TimeSheetStatusChange.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TimeSheetStatusChange
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @ManyToOne(targetEntity=&quot;Domain\Entity\TimeSheet&quot;, inversedBy=&quot;statusChanges&quot;)
     * @JoinColumn(name=&quot;timesheet_id&quot;, referencedColumnName=&quot;id&quot;, nullable=false)
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$timeSheet</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This still leaves the possibility to set ‘any’ TimeSheet and thereby skipping validation that would normally be done in TimeSheet::addStatusChange(). To prevent this, TimeSheetStatusChange::setTimeSheet() verifies if the TimeSheet’s last status is the current TimeSheetStatusChange instance. </p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/TimeSheet.php">Domain/Entity/TimeSheet.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TimeSheetStatusChange
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Sets the timeSheet.
     * 
     * Purpose is to have the reference to the timeSheet set when adding a 
     * new TimeSheetStatusChange to a TimeSheet. Therefore this method validates
     * if the timeSheet has the this instance as the last statusChange.
     * 
     * @param TimeSheet $timeSheet
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTimeSheet<span style="color: #009900;">&#40;</span>TimeSheet <span style="color: #000088;">$timeSheet</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;">$timeSheet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLastStatusChange</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #000088;">$this</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    		<span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> \InvalidArgumentException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cannot set TimeSheet if not having current instance as lastStatusChange'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span>
    	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">timeSheet</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$timeSheet</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The result is that the only way to create a persistable TimeSheetStatusChange is by adding it to the TimeSheet which will:</p>
<ol>
<li>Validate if the status change is allowed</li>
<li>Adds it to the list of status changes, making it the ‘last’ status change</li>
<li>In turn set the timeSheet reference on the TimeSheetStatusChange</li>
</ol>
<p>Persisting a TimeSheet is propagated to the status changes by setting the cascade attribute in the association definition</p>
<p><em><a href="https://github.com/TBeijen/DDD-HRM/blob/v001/Domain/Entity/TimeSheet.php">Domain/Entity/TimeSheet.php</a></em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TimeSheetStatusChange
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @OneToMany(targetEntity=&quot;Domain\Entity\TimeSheetStatusChange&quot;, mappedBy=&quot;timeSheet&quot;, cascade={&quot;persist&quot;}, orphanRemoval=true)
     * @OrderBy({&quot;dateApplied&quot; = &quot;ASC&quot;, &quot;id&quot; = &quot;ASC&quot;})
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$statusChanges</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3 id="beyondDatabase">Where the domain model goes beyond the database model</h3>
<p>One might be tempted to see an ORM as merely a convenient way to access and manipulate data contained in a database. While Doctrine 2 fits such a scenario (Entities can be modeled to reflect an already existing database) the real power shines when entities are modeled with business logic in mind instead of just being a collection of setters and getters matching the database fields.</p>
<p>Features displayed in these examples that can not be expressed in a database model include:</p>
<ul>
<li>Forcing each timesheet to start with a status ‘open’</li>
<li>Only allowing specific timesheet status changes:
<ul>
<li>By preventing ‘floating’ timesheetsStatusChanges to be created.</li>
<li>By preventing change of dateApplied and status properties, once created</li>
</ul>
</li>
<li>Make values, once persisted immutable. (the registrant property of a timesheet, the status and dateApplied properties of a timesheetStatusChange)</li>
</ul>
<h3 id="concluding">Concluding</h3>
<p>As the previous example shows, a Domain model is more than a database model: It should be modeled to comply with business logic required. As a result, for the code in this article I have used <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/tools.html">Doctrine tools</a> only for creating entity proxies, <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/tools.html#entity-generation">not the entities themselves</a></p>
<p>Furthermore, the fact that business logic is only contained in the Domain layer is illustrated by the facts that in this setup:</p>
<ul>
<li>There is no front-end</li>
<li>There is no framework (Zend Framework, Symfony, Cake, Yii, Solar, all possibilities are open)</li>
<li>There is no specific database. For the tests an in-memory SQLite database is used. In production this will obviously not be the case.</li>
</ul>
<p>Because of this isolation from other layers, domain logic is easily testable as can be seen from <a href="https://github.com/TBeijen/DDD-HRM/tree/v001/Test/Domain/Entity">the test cases</a>.</p>
<p>Credits for the test setup used here go to the example found on Giorgio Sironi&#8217;s <a href="https://github.com/giorgiosironi/ddd-talk">ddd-talk GitHub page</a>.</p>
<p>In future articles I intend to expand on this case, showing how Domain Driven Design can be used in an Agile development process.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2011/06/27/ddd-using-doctrine-2-a-case-study/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2011/06/27/ddd-using-doctrine-2-a-case-study/</feedburner:origLink></item>
		<item>
		<title>DPC 2011 preview</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/KBtie0CuQKQ/</link>
		<comments>http://www.tibobeijen.nl/blog/2011/05/17/dpc-2011-preview/#comments</comments>
		<pubDate>Tue, 17 May 2011 19:46:05 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[events]]></category>
		<category><![CDATA[dpc11]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=686</guid>
		<description><![CDATA[The yearly dutch PHP event is getting close so time to check out the schedule. Once again there are lots of interesting sessions to choose from so I probably will miss some of the good stuff. Mixing &#8216;simply interesting&#8217; and &#8216;directly usable in day-to-day job&#8217; results in the preliminary list: Day 1 TDD and Getting [...]]]></description>
			<content:encoded><![CDATA[<p>The yearly dutch PHP event is getting close so time to check out the schedule. Once again there are lots of interesting sessions to choose from so I probably will miss some of the good stuff. Mixing &#8216;simply interesting&#8217; and &#8216;directly usable in day-to-day job&#8217; results in the preliminary list: </p>
<h3>Day 1</h3>
<ul>
<li><a href="http://www.phpconference.nl/talks#tdd-and-getting-paid">TDD and Getting Paid</a> &#8211; Because indeed TDD is good and can be hard to keep doing thoroughly</a></li>
<li><a href="http://www.phpconference.nl/talks#domain-driven-design-in-php">Pursuing practices of Domain-Driven Design in PHP</a> &#8211; Fits both the &#8216;interesting&#8217; and &#8216;directly usable&#8217; categories. Based on the numerous articles by Giorgio I have high expectations</a></li>
<li><a href="http://www.phpconference.nl/talks#cooking-up-your-env">Cooking up your development environment</a> &#8211; Tools I don&#8217;t know, yet a subject that&#8217;s very real</li>
<li><a href="http://www.phpconference.nl/talks#external-dependency-management">Simplify your external dependency management</a> &#8211; Or the Uncon, depending on the schedule</li>
<li><a href="http://www.phpconference.nl/talks#implementing-comet-using-php">Implementing Comet using PHP</a> &#8211; Interesting new stuff (for me that is)</li>
<li><a href="http://www.phpconference.nl/talks#zend-framework-2-0">Zend Framework 2.0: what&#8217;s new and what&#8217;s changed?</a> &#8211; However, Advanced OO Patterns looks interesting too</li>
<li><a href="http://www.phpconference.nl/social">Conference social</a> &#8211; yup</li>
</ul>
<h3>Day 2</h3>
<ul>
<li>Pofiling, OAuth, new era of PHP Frameworks &#8211; All interesting, to be decided</li>
<li><a href="http://www.phpconference.nl/talks#managing-a-shared-mysql-farm">Managing a shared MySQL farm</a> &#8211; Because I expect to hear more new things than at the Zend Framework optimization talk</li>
<li>Agility and Quality, Modular application architecture and Character sets that suck (they do!) &#8211; Tough one once again. I think <a href="http://www.phpconference.nl/talks#agility-and-quality">Agility and Quality</a></li>
<li><a href="">Practical Git</a> &#8211; I think, because there&#8217;s a lot to learn there, although Zend Framework i18n looks interesting too</li>
<li><a href="http://www.phpconference.nl/talks#keynote-open-teams">Keynote: Open Teams</a> &#8211; Will probably be insightful as well as enjoyable</li>
</ul>
<p>Now I only need to print the ticket, bookmark this page on my iPhone and I&#8217;m off to go. Till friday!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2011/05/17/dpc-2011-preview/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2011/05/17/dpc-2011-preview/</feedburner:origLink></item>
		<item>
		<title>Usability: Autofocus and not breaking the backspace-button</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/TmCApIqt4BY/</link>
		<comments>http://www.tibobeijen.nl/blog/2011/03/14/usability-autofocus-and-not-breaking-the-backspace-button/#comments</comments>
		<pubDate>Mon, 14 Mar 2011 11:32:39 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jquery plugin]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=672</guid>
		<description><![CDATA[A while ago during a project we were asked to implement autofocus on the generic search field that every page in the application has. At a first glance a pretty straightforward task, from a technical perspective that is. Not from a user perspective, as indicated by a colleague mentioning his dislike of such autofocus fields [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago during a project we were asked to implement autofocus on the generic search field that every page in the application has. At a first glance a pretty straightforward task, from a technical perspective that is. Not from a user perspective, as indicated by a colleague mentioning his dislike of such autofocus fields &#8220;because they prevent backspace going to the previous page&#8221;. In this post I will outline some usability considerations and conclude with a jQuery plugin that will take away some of the possible hindrance of autofocusing a field.</p>
<h3>Usability considerations</h3>
<p>There are some things to consider to determine if such automatic focusing of a search field is actually helpful to the user navigating to the page. Who is <em>the</em> user?</p>
<p>As I was discussing this case with <a href="http://www.architecto.nl">an interaction designer friend</a> (dutch) of mine, he brought up the idea of mimicking the browser&#8217;s backspace behaviour, and discussing it further we concluded that this might be useful in some cases but is definitely not a &#8216;one size fits all&#8217; solution.</p>
<h4>Different goals</h4>
<p>Different users will probably have different goals when navigating to a page. On the google page or a login screen the majority of the users&#8217; goal is to type something in the first input field. On a lot of other pages this won&#8217;t be so obvious. Question then is: Will focusing a search field, if not help, instead <em>hinder</em> the user? For example: A user might have navigated to a page by accident. In that case not being able to go to the previous page by pressing &#8216;backspace&#8217; might indeed hinder the user.</p>
<h4>Different expectations</h4>
<p>Not every user navigates to the previous page by using &#8216;backspace&#8217;, some might not even be aware of that possibility. Not every user expects text entered to automatically appear in an input field. Some users might have enabled the option to directly find text in a page when typing text and find this functionality suddenly broken.</p>
<p><a href="http://diveintohtml5.org/detect.html#input-autofocus">Dive into HTML5</a> has some other nice examples of how autofocus might <em>not</em> be helpful.</p>
<h3>What size fits all?</h3>
<p>As mentioned before, there is no &#8216;one size fits all&#8217; solution. Questions that need to be asked include:</p>
<ul>
<li>How many users might be helped by adding autofocus to a common search field?</li>
<li>How many users might instead be hindered by autofocus?</li>
<li>Are there pages where autofocus on more specific fields (like the main form) is needed which will break consistency throughout the site?</li>
</ul>
<p>This means studying your site, the target audience, their goals and expectations and based on that finding a balance.</p>
<h3>Restoring the backspace: jQuery autofocusBackspace plugin</h3>
<p>If the conclusion of aforementioned considerations is that autofocus indeed <em>is</em> helpful, there is more than one way to achieve this: The first is using the HTML5 autofocus attribute. Another is using javascript to focus the field.</p>
<p>As not all browsers support the autofocus attribute yet, and we wanted to preserve the browser&#8217;s backspace functionality, I created a jQuery plugin that does just that:</p>
<ul>
<li>It focuses the first matching element
<li>It responds to &#8216;backspace&#8217; by navigating to the previous page.
<ul>
<li>Only until a user has entered text
<li>Only until the element loses focus</ul>
</ul>
<p>Refer to GitHub for the <a href="https://github.com/TBeijen/jQuery-plugin-autofocusBackspace">jQuery plugin autospaceBackspace</a>. </p>
<p>Feel free to report problems or ideas for improvement.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2011/03/14/usability-autofocus-and-not-breaking-the-backspace-button/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2011/03/14/usability-autofocus-and-not-breaking-the-backspace-button/</feedburner:origLink></item>
		<item>
		<title>Fixing mysqldump on Zend Server CE on OS X</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/AwaaprycvbA/</link>
		<comments>http://www.tibobeijen.nl/blog/2011/03/01/fixing-mysqldump-on-zend-server-ce-on-os-x/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 07:37:56 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[server administration]]></category>
		<category><![CDATA[zend server]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=652</guid>
		<description><![CDATA[A while ago I installed Zend Server Community Edition on OS X which was pretty straightforward. It was only recently that I found out that, as opposed to mysql which worked fine, mysqldump didn&#8217;t work correctly and terminated with the error: mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I installed Zend Server Community Edition on OS X which was pretty straightforward. It was only recently that I found out that, as opposed to <code>mysql</code> which worked fine, <code>mysqldump</code> didn&#8217;t work correctly and terminated with the error:<br />
<code><br />
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) when trying to connect<br />
</code><br />
Inspecting the mysql configuration contained in <code>/usr/local/zend/mysql/data/my.cnf</code> confirmed that the section [client] showed the socket as returned by executing <code>SHOW VARIABLES;</code> from the mysql client: <code>/usr/local/zend/mysql/tmp/mysql.sock</code></p>
<p>Although it is possible to specify the socket by using mysqldump&#8217;s <code>--socket</code> switch, that doesn&#8217;t really seem a &#8216;solution&#8217;. </p>
<p>Apparently mysqldump, as opposed to the mysql client does not use the server-specific settings contained in <code>/usr/local/zend/mysql/data/my.cnf</code>. The comments in my.cnf state:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"># You can copy this file to
# /etc/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options <span style="">&#40;</span>in this
# installation this directory is /usr/local/zend/mysql/data<span style="">&#41;</span> or
# ~/.my.cnf to set user-specific options.</pre></div></div>

<p>After copying <code>/usr/local/zend/mysql/data/my.cnf</code> to <code>/etc/my.cnf</code> mysqldump worked as expected.</p>
<p>In <code>/etc/my.cnf</code> I have included only the setting needed to get mysqldump running:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"># Specifying socket to use for mysql/mysqldump
# For other settings refer to /usr/local/zend/mysql/data/my.cnf
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>client<span style="">&#93;</span></span>
<span style="color: #000099;">socket</span>      <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> /usr/local/zend/mysql/tmp/mysql.sock</span></pre></div></div>

<p>Hope this saves anyone running into the same issue some time.</p>
<p><strong>Update</strong> (alternative solutions):<br />
As Joel Clermont pointed out it is also possible to create a symlink on the socket location expected by mysqldump to the real socket location. This can be done by executing:<br />
<code><br />
ln -s /usr/local/zend/mysql/tmp/mysql.sock /tmp/mysql.sock<br />
</code></p>
<p>Another possible approach is to create a symlink at <code>/etc/my.cnf</code> to <code>/usr/local/zend/mysql/data/my.cnf</code>. This has the downside that it requires loosening the default permissions (<code>drwxr-x---</code>) on the data folder by allowing &#8216;others&#8217; to enter it. Commands to execute:<br />
<code><br />
sudo chmod o+x /usr/local/zend/mysql/data<br />
sudo ln -s /usr/local/zend/mysql/data/my.cnf my.cnf<br />
</code><br />
Granting more permissions can be a security consideration but on most development setups this probably won&#8217;t be an issue.</p>
<p>Additional info about Zend Server CE on OS X:</p>
<ul>
<li><a href="http://files.zend.com/help/Zend-Server-Community-Edition/zend-server-community-edition.htm">Zend Server CE Documentation</a></li>
<li><a href="http://akrabat.com/php/some-notes-on-zend-server-ce-for-mac-os-x/">Rob Allen: Some notes on Zend Server CE for Mac OS X</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2011/03/01/fixing-mysqldump-on-zend-server-ce-on-os-x/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2011/03/01/fixing-mysqldump-on-zend-server-ce-on-os-x/</feedburner:origLink></item>
		<item>
		<title>Dutch PHP Conference (DPC) 2010</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/RuIl4eWN1qk/</link>
		<comments>http://www.tibobeijen.nl/blog/2010/06/15/dutch-php-conference-dpc-2010/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 17:17:24 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[events]]></category>
		<category><![CDATA[report]]></category>
		<category><![CDATA[dpc10]]></category>
		<category><![CDATA[dpc_uncon]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=640</guid>
		<description><![CDATA[Past weekend the Amsterdam RAI was the centre of the PHP universe as there the 2010 edition of the Dutch PHP Conference was held. Similar to past year it consisted of two presentation days, which I attended, preceded by a tutorial day. Among the presentations I attended on the first day were: Kevlin Henney&#8217;s keynote [...]]]></description>
			<content:encoded><![CDATA[<p>Past weekend the Amsterdam RAI was the centre of the PHP universe as there the 2010 edition of the <a href="http://www.phpconference.nl/">Dutch PHP Conference</a> was held. Similar to past year it consisted of two presentation days, which I attended, preceded by a tutorial day.</p>
<p>Among the presentations I attended on the first day were: </p>
<p>Kevlin Henney&#8217;s keynote presentation, titled <em>97 Things every programmer should know</em>.  I suppose every attendant will have recognised some of the things he addressed, like &#8220;Do lots of deliberate practice&#8221; or &#8220;Hard work does not pay off&#8221;.</p>
<p><em>Design for Reusability</em>. In this presentation Derick Rethans showed a number of concepts that can help in making code more reusable. Topics included  Dependency Injection Containers, the fact that private methods can never be tested and Tie-Ins. Interesting was that Derick stated that reflection is slow whereas on day 2, in the Doctrine 2 uncon talk reflection was said to be be reasonably fast (in php 5.3 that is).</p>
<p><em>Database version control</em> by Harrie Verveer was a very interesting talk, if only for the fact that it is a topic I&#8217;m confronted with at my day job. He showed tools like DbDeploy (and Phing), Liquibase, Doctrine Migrations and Akrabat DB Schema Manager. Especially ineresting was how branching can trouble database versioning.</p>
<p>Stephan Hockdoerfer&#8217;s presentation <em>Testing untestable code</em> showed some very unorthodox examples of how to test code that seems untestable, like replacing function names, manipulating the include path or mocking the filesystem. Interesting and besides that it&#8217;s great stuff to scare co-workers with (&#8220;look what trick I&#8217;ve learned!&#8221;).</p>
<p>Due to an unlucky combination of a tiresome week, a busy schedule ahead, a lot of time to kill until 20:30, and possibly age, I missed the social, so I was not devastated when day 2 started.</p>
<p>First presentation of day 2 was titled <em>Security Centered Design: Exploring the Impact of Human Behaviour</em> by Chris Shiflet. Emphasis was not on the technical aspects but on the people using an application. The presentation contained a very effective demonstration of &#8216;change blindness&#8217;. Quote of the presentation, and as far as I&#8217;m concerned whole DPC10: &#8221; If you focus on the technical problem you&#8217;re missing the actual problem&#8221;</p>
<p>Following the keynote talk, Rob Allen covered the topic of <em>Stress-free deployment</em>. There was some overlap with the database versioning talk of the previous day but still a lot to learn. Especial interesting I found the part about branching, where Rob showed how branching features as well as releases can be a good solution for some pitfals concerned with release management. Not entirely in line with the branching &#8216;problems&#8217; mentioned in the database versioning talk so it&#8217;s definitely a subject I&#8217;ll look into further.</p>
<p>After the lunch I visited the <a href="http://www.phpconference.nl/schedule/unconference">Unconference</a> room which I didn&#8217;t regret. Jeroen Keppens opened with a short presentation on a topic we need to look into at my job in the near future: <em>Integrating Zend_Acl and the domain layer</em>. Short but very insightful. After two presentations about development for mobile devices (PhoneGap looks very interesting) and Cairo I decided to stay in the uncon room some more (thereby skipping the Domain NoSQL talk) as next on were two ORM-centered presentations: First Juozas Kaziukenas explained the principles of an ORM, followed by Benjamin Eberlei giving insight on Doctrine2. That looked promising yet also, after viewing the generated SQL of some of the more complex examples, spawned a very interesting discussion I had with my co-worker who visited Sebastian Bergmann&#8217;s presentation <em>The Cake is A Lie</em>: What problems can arise from generated code that isn&#8217;t tested and nobody is responsible for?</p>
<p>Concluding: Similar to past years this was a refreshing event that fuels the urge to improve by adopting new techniques and better methodologies. Besides that I really liked the Unconference initiative. Till next year!</p>
<ul>
<li><a href="http://joind.in/event/view/142#slides">DPC 2010 slides</a> (joind.in)</li>
<li>Twitter: <a href="http://twitter.com/#search?q=dpc10">#dpc10</a> and <a href="http://twitter.com/#search?q=dpc_uncon">#dpc_uncon</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2010/06/15/dutch-php-conference-dpc-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2010/06/15/dutch-php-conference-dpc-2010/</feedburner:origLink></item>
		<item>
		<title>Zend_Form: Building dynamic forms</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/OaxYowBuwak/</link>
		<comments>http://www.tibobeijen.nl/blog/2009/12/21/zend_form-building-dynamic-forms/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 10:38:33 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[miscellaneous]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=611</guid>
		<description><![CDATA[In my previous post about Zend_Form I showed how, using Zend_Form, a form&#8217;s structure can be separated from it&#8217;s presentation and how to use custom Decorators and Validators. The example used showed a form that is tightly coupled to a record in a database: One form edits one record. There are however numerous occasions where [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="/blog/2009/12/07/using-zend_form-without-zend-framework-mvc/">my previous post about Zend_Form</a> I showed how, using Zend_Form, a form&#8217;s structure can be separated from it&#8217;s presentation and how to use custom Decorators and Validators. The example used showed a form that is tightly coupled to a record in a database: One form edits one record. There are however numerous occasions where no &#8216;one to one&#8217; connection exists and where the fields that need to be shown are not predetermined. Take for example a shopping cart that shows the amounts of each product. In this article I&#8217;ll take a look at how to:</p>
<ul>
<li>dynamically construct a form based on the data being edited</li>
<li>use subforms to reuse common parts and group related values</li>
<li>create composite &#8216;elements&#8217; by using the default Zend_Form_Element in combination with a custom decorator</li>
<li>create additional elements with Javascript and have them processed by the form when submitted</li>
</ul>
<p>Like previous article the case examined assumes a situation where Zend_Form is used in an existing project that doesn&#8217;t use the Zend Framework MVC stack. The Form <a href="/static/zend_form_dynamic/">can be viewed online</a> and all of the <a href="http://github.com/TBeijen/Zend_Form_Dynamic">sample code can be found on GitHub</a>.</p>
<h3>Case outline</h3>
<p>In this example I construct a form where a user can view and edit a task list for a week&#8217;s working days. Every task can be edited in one single form and new tasks can be added at will. When viewing the page the application fetches the tasks already entered for that week. The assumed codebase is able to generate and consume an array as shown below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// array format used to supply data of multiple tasks to form</span>
<span style="color: #000088;">$tasks</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$timestampDay1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$taskId1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'desc'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Gotta do this'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tasks</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$timestampDay1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$taskId1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'completed'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tasks</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$timestampDay2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$taskId2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'desc'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Gotta do that'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tasks</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$timestampDay2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$taskId2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'completed'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span></pre></div></div>

<p>The &#8216;current&#8217; part will later help to distinguish between new and allready stored tasks.</p>
<h3>Dynamically building a Zend_Form</h3>
<p>Using Zend_Form typically follows these steps:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Form<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// My_Form::init() will define elements</span>
<span style="color: #000088;">$Form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDefaults</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$myData</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;">$Form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$submittedValues</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValues</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// process values and redirect to same or other page</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$Form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>When a form&#8217;s elements need to be defined based on the data being edited, Zend_Form::init() is not suitable as at that point the data is not known yet. Providing data through the constructor to have it available in the init() method &#8216;could&#8217; work but is not a really nice solution as it means changing the parameter scheme of the constructor. Furthermore, it would ignore the method that exists specifically for adding initial data: setDefaults(). As that will be the first point at which the form &#8216;knows&#8217; what data needs to be edited, that will be the point to add elements. Or, as in this case, subforms.</p>
<h4>My_Form_TaskWeek</h4>
<p>The setDefaults() method of the week-form is changed as displayed below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Form_TaskWeek <span style="color: #000000; font-weight: bold;">extends</span> Zend_Form
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setDefaults<span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// first add the subforms</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearSubForms</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$dates</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$dates</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$day</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$dayForm</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_SubForm_TaskDay<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$dayForm</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$day</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">// set defaults, which will propagate to newly created subforms</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">setDefaults</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>For every day in $defaults (in this example the key is a timestamp, but it could be anything) a subform is added. This is done <em>before</em> calling parent::setDefaults(). With the subforms in place the call to the parent method will propagate to the subforms we&#8217;ve just created.</p>
<h4>My_Form_TaskDay</h4>
<p>In the form that shows one single day, some actions <em>are</em> performed in the init() method: A subform for both &#8216;current&#8217; and &#8216;new&#8217; elements is added. Also a &#8216;template&#8217; element is added. The subforms have just one decorator: FormElements. The template element will be used as source for new elements that are added by javascript. When setDefaults() is called, elements are added to the current subform.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"> <span style="color: #000000; font-weight: bold;">class</span> My_SubForm_TaskDay <span style="color: #000000; font-weight: bold;">extends</span> Zend_Form_SubForm
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// create subforms having nothing but element decorator</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Form_SubForm<span style="color: #339933;">,</span> <span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_Form_SubForm<span style="color: #339933;">,</span> <span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDecorators</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FormElements'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDecorators</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FormElements'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// add template element</span>
        <span style="color: #000088;">$templateElement</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createTaskElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'__template__'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$templateElement</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setDefaults<span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$subform</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'current'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$id</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$subform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createTaskElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">// set defaults, which will propagate to newly created subforms &amp; elements</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">setDefaults</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>The method that creates an element:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> createTaskElement<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$values</span><span style="color: #339933;">,</span> <span style="color: #000088;">$isNew</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$elm</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearDecorators</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDecorator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> My_Decorator_TaskElement<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDecorator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Errors'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'placement'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'prepend'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// add configured validator</span>
        <span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Validator_TaskElement<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$validator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setIsNew</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$isNew</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$validator</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$elm</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Creating composite elements by using custom decorator</h3>
<p>As the code above shows, creating a task element consists of three steps:</p>
<h4>Zend_Form_Element</h4>
<p>A basic Zend_Form_Element is created. This is the &#8216;root&#8217; class of which specific element-types (like Zend_Form_Element_Text) are descendants. The Form will supply each element with the element&#8217;s value which in this case will be an associative array with the keys &#8216;desc&#8217; and &#8216;completed&#8217;.</p>
<h4>My_Decorator_TaskElement</h4>
<p>A custom decorator is added: My_Decorator_TaskElement. This decorator replaces what would normally be the ViewRenderer decorator. It is responsible for rendering <em>both</em> the text and checkbox input elements and wraps them in a div. For the template element (based on the element name) the containing div will be given a classname &#8216;template&#8217; which will be of use when creating the javascript behaviour.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// get element details</span>
        <span style="color: #000088;">$elm</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElement</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elmName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFullyQualifiedName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// construct inputs</span>
        <span style="color: #000088;">$isCompleted</span> <span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'completed'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'completed'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$descValue</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'desc'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #990000;">htmlspecialchars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'desc'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$inputDesc</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'&lt;input type=&quot;text&quot; name=&quot;%s&quot; value=&quot;%s&quot; /&gt;'</span><span style="color: #339933;">,</span>
            <span style="color: #000088;">$elmName</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'[desc]'</span><span style="color: #339933;">,</span>
            <span style="color: #000088;">$descValue</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$inputCompleted</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'&lt;input type=&quot;checkbox&quot; name=&quot;%s&quot; value=&quot;1&quot; %s /&gt;'</span><span style="color: #339933;">,</span>
            <span style="color: #000088;">$elmName</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'[completed]'</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#40;</span><span style="color: #000088;">$isCompleted</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">'checked=&quot;checked&quot;'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">''</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// wrap in div, optionally adding attribute class</span>
        <span style="color: #000088;">$elmHtml</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'&lt;div class=&quot;task %s&quot;&gt;%s%s&lt;/div&gt;'</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#40;</span><span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'__template__'</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">'template'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span>
            <span style="color: #000088;">$inputDesc</span><span style="color: #339933;">,</span>
            <span style="color: #000088;">$inputCompleted</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// this should be the first decorator but add the content for</span>
        <span style="color: #666666; font-style: italic;">// consistency's sake</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$content</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$elmHtml</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<h4>My_Validator_TaskElement</h4>
<p>A custom validator is added: My_Validator_TaskElement (<a href="http://github.com/TBeijen/Zend_Form_Dynamic/blob/master/htdocs/My_Validator_TaskElement.php">see code on GitHub</a>). This validator will check if the description is empty but treats new elements differently from existing ones: For existing elements it is not allowed to have an empty description. For new elements this is only allowed if the &#8216;completed&#8217; checkbox isn&#8217;t checked. (This way a user can still submit the form if he&#8217;d accidentally added a new field). </p>
<h3>Using jQuery to let the user add new elements</h3>
<p>The javascript that lets a user add a new element is implemented as a jQuery plugin. The code having the javascript initiate looks as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'form .taskDay'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">dynamicForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>As can be seen each of the &#8216;day&#8217; subforms outer elements is selected and applied upon a jQuery plugin. This plugin (<a href="http://github.com/TBeijen/Zend_Form_Dynamic/blob/master/htdocs/js/jquery.dynamicform.js">on GitHub</a>)performs the following tasks:</p>
<ul>
<li>Within the element it operates on it searches for an element with classname &#8216;add&#8217; and attaches a &#8216;click&#8217; event handler to it.</li>
<li>It searches for an element &#8216;template&#8217; and stores a reference to it.</li>
<li>Whenever the user clicks the &#8216;add&#8217; button, the template element is cloned</li>
<li>Within the template element the &#8216;name&#8217; attribute of any input element is altered: The string &#8216;__template__&#8217; is replaced by a timestamp. This makes sure that multiple new tasks can be added within a day without them interfering with each other.</li>
<li>The new element is placed after the last found element with classname &#8216;task&#8217;</li>
</ul>
<p>By referring to classnames, the javascript&#8217;s dependencies on the exact HTML are kept to a minimum. This way, if needed, the HTML structure of the form elements can be changed without the need to update the javascript.</p>
<h3>Having the form process the new elements</h3>
<p>When the task form is submitted, newly added tasks will be in the $_POST array as shown below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// is assoc. array having 'desc' and 'completed' keys</span>
<span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$dayTimestamp</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$uniqueJSCreatedValue</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The form object needs to be able to validate the input for both the existing and the new tasks, so the $_POST array is passed to the isValid() method. At this point the form doesn&#8217;t yet contain the &#8216;new&#8217; elements. Adding those is done in a similar fashion to how the existing elements are added in setDefaults(), only this time it is done in isValid(). That is the first point where the form is able to determine what the new elements are. Dynamically adding the new elements happens in the &#8216;day&#8217; subform:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_SubForm_TaskDay <span style="color: #000000; font-weight: bold;">extends</span> Zend_Form_SubForm
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isValid<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$subform</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubForm</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// make sure new is array (won't be in $data if nothing submitted)</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$idx</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// Don't add element with idx = __template__. SetIgnore works on</span>
            <span style="color: #666666; font-style: italic;">// getValues. Template elements are submitted so this would otherwise</span>
            <span style="color: #666666; font-style: italic;">// override the previously added template element, thereby losing the</span>
            <span style="color: #666666; font-style: italic;">// setIgnore setting...</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$idx</span> <span style="color: #339933;">!==</span> <span style="color: #0000ff;">'__template__'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$subform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createTaskElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$idx</span><span style="color: #339933;">,</span> <span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">// call parent, which will populate newly created elements.</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">//...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Here the aforementioned createTaskElement() method pops up again. Notice the third parameter (true) that will make the validator treat the element as a &#8216;new&#8217; one.</p>
<h3>All done, except for &#8230; </h3>
<p>In theory now everything works. But practice tends to have those little things that go wrong which you hardly ever read about in code examples. When working on this example I noticed that getValues() doesn&#8217;t preserve the per-day timestamp keys in the array returned. Instead, it returns an indexed array like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$getValues</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #666666; font-style: italic;">// this '0' should have been a timestamp, like: 1261350000</span>
    <span style="color: #0000ff;">'0'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'current'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// etc. etc.</span>
        <span style="color: #0000ff;">'new'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// etc. etc.</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Bummer. As it appears, Zend_Form &#8216;requires&#8217; elements, subforms and display groups to have valid variable names (See <a href="http://framework.zend.com/issues/browse/ZF-4204">ZF-4204</a>). One of the reasons is problably that the names also end up in HTML id attributes which are not allowed to start with a number. The name attribute <em>is</em> though (you can run the demo form through the W3C validator). Remarkably, the task elements, having a name consisting of the database id, are processed just fine.</p>
<p>Two possible solutions for this:</p>
<ul>
<li>Avoid numeric names. Downside is that this also involves changing the existing code generating and processing the array. The day-form header decorator which uses the form&#8217;s name to display the date needs to be changed as well.</li>
<li>Add an implementation of getValues() in My_Form_TaskWeek that checks for numeric keys and changes them back to their original timestamp</li>
</ul>
<p>I choose the latter (for now) because it allows to leave almost all existing code unaltered and the resulting behaviour is unit testable (supply defaults, test what is rendered, test what is returned, etc.).</p>
<h3>Conclusion</h3>
<p>The above shows that:</p>
<ul>
<li>Subforms are very useful to repeat similar blocks within a form and to group related values in the returned value array.</li>
<li>Dynamically adding initial and newly submitted elements follows a similar pattern: Add elements based on the passed in array and then call the parent&#8217;s method. This is done in setDefaults() and isValid() respectively.</li>
</ul>
<p>The question might arise &#8216;is Zend_Form the best solution for this type of customized form?&#8217;. The default ViewHelper decorator is ignored, no default validator is used. I can&#8217;t tell if Zend_Form is the <em>best</em> solution but fact is that it provides a lot of functionallity and flexibility: The Form, Errors and HtmlTag decorators are used &#8216;as is&#8217;. Furthermore, the option to reuse parts comes almost naturally because of Zend_Form&#8217;s design.</p>
<p>Regarding the last point I&#8217;ll conclude with following example: What if, some time after having created this form, the idea is born to have some sort of per-day dashboard page where a user can view and edit things like calendar, messages and tasks? (This is the kind of stuff that happens in agile projects). Reusing My_SubForm_TaskDay would be very useful. And luckily that is easily accomplished. All that is needed is wrapping the subform in a class that will additionally:</p>
<ul>
<li>Set a view object</li>
<li>Add a submit button</li>
<li>Add a Form decorator</li>
</ul>
<p>See the code of <a href="http://github.com/TBeijen/Zend_Form_Dynamic/blob/master/htdocs/My_Form_TaskDay.php">My_Form_TaskDay on GitHub</a> or <a href="/static/zend_form_dynamic/day_only.php">see it in action online</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2009/12/21/zend_form-building-dynamic-forms/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2009/12/21/zend_form-building-dynamic-forms/</feedburner:origLink></item>
		<item>
		<title>Using Zend_Form without Zend Framework MVC</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/r8JdDT2F6Ro/</link>
		<comments>http://www.tibobeijen.nl/blog/2009/12/07/using-zend_form-without-zend-framework-mvc/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 10:13:13 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[zend_form]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=568</guid>
		<description><![CDATA[Most components of Zend Framework can be used without using the entire framework and Zend_Form is no exception. It&#8217;s a versatile component that can be customized to great extent. The payoff is that seemingly easy tasks can seem quite complex to complete and involve concepts like Decorators and View Helpers. Complexity is increased by the [...]]]></description>
			<content:encoded><![CDATA[<p>Most components of <a href="http://framework.zend.com/">Zend Framework</a> can be used without using the entire framework and <a href="http://framework.zend.com/manual/en/zend.form.html">Zend_Form</a> is no exception. It&#8217;s a versatile component that can be customized to great extent. The payoff is that seemingly easy tasks can seem quite complex to complete and involve concepts like Decorators and View Helpers. Complexity is increased by the fact that most tasks can be achieved in multiple ways.</p>
<p>Forms in general are elements where a lot of parts of an application &#8216;meet&#8217;: Frontend code (HTML/CSS), behavior (JS) and backend processing (validation, filtering and storage). In this post I&#8217;ll show how one can:</p>
<ul>
<li>Use Zend_Form outside the Zend Framework MVC (most likely an existing project)</li>
<li>Separate Form rendering from it&#8217;s structure</li>
<li>Use custom validators and decorators</li>
</ul>
<p>The Form used in this tutorial can be <a href="/static/zend_form_without_mvc/">viewed here</a>. The code can be browsed or downloaded <a href="http://github.com/TBeijen/Zend_Form_Without_MVC">on GitHub</a>.</p>
<h3>Zend_Form components at a glance</h3>
<p>Let&#8217;s start with a quick look at how Zend_Form&#8217;s different components are tied together:</p>
<ul>
<li>A Zend_Form consists of elements, descendants of Zend_Form_Element</li>
<li>Elements can be supplied with Validators and Filters</li>
<li>Both the form and it&#8217;s elements depend on Decorators to generate HTML. Decorators form a &#8216;chain&#8217; where each decorator adds HTML to the result of the previous decorators.</li>
<li>The standard decorators provided by Zend_Form delegate the rendering of the actual HTML to <a href="http://framework.zend.com/manual/en/zend.view.helpers.html">View Helpers</a></li>
</ul>
<h3>Using Zend_Form without the MVC</h3>
<p>As the last point above shows, Zend_Form, through Decorators, makes extensive use of Zend_View helpers. In a Zend_Framework project Zend_Form is able to retrieve the View itself. In other projects (if one wants to use any of Zend_Form&#8217;s default decorators) a View instance has to be supplied to Zend_Form:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$view</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_View<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">doctype</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'XHTML1_TRANSITIONAL'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setView</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_View<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>In this example the doctype is specified in the view. This controls if input elements are rendered with XHTML self-closing tags.</p>
<h3>Separate structure and rendering</h3>
<p>In this tutorial I create a form for an admin interface where basic user-details can be edited. Let&#8217;s assume an ACL implementation dictates that some people can actually <em>edit </em>the details while others are only allowed to <em>view </em>them. I&#8217;ve decided to keep the form definition (the &#8216;model&#8217; side of a form) to a bare minimum and let different renderers (the &#8216;view&#8217; side) control the output. </p>
<p>For re-usability and keeping controller code clean one can best create form objects by creating an instance of a subclass of Zend_Form:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Form_User <span style="color: #000000; font-weight: bold;">extends</span> Zend_Form
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// username</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'username'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'validators'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #666666; font-style: italic;">// arguments: type, breakchain, validator constructor options</span>
                <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Alnum'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
                <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'StringLength'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">16</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// email</span>
        <span style="color: #000088;">$EmailValidate</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Validator_Email<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'email'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'validators'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EmailAddress'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
                <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$EmailValidate</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>(As can be seen I create an instance of My_Validate_Email and add that to the email element. We&#8217;ll look into that later. First, let&#8217;s continue with the form definition.)</p>
<p>The init() method is designed for this type of form definition, thereby avoiding the need to duplicate the constructor and it&#8217;s parameter scheme. As can be seen, I only define the form elements and validators. Labels and such I defer to the renderer (more on that later). As this is about integrating Zend_Form into existing projects that are not based on Zend Framework, I assume there is some sort of language-aware component. In this example I use a language pack that returns language-specific results based on tags. Adding a set of checkboxes then looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Form_User <span style="color: #000000; font-weight: bold;">extends</span> Zend_Form
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
        <span style="color: #000088;">$lang</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_LanguagePack<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$groupIds</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><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>
        <span style="color: #000088;">$groupOptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$groupIds</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$groupOptions</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'group.label.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$elmGroup</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Form_Element_MultiCheckbox<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'group'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elmGroup</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMultiOptions</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$groupOptions</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elmGroup</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setRequired</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addElement</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$elmGroup</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now I create two renderer classes for both the &#8216;edit&#8217; and &#8216;view&#8217; display mode. Both accepting a Zend_Form instance in the constructor. Code below shows how the form is displayed using either rendering class:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Form_User<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$RendererEdit</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Form_Renderer_Edit<span style="color: #009900;">&#40;</span><span style="color: #000088;">$Form</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user_edit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$RendererEdit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$RendererView</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Form_Renderer_View<span style="color: #009900;">&#40;</span><span style="color: #000088;">$Form</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user_view'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$RendererView</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>But before moving onto the renderers, let&#8217;s look into the aforementioned My_Email_Validator class.</p>
<h3>Adding a custom validator</h3>
<p>When specifying validators by string, as is done with &#8216;EmailAddress&#8217;, Zend_Form adds one of the types of <a href="http://framework.zend.com/manual/en/zend.validate.html">Zend_Validate</a>. For validation not covered by the standard validators one can create a custom validator by extending Zend_Validate_Abstract or implementing Zend_Validator_Interface. For email addresses, a typical scenario would be a custom validator that connects to a database and checks if the given email address is allready used by another user. For this demo I skip the database part, resulting in:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Validator_Email <span style="color: #000000; font-weight: bold;">extends</span> Zend_Validate_Abstract
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$isValid</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isValid<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span> <span style="color: #339933;">=</span> <span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'duplicate@test.com'</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getMessages<span style="color: #009900;">&#40;</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'duplicateEmail'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'This email address is allready used'</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getErrors<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessages</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now let&#8217;s continue with the two renderer classes:</p>
<h3>Rendering the edit mode</h3>
<p>The basics of the My_Form_Renderer_Edit class constructor are shown below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> My_Form_Renderer_Edit
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$lang</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Zend_Form <span style="color: #000088;">$form</span><span style="color: #339933;">,</span> <span style="color: #000088;">$form_id</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$view</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_View<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">doctype</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'XHTML1_TRANSITIONAL'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setView</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Zend_View<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttrib</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'form_edit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form_id</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttrib</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$form_id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_LanguagePack<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As can be seen this is where I setup the view (as mentioned before) and set id and classname that can be used in CSS. I want the HTML to look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ul<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;li</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;username-label&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;label</span> <span style="color: #000066;">for</span>=<span style="color: #ff0000;">&quot;username&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;required&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>* Username<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/label<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;element&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;username&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;username&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;span</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;description&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>(Min 6, max 16 char.)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ul<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>When the render() method is called on the renderer class I do four things:</p>
<ul>
<li>Add a submit element</li>
<li>Setup element properties that are common for all elements</li>
<li>Setup properties on a per-element basis</li>
<li>Setup properties of the form element</li>
</ul>
<p>I&#8217;ll briefly run through those steps. <a href="http://github.com/TBeijen/Zend_Form_Without_MVC/blob/master/htdocs/My_Form_Renderer_Edit.php">Complete code for My_Form_Renderer_Edit</a> can be seen on Github.</p>
<h4>Add a submit element</h4>
<p>As long as the submit value doesn&#8217;t play a role in the processing of entered data I consider this part of the view layer. For example, interaction design might dictate that on long forms submit buttons are placed both above and below the form.</p>
<h4>Setup common properties</h4>
<p>By using the method setElementDecorators() of Zend_Form, all default decorators are replaced by the ones specified. The decorators that fit my needs are ViewHelper (renders the element itself) and Description, resulting in:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> setupElementsCommon<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
         <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setElementDecorators</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'ViewHelper'</span><span style="color: #339933;">,</span>
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Description'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'placement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'append'</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'tag'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'span'</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'description'</span>
            <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
         <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<h4>Setup per-element properties</h4>
<p>Here I add additional decorators. First I setup the element&#8217;s label and description properties by using the language pack, then I add the appropriate decorators. Furthermore I add some additional classnames to elements. If the element has an error I not only want to display the errors (using a custom decorator, more on that later). I also want to give the HTML element wrapped around all of the parts an &#8216;error&#8217; classname.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">        <span style="color: #000088;">$elmHasError</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessages</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$liClass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$elmHasError</span> ? <span style="color: #0000ff;">'error'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$elm</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDecorator</span><span style="color: #009900;">&#40;</span>
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'outerLi'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'HtmlTag'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tag'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'li'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$liClass</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h4>Setup the form object</h4>
<p>Finally the Form is configured. After removing all existing decorators, three decorators are added. The only difference with the default set of decorators is the UL element used in the HtmlTag decorator:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> setupForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearDecorators</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDecorator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FormElements'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDecorator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HtmlTag'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tag'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'ul'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDecorator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Adding a custom decorator</h3>
<p>The complete code shows that instead of the default &#8216;Errors&#8217; decorator I provide my own. This way I can retrieve the error messages provided by the form element and then replace them with messages retrieved from the languagePack. A custom decorator needs to extend Zend_Form_Decorator_Abstract or implement Zend_Form_Decorator_Interface. Excerpts from <a href="http://github.com/TBeijen/Zend_Form_Without_MVC/blob/master/htdocs/My_Decorator_Errors.php">My_Decorator_Errors</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000088;">$element</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getElement</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$errorMessages</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$element</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessages</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$errorMessages</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000088;">$content</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// iterate over errorMessages, replace or use default</span>
        <span style="color: #000088;">$errorLinesHtml</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$errorMessages</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$errorCode</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$errorMsg</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// make an exception for isEmpty and array representing elements</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$element</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$errorCode</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'isEmpty'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$msgLangPack</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form.error.array.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$errorCode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$msgLangPack</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form.error.'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$errorCode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #000088;">$errorMsg</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$msgLangPack</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$msgLangPack</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$errorMsg</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$errorLinesHtml</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;li&gt;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$errorMsg</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;/li&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">// combine</span>
        <span style="color: #000088;">$errorHtml</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'&lt;ul class=&quot;errors&quot;&gt;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$errorLinesHtml</span> <span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/ul&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// ...</span></pre></div></div>

<p>Errormessages are fetched by an element&#8217;s getMessages() method that returns an associative array. The error-codes (keys) can be used to translate the message. As can be seen I treat elements representing an array differently when fetching the &#8216;isEmpty&#8217; error message.</p>
<div class="sidenote">
<p>Why using a custom errors decorator and not setting the messages on the element?</p>
<p>setErrors() can be used to set own errors on Zend_Form_Element. Those errors are stored in property _errorMessages which is indeed cleared first. This doesn&#8217;t remove the messages received from the validators though as they are stored in _messages. Upon adding an error by setErrors() both arrays are merged into _messages (this happens in markAsError()) and that&#8217;s the one returned by getMessages(). So trying to replace the existing isEmpty error by &#8216;setting&#8217; a custom error effectively adds an error instead of replacing it. getErrorMessages() does return just the new errors but&#8230; the viewHelper formErrors (which is invoked by the default &#8216;Errors&#8217; decorator) uses getMessages()&#8230;</p>
</div>
<h3>Rendering the view mode</h3>
<p>The view renderer is a simplified version of the edit renderer. Main differences are:</p>
<ul>
<li>The form doesn&#8217;t have a Form decorator and thereby no form tag. (I&#8217;ll keep calling the no-form a form though ;)).</li>
<li>All elements have only one decorator common for all elements: My_Decorator_View_Element</li>
<li>As the only element decorator doesn&#8217;t use Zend_View, the form has no need for a View element.</li>
</ul>
<h4>My_Decorator_View_Element</h4>
<p>This decorator retrieves value and label from the element and creates. It then creates HTML making exceptions for:</p>
<ul>
<li>Submit elements (which are ignored)</li>
<li>Array representing elements (where more than one value needs to be displayed)</li>
</ul>
<h3>Concluding</h3>
<p>Above examples give an impression of how Zend_Form can be suited to virtually anyone&#8217;s needs. One can argue that separating the rendering from the basic definition adds unnecessary complexity. It does however pull HTML specifics (which during a project life-cycle often are subject to change) out of the &#8216;model&#8217; layer. Both the stripped down forms and renderers are easy to reuse: The renderer can be applied to a number of forms and the forms themselves can be used in projects requiring different HTML.</p>
<p>Even without considering the rendering part, Zend_Form is a valuable platform offering a lot of ways to customize it. As the view renderer example shows it can also operate without Zend_View, provided one doesn&#8217;t use any of the built in decorators. Being able to provide self-built elements, validators and decorators makes it possible to use Zend_Form in virtually any project.</p>
<p>Further reading:</p>
<ul>
<li><a href="http://framework.zend.com/apidoc/core/">Zend Framework API documentation</a></li>
<li><a href="http://devzone.zend.com/article/3450">Decorators with Zend_Form</a></li>
<li><a href="http://weierophinney.net/matthew/archives/215-Rendering-Zend_Form-decorators-individually.html">Rendering Zend Form decorators individually</a></li>
<li><a href="http://giorgiosironi.blogspot.com/2009/10/advanced-zendform-usage.html">Advanced Zend_Form usage</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2009/12/07/using-zend_form-without-zend-framework-mvc/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2009/12/07/using-zend_form-without-zend-framework-mvc/</feedburner:origLink></item>
		<item>
		<title>Fronteers 2009</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/2lil-H4-d58/</link>
		<comments>http://www.tibobeijen.nl/blog/2009/11/07/fronteers-2009/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 18:46:22 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[report]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[fronteers]]></category>
		<category><![CDATA[fronteers09]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[webdesign]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=555</guid>
		<description><![CDATA[About five months after having enjoyed server-side talks at DPC09 it was now time for front-end matters: Fronteers 2009. There&#8217;s no exaggeration in the description on the fronteers site: A stellar line up of speakers who are at the front of what&#8217;s happening in web-development. Generally speaking I really liked most of the talks and [...]]]></description>
			<content:encoded><![CDATA[<p>About five months after having enjoyed server-side talks at <a href="http://www.tibobeijen.nl/blog/2009/06/13/dpc09-down-dpc10-to-go/">DPC09</a> it was now time for front-end matters: Fronteers 2009. There&#8217;s no exaggeration in the description on the fronteers site: A <a href="http://fronteers.nl/congres/2009/speakers">stellar line up</a> of speakers who are at the front of what&#8217;s happening in web-development. Generally speaking I really liked most of the talks and some of them pointed me to some interesting new techniques and ideas.</p>
<p>Slides of the presentation (if online) are listed at the <a href="http://fronteers.nl/blog/2009/11/presentations-fronteers-2009">Fronteers site</a> and at the end of this post (same content, read along). I&#8217;ll briefly recap some of the (for me that is) most interesting parts.<br />
<span id="more-555"></span></p>
<h3>Thursday</h3>
<p>After a pre-conference meeting tuesday at Mirabeau (Where Chris Heilmann and Peter Paul Koch hinted at what was to come) Thursday started with two talks concentrating on the mobile web. Summarized: Webkit is not webkit (and webkit is just one of the mobile browsers) and mobile devices are more different from each-other than desktop PC&#8217;s. So, developing for the mobile web (and not just the iPhone) is challenging. </p>
<p>Next on was the presentation with the most hilarious title of all (and arguably content also) by Chris Heilman: <a href="http://www.wait-till-i.com/2009/11/05/of-hamsters-feature-creatures-and-missed-opportunities-my-talk-at-fronteers-2009/">Of Hamsters, Feature Creatures and Missed Opportunities</a>. Some highlights: Be passionate about what you do as a developer or leave that aspect for someone who <em>is</em>. Don&#8217;t reinvent the wheel just because you like to apply a (your favorite) technique. The web is information, not sites. The feature creature (just check the slides) and <a href="http://developer.yahoo.com/yql/console/">YQL</a>, which basically is querying the web and looks really great (kinda missed out on that one having done a lot of back-end development lately).</p>
<p>After the lunch-break Stephen Hay covered three drafts that exist for CSS layouts that will take away the limitations that exist today: CSS3-Grid (Microsoft), CSS3-Flexbox (Mozilla) and CSS3-Layout (W3C). Very interesting as it makes very clear that, although a vast improvement over tables, today&#8217;s CSS capabilities with respect to layout (and thereby the way we work) are far from perfect.<br />
Following Stephen, John Resig went in-depth on javascript testing techniques covering unit testing as well as functional testing. Furthermore an interesting testing concept that can be used for testing JS frameworks was introduced: <a href="http://testswarm.com/">TestSwarm</a>. Steve Souders, fully aware of being the last barrier between the crowd and the after-party, concluded the day with some interesting techniques that can help speed up websites.</p>
<h3>Friday</h3>
<p>Douglas Crockford kicked of day 2 with a presentation about javascript security. He explained <a href="http://en.wikipedia.org/wiki/Object-capability_model">Object Capapability Design</a>, a security model in which objects can only access objects they have a reference too. I liked the part about using &#8216;facet objects&#8217; to control whether or not references are maintained or broken. After that Pete LePage showed some HTML5 stuff that&#8217;s found it&#8217;s way into IE8. The presentation had a (not the only one) funny moment where in Expression Web&#8217;s IE6 emulation it showed the fronteers website with the &#8216;your (IE6) browser is obsolete&#8217; warning. Jonathan Snook then extensively covered the topic of getting fonts on the web. It was very interesting that he addressed the licensing issues involved with using tools like sIFR. Something I think is often overlooked.</p>
<p>After the lunch Robbert Broersma lifted the hood (just slightly) of the engine powering the Xopus editor. He showed some tips with regard to improving and maintaining performance, most notably <a href="http://www.google.nl/search?q=leak+free+closures">Google for &#8216;leak free closures&#8217;</a>. Thomas Fuchs took over and explained some of the animation scripting going on in <a href="http://scripty2.com/">scripty2</a> and showcased his lightweight animation library <a href="http://github.com/madrobby/emile">emile.js</a>.</p>
<p>Next presentation was by Nicolle Sullivan and the title &#8216;Object Oriented CSS&#8217; made me quite curious. Rightly so cause I really enjoyed this presentation. OOP concepts like code reuse, encapsulation, singletons and inheritance were put into the perspective of organizing CSS. Quite a different approach really but it addresses problems I think a lot off css-coders can relate to. I found it interesting to realize that OOP thinking, which for me is day-to-day practice when working with PHP, somehow hadn&#8217;t made it to my CSS approach. At least not to the extent as shown in this presentation.</p>
<p>The day concluded with Dion Almaer and Ben Galbraith talking about &#8216;The Future of Web Applications&#8217;. Very entertaining presentation covering new technologies like <a href="http://code.google.com/closure/">Google Closure Tools</a> (Quoting: &#8216;If you want to write code that looks like java then it&#8217;s a great tool for you&#8217;), canvas, web workers and webGL.</p>
<p>Conclusion: Very nice conference with indeed a stellar line-up. As always the hallway sessions are not to be underestimated as I usually (unless I&#8217;m tired or need to get things done) find it interesting to talk to other people and pick up some new ideas or approaches. To conclude with the closing presentation&#8217;s very fitting last commandments (yes, I wrote those down):</p>
<ul>
<li>Thou shalt make thine interfaces responsive</li>
<li>Thou shalt keep the data of thy users holy</li>
</ul>
<ul>
<li><a href="http://search.twitter.com/search?q=&#038;ands=&#038;phrase=&#038;ors=&#038;nots=&#038;tag=fronteers09&#038;lang=all&#038;from=&#038;to=&#038;ref=&#038;near=&#038;within=15&#038;units=mi&#038;since=&#038;until=&#038;rpp=15">Twitter: #fronteers09</a></li>
<li><a href="http://www.flickr.com/search/?q=fronteers09&#038;s=int">Flickr: fronteers09</a></li>
</ul>
<h3>Presentations</h3>
<p>Just to show that YQL literally <em>is</em> &#8216;querying the web&#8217;: The YQL below extracts from the <a href="http://fronteers.nl/blog/2009/11/presentations-fronteers-2009">Fronteers 2009 presentations</a> page those elements in the list that have a link. And&#8230; it always returns valid xml which makes it ideal for parsing the <del datetime="2009-11-08T19:21:45+00:00">HTML</del> cruft generated by some applications.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> html 
<span style="color: #993333; font-weight: bold;">WHERE</span> url<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://fronteers.nl/blog/2009/11/presentations-fronteers-2009&quot;</span> 
<span style="color: #993333; font-weight: bold;">AND</span> xpath<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;//ol/li/p/a/ancestor::li&quot;</span></pre></div></div>

<ul class="paragraphs">
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2009/11/07/fronteers-2009/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2009/11/07/fronteers-2009/</feedburner:origLink></item>
		<item>
		<title>Catching PHP Exceptions: Except the unexpected</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/gcnlwRHBzgI/</link>
		<comments>http://www.tibobeijen.nl/blog/2009/10/26/catching-php-exceptions-except-the-unexpected/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 11:57:20 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=527</guid>
		<description><![CDATA[PHP Exceptions can greatly assist in implementing various error scenario&#8217;s into an application. Before PHP5 one had to resort to specific return values or drastic measures like trigger_error(). Planning exceptions, I found out, is just as important as class design. At any point where a developer needs to handle the possibility of an exception being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://us.php.net/manual/en/language.exceptions.php">PHP Exceptions</a> can greatly assist in implementing various error scenario&#8217;s into an application. Before PHP5 one had to resort to specific return values or drastic measures like <a href="http://us.php.net/manual/en/function.trigger-error.php">trigger_error()</a>. Planning exceptions, I found out, is just as important as class design. At any point where a developer needs to handle the possibility of an exception being thrown he needs to know: </p>
<ul>
<li>What Exceptions can I expect?</li>
<li>What Exceptions do I plan to catch?</li>
</ul>
<p>In this post I&#8217;ll show some important aspects to consider when planning exceptions.<br />
<span id="more-527"></span></p>
<h3>The Basic Exception</h3>
<p>Let&#8217;s assume a Soap-based web-service client class used to submit order-data to a supplier&#8217;s web-service. The web-service client throws an exception if required configuration parameters are missing. The actual SoapClient object will be initialized when the first webservice method is called.</p>
<p>Web-service client class:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> WsSoapClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$config</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$soapClient</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$config</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initSoapClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soapClient</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">submitOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toSoapParam</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> initSoapClient<span style="color: #009900;">&#40;</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: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soapClient</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">wsdl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Configuration error'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soapClient</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SoapClient<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">wsdl</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Application code:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> Registry<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$client</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WsSoapClient<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
try <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">submitOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// We need to act on this asap...</span>
    <span style="color: #000088;">$AppError</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">register_error</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// Redirect to application error page</span>
    <span style="color: #000088;">$Redirect</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In case of a configuration error a redirect is performed to an application-error page. And (just an example) some mechanism is triggered that starts to bug a (or all) developers that there&#8217;s a problem that needs immediate attention. </p>
<h3>Knowing what to catch</h3>
<p>There are of course errors that are less disastrous. Web-services can be down so we need to cope with that, resulting in the modifications below:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> WsSoapClientException <span style="color: #000000; font-weight: bold;">extends</span> Exception <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsSoapClientConfigurationException <span style="color: #000000; font-weight: bold;">extends</span> WsSoapClientException<span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsSoapClientConnectionException <span style="color: #000000; font-weight: bold;">extends</span> WsSoapClientException<span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> WsSoapClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> initSoapClient<span style="color: #009900;">&#40;</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: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soapClient</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">wsdl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> WsSoapClientConfigurationException<span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'Configuration error'</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        try <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soapClient</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SoapClient<span style="color: #009900;">&#40;</span>
                <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">wsdl</span><span style="color: #339933;">,</span> 
                <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'exceptions'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>SoapFault <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> WsSoapClientConnectionException<span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'Cannot load WSDL: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">wsdl</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$client</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WsSoapClient<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
try <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">submitOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>WsSoapClientConnectionException <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// store the order in a queue to be processed later</span>
    <span style="color: #000088;">$Order</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">queue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$Redirect</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Page</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'OrderQueued'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Catch everything, also WsSoapClientConfigurationException</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// We need to act on this asap...</span>
    <span style="color: #000088;">$AppError</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">register_error</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// Redirect to application error page</span>
    <span style="color: #000088;">$Redirect</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Two things have changed:</p>
<h4>Extending exception types</h4>
<p>Exception classes have been defined for specific errors. They both extend an Exception class that is specific for the WsSoapClient class. This allows us to catch specific exceptions, like is done with WsSoapClientConnectionException. We could also catch all exceptions directly thrown by WsSoapClient by catching WsSoapClientException. When defining exception types one might take <a href="http://us.php.net/manual/en/spl.exceptions.php">SPL Exceptions</a> as a starting point.</p>
<h4>Rethrowing exceptions</h4>
<p>A SoapFault exception is caught and a WsSoapClientConnectionException is thrown instead. Now one might wonder: Why? Couldn&#8217;t I just as well catch SoapFault in the application code? That brings us to the next section.</p>
<h3>Knowing what to expect</h3>
<p>In the previous example we simply used one WsSoapClient class to handle all web-service related communications. Now imagine that we have different suppliers that (inevitably) offer different types of web-services for us to use. Besides a client that handles Soap we now also need a client that handles XML-RPC.</p>
<p>After reading up a bit on <a href="http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29">Design Patterns</a> we decide to introduce a <a href="http://www.ibm.com/developerworks/library/os-php-designptrns/#N10076">Factory</a> that returns the proper web-service client for the order, which we supply in the method call.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> WsClientFactory
<span style="color: #009900;">&#123;</span>
    static <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getWsClient<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">supplier</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'supplierA'</span><span style="color: #339933;">:</span>
                <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">new</span> WsSoapClient<span style="color: #009900;">&#40;</span>
                    Registry<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">soap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">supplierA</span>
                <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'supplierB'</span><span style="color: #339933;">:</span>
                <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">new</span> WsXmlRpcClient<span style="color: #009900;">&#40;</span>
                    Registry<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">xmlrpc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">supplierB</span>
                <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Briefly put: The point of a factory is to avoid the &#8216;new&#8217; keyword by allowing it to return various class instances. To know what callable methods to expect on the returned object, the possible object types need to implement a common interface or extend a common (abstract) class. We define an interface WsClient and let the two client types implement it:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">interface</span> WsClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsSoapClient implements WsClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// submitting order to soap webservice</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsXmlRpcClient implements WsClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// submitting order to xml-rpc webservice</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now if we take a look at our original application code it becomes obvious that we are not finished yet.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$client</span> <span style="color: #339933;">=</span> WsClientFactory<span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
try <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">submitOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>WsSoapClientConnectionException <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Now what if there's a XML-RPC client throwing other exceptions?</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We could catch WsXmlRpcClientConnectException as well but that&#8217;s not the way to go for two obvious reasons:</p>
<ol>
<li>We would be duplicating the code in the catch blocks</li>
<li>If later we need to add a WsEmailClient class, we would need to update both the factory and all the try-catch blocks in the application.</li>
</ol>
<h4>Abstracting exceptions</h4>
<p>As the client types implement a common interface we can also define a set of exceptions that are thrown by all classes implementing that interface:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> WsClientException <span style="color: #000000; font-weight: bold;">extends</span> Exception <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsClientConfigurationException <span style="color: #000000; font-weight: bold;">extends</span> WsClientException<span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsClientConnectionException <span style="color: #000000; font-weight: bold;">extends</span> WsClientException<span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">interface</span> WsClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The classes implementing WsClient:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> WsSoapClient implements WsClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initSoapClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> initSoapClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Might throw: WsClientConfigurationException</span>
        <span style="color: #666666; font-style: italic;">// Might throw: WsClientConnectionException</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">class</span> WsXmlRpcClient implements WsClient
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span>Order <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initXmlRpcClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> initXmlRpcClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Might throw: WsClientConfigurationException</span>
        <span style="color: #666666; font-style: italic;">// Might throw: WsClientConnectionException</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The application code retrieving an object from the factory now knows what exception types to expect:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$client</span> <span style="color: #339933;">=</span> WsClientFactory<span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
try <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$client</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">submitOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>WsClientConnectionException <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Now we know what to expect</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Wrapping it up</h3>
<p>What the above shows is that:</p>
<ul>
<li>Throwing a default &#8216;Exception&#8217; is bad practice if you ever want to act on that specific error scenario. Without extending the Exception class you can only catch all or none.</li>
<li>New exceptions can be thrown in catch blocks. That way it&#8217;s possible to prevent unexpected exception types to cross certain application design boundaries.</li>
<li>Once class design involves abstract classes or interfaces it is wise to design exception structures as well and organize them in similar layers of abstraction.</li>
</ul>
<p>Using above &#8216;rules of thumb&#8217; will hopefully help in using exceptions to maximum effect. The above mainly covers the structure of exceptions and not so much functionally that can be added to an exception subclass. Ideas to consider:</p>
<ul>
<li>Adding listeners to an Exception that might write exceptions to a log. Beware though: There&#8217;s probably no need to log &#8216;expected exceptions&#8217; and every disk-write is a small hit on performance.</li>
<li>Adding the caught exception to the new exception that is being re-thrown.</li>
</ul>
<p>Do you think I&#8217;ve left out important parts or are you using (entirely) different exception strategies? Feel free to comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2009/10/26/catching-php-exceptions-except-the-unexpected/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2009/10/26/catching-php-exceptions-except-the-unexpected/</feedburner:origLink></item>
		<item>
		<title>Usability: What does this button do?</title>
		<link>http://feedproxy.google.com/~r/tbnl/~3/NZTG2y_zAow/</link>
		<comments>http://www.tibobeijen.nl/blog/2009/10/09/usability-what-does-this-button-do/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 14:01:48 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[graphic design]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=484</guid>
		<description><![CDATA[In software development projects, paying proper attention to usability aspects, can greatly help &#8216;getting the message functionality across&#8217;. Usability is a field of expertise on its own and involves techniques like wireframes, prototyping and card sorting. Not every project is the same and (sadly) lack of time or budget can prevent specialized interaction designers to [...]]]></description>
			<content:encoded><![CDATA[<p>In software development projects, paying proper attention to usability aspects, can greatly help &#8216;getting the <del datetime="2009-09-20T10:22:43+00:00">message </del>functionality across&#8217;. <a href="http://en.wikipedia.org/wiki/Usability">Usability</a> is a field of expertise on its own and involves techniques like <a href="http://www.usabilityfirst.com/glossary/term_645.txl">wireframes</a>, <a href="http://www.usabilitynet.org/tools/prototyping.htm">prototyping</a> and <a href="http://en.wikipedia.org/wiki/Card_sorting">card sorting</a>. Not every project is the same and (sadly) lack of time or budget can prevent specialized interaction designers to be involved in the project. This means that making the application &#8216;usable&#8217; becomes the responsibility of graphic designers or developers (or it is neglected altogether). Not an easy combination of tasks&#8230;<br />
<span id="more-484"></span><br />
When developing or visually designing an application one goes into much detail which makes it hard to step back and look at the application from an end user&#8217;s perspective. To help measure and improve usability there are numerous <a href="http://www.usereffect.com/topic/25-point-website-usability-checklist">usability checklists</a> out there, some of them focusing on <a href="http://www.alistapart.com/articles/sensibleforms">specific subjects like forms</a>. Such lists can be very complete (and thereby very long) and because of that difficult to continuously use during development. They tend to be more useful as an evaluation tool than as a development tool.</p>
<p>To help during development (or design) it helps to keep in mind that a user using an application is all about interaction and exchanging information. At any given moment while using an application, a user might wonder things like:</p>
<ul>
<li>What did that button do?</li>
<li>What will this button do?</li>
<li>What does this label mean?</li>
<li>How can I find the page I&#8217;m looking for?</li>
</ul>
<p>Summarized: action and information, past and future as illustrated below:<br />
<div id="attachment_501" class="wp-caption aligncenter" style="width: 510px"><img src="http://www.tibobeijen.nl/blog/wp-content/uploads/2009/09/usability_application_state_diagram_01.gif" alt="Usability: Application State Diagram" title="Usability: Application State Diagram" width="500" height="350" class="size-full wp-image-501" /><p class="wp-caption-text">Usability: Application State Diagram</p></div></p>
<h3>Four quadrants</h3>
<h4>I. Past actions</h4>
<p>This translates to &#8216;feedback&#8217;. Is it at any point clear to the user what the application is doing or has done, following the user&#8217;s commands? Is the feedback form sent? Are modifications done through the CMS visible online? Is the application really still busy or is something going wrong?</p>
<h4>II. Future actions</h4>
<p>Feed forward. For a user to &#8216;trust&#8217; an application he needs to be able to predict what will happen when he performs certain actions. Take for instance a webshop: After clicking &#8216;place order&#8217;, will there be a screen to review and possibly cancel the order process? Or, after saving a page in a CMS, will it be possible to preview a page before it&#8217;s visible on the live site?</p>
<h4>III. Past information</h4>
<p>This focuses mainly on how information is displayed at a given point. Is important information clearly recognizable? Is it clear what is displayed? For example a product page on a webshop: Can editorials and user comments be clearly distinguished?</p>
<h4>IV. Future information</h4>
<p>This covers navigation and thereby how all the information and possible interaction of an application is structured. To efficiently use an application a user needs to be able to predict where to find information and how to get there. This involves structuring navigation and perhaps also tailoring navigation to accommodate for common usage scenarios.</p>
<h3>What this diagram does not</h3>
<p>The above diagram focuses on the state of an application at a given point and therefore doesn&#8217;t look at the bigger picture. This means it doesn&#8217;t:</p>
<ul>
<li>Cover consistency throughout the application.</li>
<li>Prioritize functionality.</li>
<li>Match functionality with user goals.</li>
<li>Look into characteristics of the targetted users (like experience with similar applications) or the environment the application is used in.</li>
</ul>
<h3>What this diagram can do</h3>
<p>Taking back a step once in a while <em>during</em> development and applying this diagram on the application that is being created, can help to quickly point out certain usability flaws. This is especially true when there is no dedicated usability expert in the team. Having a certain amount of knowledge of the more elaborate checklists mentioned earlier will help. Besides being used as a quick evaluation tool this diagram can also be used to structure usability-related thoughts and ideas and predict their effectiveness. Hopefully that will help creating a better user experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2009/10/09/usability-what-does-this-button-do/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.tibobeijen.nl/blog/2009/10/09/usability-what-does-this-button-do/</feedburner:origLink></item>
	</channel>
</rss>
