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

<channel>
	<title>David's virtual world &#187; symfony</title>
	<atom:link href="http://blog.vworld.at/category/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.vworld.at</link>
	<description>Software development and software quality</description>
	<lastBuildDate>Wed, 17 Mar 2010 10:26:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>What to do when symfony cli colorization does not work on unix systems</title>
		<link>http://blog.vworld.at/2010/02/21/what-to-do-when-symfony-cli-colorization-does-not-work-on-unix-systems/</link>
		<comments>http://blog.vworld.at/2010/02/21/what-to-do-when-symfony-cli-colorization-does-not-work-on-unix-systems/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 13:03:57 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[command-line]]></category>
		<category><![CDATA[documentation]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=216</guid>
		<description><![CDATA[I recently ran into an interesting problem: symfony wouldn&#8217;t colorize the command-line output on any recently installed openSUSE (11.2) system. At first I was totally at a loss, but after diving into the code base and doing some debugging I finally found the core of the problem: the posix PHP extension was not installed.
So if [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.vworld.at/wp-content/uploads/sf-cli.png" alt="symfony CLI" title="sf-cli" width="138" height="141" class="alignright size-full wp-image-224" style="padding-left: 10px" />I recently ran into an interesting problem: symfony wouldn&#8217;t colorize the command-line output on any recently installed openSUSE (11.2) system. At first I was totally at a loss, but after diving into the code base and doing some debugging I finally found the core of the problem: the posix PHP extension was not installed.</p>
<p>So if any of you experience a similar issue, check if the extension is present and loaded. On openSUSE systems it&#8217;s enough to install the php5-posix package. Looks like the package maintainers start to leave out stuff that hardly anyone uses anymore, which is basically a good thing. It just caught me on the wrong foot <img src='http://blog.vworld.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>I <a href="http://trac.symfony-project.org/ticket/8312">filed a ticket</a> to include this in the symfony installation documentation because i couldn&#8217;t find it mentioned anywhere.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2010/02/21/what-to-do-when-symfony-cli-colorization-does-not-work-on-unix-systems/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Symfony Live 2010 review</title>
		<link>http://blog.vworld.at/2010/02/21/symfony-live-2010-review/</link>
		<comments>http://blog.vworld.at/2010/02/21/symfony-live-2010-review/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 22:00:28 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[Open source]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=200</guid>
		<description><![CDATA[The conference is over, I&#8217;m back in Vienna since Thursday evening and life has gone back to everyday normal. The city of Paris was quite interesting, I especially liked the broad architectural scope. Unfortunately I didn&#8217;t have much time for sightseeing. But let&#8217;s get back to why I was there, the symfony Live 2010 conference!
What [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.vworld.at/wp-content/uploads/sf-live.png" alt="Symfony Live" title="symfony live" width="150" height="149" class="alignright size-full wp-image-213" />The conference is over, I&#8217;m back in Vienna since Thursday evening and life has gone back to everyday normal. The city of Paris was quite interesting, I especially liked the broad architectural scope. Unfortunately I didn&#8217;t have much time for sightseeing. But let&#8217;s get back to why I was there, the <a href="http://www.symfony-live.com/">symfony Live 2010</a> conference!</p>
<h3>What was not so good</h3>
<p>Altogether I liked most talks, even the infamous Microsoft one, because each single talk provided knowledge I didn&#8217;t have before. There are some general issues I want to address though:</p>
<ul>
<li>Some speakers had a really bad French accent. I&#8217;m glad my English was good enough so I was able to follow all of them nevertheless, but for some listeners it must have been really hard.</li>
<li>Please please please provide portable headset microphones at future conferences. Speakers having to hold a microphone in their hands just look awkward, and it limits their freedom of movement and gestures. I mean, it&#8217;s not like headset mikes were ultra-future technology&#8230; This would also fix the &#8220;speaker A is much louder than speaker B because he holds the microphone too close&#8221; issue.</li>
<li>The Wi-Fi connection was really bad on the first day, but it was acceptable on the second. Looks like someone didn&#8217;t realize on time that there&#8217;d be hundreds of nerds with laptops present.</li>
<li>Please provide some way to get cola at future conferences, caffeine addicts will thank you for this, especially through the afternoon sessions <img src='http://blog.vworld.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li>The only speaker I really disliked was the second guy from the Microsoft team. If I want to be shouted at like that, I&#8217;ll visit a boot camp and insult some drill instructor, not attend a software conference!</li>
</ul>
<p>As said above the content of the talks was fine, although there were ups and downs of course. What was much more annoying was that some speakers seemingly didn&#8217;t know much about presenting stuff. This is of course acceptable for hacking nerds in general, but only until they have to speak at conferences. Please, guys, read some books about presentation techniques in advance before giving your next speech!</p>
<h3>What was great</h3>
<p>Let&#8217;s stop talking about failures and continue with things that require mentioning because they were great.</p>
<ul>
<li>The overall organization was cool and professional. If there were any troubles behind the scenes they were kept hidden from the audience, which is fine.</li>
<li>The food was good.</li>
<li>The twitter visualization on the big screen was a really cool thing to do.</li>
<li>The selection of talks was OK. It addressed both symfony newcomers and experienced listeners.</li>
<li>The truly outstanding speakers worth mentioning were in my opinion (in order of schedule):
<ul>
<li>John Cleveley: this talk set the bar for the first day. Clearly audible, great presentation, interesting content!</li>
<li>Jonathan Wage: obviously an experienced speaker too, with lots of detailed knowledge</li>
<li>Stefan Koopmanschap: although the session didn&#8217;t provide much new information for me it was nice to listen to. He knows how to handle crowds.</li>
<li>Lukas Kahwe Smith: unlike his companion (don&#8217;t remember the name) he was cool, professional and easy to understand.</li>
<li>Scott Chacon: that&#8217;s what a presentation has to be like. Just like that. The reference for the second day, which was altogether definitely better than the first one.</li>
<li>Fabien Potencier: Fabien knows how to savor his fame in situations like this and he has every right to do so! What he does and how he convinces people to follow his lead is just outstanding. Standing ovations for one of the most inspiring web developers nowadays!</li>
</ul>
</li>
</ul>
<p>Symfony Live 2010 was a huge gain for myself. I met lots of interesting people and collected tons of first-hand information. Since it was the first (but definitely not the last) symfony or PHP conference I attended, future events will show how it compares.</p>
<h3>Symfony 2 and the future</h3>
<p>Symfony 2 will be awesome. I also checked out the <a href="http://symfony-reloaded.org/">brand-new Symfony 2 web page</a>, which I recommend to everyone who is interested in PHP applications or frameworks.</p>
<p>It looks like <a href="http://www.phpbb.com/">phpBB</a> 4 will be built upon Symfony 2, which I personally really appreciate because phpBB was my stepladder into PHP development and the open source community around 2001. After switching to PHP5 and OOP style programming I started to disapprove of the phpBB development style. Hopefully there will be a turn around towards more best practices in the future!</p>
<h3>Before I forget it&#8230; the user stories</h3>
<p>On the first day Stefan Koopmanschap announced that symfony needs more people writing success stories helping others arguing in favor of symfony. Every publishable story provided until the end of the second day would win a set of symfony books. I couldn&#8217;t resist this offer and sat through the late evening in my hotel room hurting my fingers by typing on my netbook keyboard for 4 full hours. Since I had filed similar content as my speaker&#8217;s submission (which was unfortunately rejected) I knew there was enough interesting stuff to write about. It was worth the effort: I got 3 symfony books. Thanks to the symfony team!</p>
<p>I don&#8217;t know when my story will be published, but I&#8217;ll link it as soon as it is. The title is &#8220;Running a TV station with symfony&#8221;.</p>
<h3>Last but not least</h3>
<p><a href="http://www.devexp.eu/mr-t/">Toni</a>, I really would have liked meeting you, but it seems we just weren&#8217;t able to find each other. Let&#8217;s hope it will work next time <img src='http://blog.vworld.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>&lt;off-topic&gt; why is my Wordpress editor so damn slow recently? &lt;/off-topic&gt;</p>
<p>Update 2010-03-17: <a href="http://www.symfony-project.org/blog/2010/03/17/running-a-tv-station-with-symfony">Running a TV station with symfony</a> was published on the symfony blog today.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2010/02/21/symfony-live-2010-review/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Symfony Live 2010 has started</title>
		<link>http://blog.vworld.at/2010/02/16/symfony-live-2010-has-started/</link>
		<comments>http://blog.vworld.at/2010/02/16/symfony-live-2010-has-started/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 14:15:35 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[conference]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=196</guid>
		<description><![CDATA[Today Symfony Live 2010 has started. There have already been some interesting sessions, but the WiFi connection is awfully slow or even down most of the time.
]]></description>
			<content:encoded><![CDATA[<p>Today <a href="http://www.symfony-live.com/">Symfony Live 2010</a> has started. There have already been some interesting sessions, but the WiFi connection is awfully slow or even down most of the time.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2010/02/16/symfony-live-2010-has-started/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;ll be attending Symfony Live 2010</title>
		<link>http://blog.vworld.at/2009/09/29/ill-be-attending-symfony-live-2010/</link>
		<comments>http://blog.vworld.at/2009/09/29/ill-be-attending-symfony-live-2010/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 15:05:48 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[conference]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=184</guid>
		<description><![CDATA[Today I registered for the Symfony Live 2010 conference which will take place in Paris in February 2010. I&#8217;m looking forward to meeting lots of interesting people there!
]]></description>
			<content:encoded><![CDATA[<p>Today I registered for the <a href="http://www.symfony-live.com/">Symfony Live 2010 conference</a> which will take place in Paris in February 2010. I&#8217;m looking forward to meeting lots of interesting people there!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/09/29/ill-be-attending-symfony-live-2010/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Support symfony at the SourceForge.net Community Choice Awards 2009</title>
		<link>http://blog.vworld.at/2009/05/14/support-symfony-at-the-sourceforgenet-community-choice-awards-2009/</link>
		<comments>http://blog.vworld.at/2009/05/14/support-symfony-at-the-sourceforgenet-community-choice-awards-2009/#comments</comments>
		<pubDate>Thu, 14 May 2009 10:47:46 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Open source]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=179</guid>
		<description><![CDATA[The SourceForge.net Community Choice Awards are on again and it&#8217;s time to nominate the greatest rapid application development PHP framework: symfony!
I&#8217;ve nominated symfony in 3 categories:

Best Tool or Utility for Developers
Best Project
Best Commercial Open Source Project

Click the picture to nominate symfony too! Of course don&#8217;t forget to read and follow the nomination rules to allow [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://sourceforge.net/community/cca09/">SourceForge.net Community Choice Awards</a> are on again and it&#8217;s time to nominate the greatest rapid application development PHP framework: symfony!</p>
<p>I&#8217;ve nominated symfony in 3 categories:</p>
<ul>
<li>Best Tool or Utility for Developers</li>
<li>Best Project</li>
<li>Best Commercial Open Source Project</li>
</ul>
<p>Click the picture to nominate symfony too! Of course don&#8217;t forget to <strong>read and follow the nomination rules to allow for a fair voting process</strong>!<br />
<a href="http://sourceforge.net/community/cca09/nominate/?project_name=symfony PHP framework&#038;project_url=http://www.symfony-project.org/"><img src="http://sourceforge.net/images/cca/cca_nominate.png" border="0"/></a></p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/05/14/support-symfony-at-the-sourceforgenet-community-choice-awards-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>symfony at the &#8220;Linux weeks Vienna&#8221;</title>
		<link>http://blog.vworld.at/2009/04/15/symfony-at-the-linux-weeks-vienna/</link>
		<comments>http://blog.vworld.at/2009/04/15/symfony-at-the-linux-weeks-vienna/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 21:01:55 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Events]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=169</guid>
		<description><![CDATA[From April 16th to 18th the so-called Linux weeks will take place in the city hall of Vienna/Austria. There will be a symfony desk providing general information and exchange of personal experience using symfony. Bernhard Schussek and Klemens Ullmann, the heads behind webmozarts.com, will give 2 lectures about symfony in general and concrete projects. I [...]]]></description>
			<content:encoded><![CDATA[<p>From April 16th to 18th the so-called <em><a href="http://www.linuxwochen.at/index.php?option=com_content&#038;view=article&#038;id=4&#038;Itemid=32">Linux weeks</a></em> will take place in the city hall of Vienna/Austria. There will be a symfony desk providing general information and exchange of personal experience using symfony. Bernhard Schussek and Klemens Ullmann, the heads behind <a href="http://webmozarts.com/">webmozarts.com</a>, will give 2 lectures about symfony in general and concrete projects. I will be available at the symfony desk tomorrow (April 16th).</p>
<p>If you happen to be in Vienna at the time we&#8217;re looking forward to your visit!</p>
<p> Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/04/15/symfony-at-the-linux-weeks-vienna/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Improving the forms even more</title>
		<link>http://blog.vworld.at/2009/04/14/improving-the-forms-even-more/</link>
		<comments>http://blog.vworld.at/2009/04/14/improving-the-forms-even-more/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 07:38:02 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Forms]]></category>
		<category><![CDATA[OOp]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=149</guid>
		<description><![CDATA[After reading Bernhard&#8217;s great article about how the symfony forms framework could be enhanced I sat back and thought: how would I like the forms to be? What could be improved to increase my efficiency? Well, after 2 days of brain storming I have found those areas:

Field grouping
Field formatters
Required marks
Separators
Submit buttons
Help texts
I18n for everything


In my [...]]]></description>
			<content:encoded><![CDATA[<p>After reading <a href="http://webmozarts.com/2009/04/12/improving-the-forms/">Bernhard&#8217;s great article about how the symfony forms framework could be enhanced</a> I sat back and thought: how would I like the forms to be? What could be improved to increase my efficiency? Well, after 2 days of brain storming I have found those areas:</p>
<ul>
<li>Field grouping</li>
<li>Field formatters</li>
<li>Required marks</li>
<li>Separators</li>
<li>Submit buttons</li>
<li>Help texts</li>
<li>I18n for everything</li>
</ul>
<p><span id="more-149"></span><br />
In my current symfony project at work I&#8217;m using at least 9 different forms, tendency rising. There are lots of things that would help making most of them easier to use.</p>
<h3>Field grouping</h3>
<p>The <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.10">W3C HTML specification provides a clean solution to grouping form fields: <em>fieldset</em> and <em>legend</em> elements</a>. Symfony doesn&#8217;t support them by now, but I think they are crucial, since lots of people use them and they are quite easy to define.<br />
Looking at Bernhard&#8217;s code sample let&#8217;s suppose we want to group the username and email fields and then the password fields:</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> configure<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;">addGroup</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user_stuff'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Personal information'</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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfValidatorEmail<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addGroup</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password_stuff'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Password information'</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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> PasswordField<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password_again'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidget</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfWidgetPassword<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: #004000;">setValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfValidatorPass<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: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Password (again)'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>In my imagination this should render like this:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">fieldset</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;user_stuff&quot;</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">legend</span>&gt;</span>Personal information<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">legend</span>&gt;</span>
  <span style="color: #808080; font-style: italic;">&lt;!-- The name and email form fields go here --&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">fieldset</span>&gt;</span>
&nbsp;
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">fieldset</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;password_stuff&quot;</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">legend</span>&gt;</span>Password information<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">legend</span>&gt;</span>
  <span style="color: #808080; font-style: italic;">&lt;!-- The password form fields go here --&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">fieldset</span>&gt;</span></pre></div></div>

<p>The magic would be that &#8220;addGroup($name, $legendText)&#8221; would automatically close a previous group and add all further fields to the current group fieldset. To close a group manually and add the following fields to the global scope a closeGroup() method would be enough.<br />
The grouping HTML code would be defined in the form&#8217;s formatter, which can be enhanced easily:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfWidgetFormSchemaFormatterList <span style="color: #000000; font-weight: bold;">extends</span> sfWidgetFormSchemaFormatter
<span style="color: #009900;">&#123;</span>
  protected
    <span style="color: #666666; font-style: italic;">// other stuff</span>
    <span style="color: #000088;">$groupFormat</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&lt;fieldset&gt;<span style="color: #000099; font-weight: bold;">\n</span>  &lt;legend&gt;%legend%&lt;/legend&gt;<span style="color: #000099; font-weight: bold;">\n</span>  <span style="color: #009933; font-weight: bold;">%c</span>ontent%&lt;/fieldset&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And what if we add a form field later on that belongs to a previous group? Nothing easier than that!</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addFieldToGroup</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'surname'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user_stuff'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>At the end of the article you&#8217;ll see why I think it would be useful to have this in the form definition.</p>
<h3>Field formatters</h3>
<p>Besides the grouping my forms share one more thing: not all the fields are rendered the same way. Some of them require parameters to the <em>label</em> tag or just completely different row stylings. The solution to this at the moment: I have to generate the row myself. The drawback: I&#8217;m usually too lazy to include stuff like error rendering and if I change the formatter one day I have to manually alter all the custom form field rows. There&#8217;s only one summary for this: it sucks!<br />
Why not enable custom formatters per row? There&#8217;s not even a need to define something new, we can re-use the existing formatter code!</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> configure<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;">//  This is how formatters are defined now:</span>
<span style="color: #666666; font-style: italic;">//  $this-&gt;widgetSchema-&gt;setFormFormatterName('List');</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//  Make it more intuitive in the first place:</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFormatterName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'List'</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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfValidatorEmail<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> PasswordField<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #666666; font-style: italic;">// here it comes!</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFormatterName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'customPasswordFormat'</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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password_again'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidget</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfWidgetPassword<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: #004000;">setValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfValidatorPass<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: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Password (again)'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #666666; font-style: italic;">// and here!</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFormatterName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'customPasswordFormat'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>The only thing that changes here is that the 2 password fields would be formatted using another formatter. Everything else would stay the same. So simple and yet so powerful&#8230;</p>
<h3>Required marks</h3>
<p>There have been lots of discussions on the mailing lists how required fields should be displayed. My favourite solution would be to put this where all the other formatting stuff goes: to the formatter.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfWidgetFormSchemaFormatterList <span style="color: #000000; font-weight: bold;">extends</span> sfWidgetFormSchemaFormatter
<span style="color: #009900;">&#123;</span>
  protected
    <span style="color: #000088;">$rowFormat</span>       <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&lt;li&gt;<span style="color: #000099; font-weight: bold;">\n</span>  <span style="color: #009933; font-weight: bold;">%e</span>rror<span style="color: #009933; font-weight: bold;">%%</span>label<span style="color: #009933; font-weight: bold;">%%</span>required%<span style="color: #000099; font-weight: bold;">\n</span>  <span style="color: #009933; font-weight: bold;">%f</span>ield<span style="color: #009933; font-weight: bold;">%%</span>help%<span style="color: #000099; font-weight: bold;">\n</span>%hidden_fields%&lt;/li&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #666666; font-style: italic;">// other stuff</span>
    <span style="color: #000088;">$requiredFormat</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&lt;span&gt;*&lt;/span&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Combined with the ability to define custom styles per field this would be a powerful solution.<br />
Ah, there&#8217;s something else I would like to notice: defining the <em>required</em> property in the validator is fine from a techie-architect-point-of-view (as are so many other form related issues). But let&#8217;s once more see it from the user&#8217;s perspective:</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> configure<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;">// old way</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #339933;">,</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: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// what about this?</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</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></pre></div></div>

<p>See the difference? I&#8217;d personally like to have both options, but the second one would be much more intuitive from the user&#8217;s point of view.</p>
<h3>Separators</h3>
<p><em><strong>Update 2009-04-16: I&#8217;m not sure anymore that separators like I described them here are a good idea. I&#8217;ll keep the content unchanged for anyone to understand the discussion that followed. Keep in mind that all this is a kind of brain storming which naturally results in more storm than brain <img src='http://blog.vworld.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</strong></em></p>
<p>Separators are quite useful in templates when 2 form rows shouldn&#8217;t be too close to each other or separated visually using a horizontal line or whatever. In the template this is usually done like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderRow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;div class=&quot;separator&quot;&gt;&lt;/div&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderRow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Let&#8217;s extend the formatter first (you know what I&#8217;m getting at, don&#8217;t you?):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfWidgetFormSchemaFormatterList <span style="color: #000000; font-weight: bold;">extends</span> sfWidgetFormSchemaFormatter
<span style="color: #009900;">&#123;</span>
  protected
    <span style="color: #666666; font-style: italic;">// other stuff</span>
    <span style="color: #000088;">$separatorFormat</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'&lt;div class=&quot;separator&quot;&gt;&lt;/div&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now we can use it in the form code. And we can use different separators in the same form!</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> configure<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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSeparator</span><span style="color: #009900;">&#40;</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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfValidatorEmail<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSeparator</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFormatterName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'anotherSeparatorFormat'</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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">new</span> PasswordField<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>

<h3>Submit buttons</h3>
<p>Submit buttons belong to the form. They are even input widgets from a technical point of view. So why not add them to the form definition?</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> configure<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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</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;">// all the other fields </span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// solution 1</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'submit'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidget</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfWidgetSubmit<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Submit the form'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfValidatorPass<span style="color: #009900;">&#40;</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;">// solution 2</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSubmitButton</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'submit'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Submit the form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Together with the ability to use a specific formatter for the submit widget this would make every kind of submit button possible.</p>
<h3>Help texts</h3>
<p>So far the only possible way to add help texts to your form is passing them to the renderRow() method like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderRow</span><span style="color: #009900;">&#40;</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: #0000ff;">'Label text'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Help text'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Why is this separated from the form definition? Especially if the label is defined inside the form? Are there scenarios where the label stays the same but the help text changes? I don&#8217;t think so!<br />
Let&#8217;s try an alternative approach:</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> configure<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;">addField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidatorOptions</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'max_length'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Label text'</span><span style="color: #009900;">&#41;</span>
         <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHelp</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Help text'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>You see that this is mixing content with structure. But since most of the forms stuff is mixing content with structure (otherwise the labels should never have been in the form definition in the first place) why not allow to do it properly? And this leads to my last point:</p>
<h3>I18n for everything</h3>
<p>Symfony is great. Symfony has many powerful features. Symfony supports internationalization (short i18n) for everything. Everything? Not so! The form classes strictly defy being i18ned (sic!), making you wrap labels and help texts in <em>__()</em> functions in the template and hoping that the users don&#8217;t mind english error messages. Is there a reason for this? Of course: removing the form&#8217;s dependency to use an i18n instance. Is this necessary? I don&#8217;t think so:</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> configure<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;">enableI18n</span><span style="color: #009900;">&#40;</span>sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getI18n</span><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>Inject the i18n instance into the form. After that, everything could be translated: labels, help texts, messages, errors, even formatters! If you don&#8217;t want to use it, don&#8217;t. If you need it, make sure you get the damn i18n instance into the form somehow (there are solutions&#8230;). I know this is not easy because it changes how most of the widgets are rendered. But I think it would be worth the price.</p>
<h3>Why do I want all this stuff?</h3>
<p>That&#8217;s lots of feature requests. That&#8217;s lots of extensions and changes to the forms framework. But why? I can tell you! Because if all of the above features were available, <strong>80% of my form templates could look like this</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #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: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Wouldn&#8217;t that be worth it? Wouldn&#8217;t that help the core powers of symfony: KISS and DRY? I know that some projects have different people for generating form code and markup, but I think most work is done by the same developers. At least this would provide an option to do it differently.</p>
<p>Comments are welcome!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/04/14/improving-the-forms-even-more/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Creating a routing-based menu in symfony 1.2, part 4: the full package</title>
		<link>http://blog.vworld.at/2009/04/06/creating-a-routing-based-menu-in-symfony-12-part-4-the-full-package/</link>
		<comments>http://blog.vworld.at/2009/04/06/creating-a-routing-based-menu-in-symfony-12-part-4-the-full-package/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 13:49:40 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[menu]]></category>
		<category><![CDATA[OOp]]></category>
		<category><![CDATA[YAML]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=131</guid>
		<description><![CDATA[During the last 3 articles I showed you how to define the menu structure, generate sfMenuItem objects and create a builder that does all this for you. Today I want to present you the full package of my sfMenuBuilder and describe all the additional options I included.
Owing to a comment by Hugo HAMON, I decided [...]]]></description>
			<content:encoded><![CDATA[<p>During the last 3 articles I showed you how to define <a href="http://blog.vworld.at/2009/03/31/creating-a-routing-based-menu-in-symfony-12-part-1/">the menu structure</a>, generate <a href="http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-2-the-menuitem-object/">sfMenuItem objects</a> and <a href="http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-3-the-builder/">create a builder that does all this for you</a>. Today I want to present you the full package of my sfMenuBuilder and describe all the additional options I included.<br />
Owing to a comment by <a href="http://www.apprendre-php.com/">Hugo HAMON</a>, I decided to remove all external dependencies, so now the routing and i18n have to be injected, making i18n optional.</p>
<p><span id="more-131"></span></p>
<h3>Download the package</h3>
<p>For trying the sfMenuBuilder conveniently I have prepared a <a title="sfMenuBuilder v1.0" href="http://blog.vworld.at/download/sfMenuBuilder">zip package containing all the classes and some examples (yes, that&#8217;s the download link)</a>. Feel free to use it any way you like to!</p>
<p>The package contains the following files:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">config/
  example_app.yml
lib/
  menu_builder/
    sfMenuBuilder.class.php
    sfMenuItem.class.php
  resolver/
    sfObjectResolver.class.php
    sfObjectResolverInterface.class.php
examples.php
LICENSE</pre></div></div>

<p><em>config/example_app.yml</em> contains the markup and comprehensive documentation of a menu item in YAML &#8211; of course the parameters have to be the same wherever your menu structure is generated. In <em>examples.php</em> I placed some code showing how to create an <em>sfMenuBuilder</em> instance and how to render the menu either in tab levels or as a tree.</p>
<h3>New options in sfMenuBuilder</h3>
<p><em>sfMenuBuilder</em> now works as a multi-instance holder for <em>sfMenuBuilder</em> objects. It&#8217;s like a singleton with multiple named singletons, allowing you to create several menu definitions in parallel and at the same time holding them in a static container &#8211; this is especially important for helper functions where you would have to manually store the menus somewhere else.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfMenuBuilder <span style="color: #009900;">&#123;</span>
  protected static 
    <span style="color: #000088;">$instances</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>
&nbsp;
  protected
    <span style="color: #000088;">$menuItems</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: #000088;">$route</span>        <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$routeName</span>    <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$routeObject</span>  <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$i18n</span>         <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Initialize an instance of sfMenuBuilder with the given data and name.
   * If there is an existing instance with the same name it will be overwritten.
   * 
   * Since sfMenuBuilder needs the current sfContext to access the routing and 
   * request objects the context has to be provided as parameter. 
   * 
   * @param array $itemsData    Array of data to create sfMenuItem objects
   * @param sfRoute $route      The current sfRoute
   * @param string $routeName   The name of the current sfRoute
   * @param string $name        The name of the instance, optional, defaults to &quot;default&quot;
   * @param sfI18n $i18n        An instance of sfI18n to perform translations using __()
   * 
   * @return sfMenuBuilder      The newly created instance
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> initInstance<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$itemsData</span><span style="color: #339933;">,</span> sfRoute <span style="color: #000088;">$route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'default'</span><span style="color: #339933;">,</span> sfI18n <span style="color: #000088;">$i18n</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: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$instances</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuBuilder<span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemsData</span><span style="color: #339933;">,</span> <span style="color: #000088;">$route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$i18n</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$instances</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the instance for the given name parameter.
   * 
   * Warning: this does not create instances automatically! If you 
   * try to get an instance that doesn't exist, null will be returned!
   * 
   * @param string $name    The name of the instance to fetch
   * 
   * @return sfMenuBuilder  An sfMenuBuilder instance for the given name.
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> getInstance<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'default'</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$instances</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</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: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$instances</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Set to protected to prevent access from outside the singleton instance holder.
   * 
   * @param array $itemsData    Array of data to create sfMenuItem objects
   * @param sfRoute $route      The current sfRoute
   * @param string $routeName   The name of the current sfRoute
   * @param sfI18n $i18n        An instance of sfI18n to perform translations using __()
   */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$itemsData</span><span style="color: #339933;">,</span> sfRoute <span style="color: #000088;">$route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> sfI18n <span style="color: #000088;">$i18n</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$route</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">i18n</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i18n</span><span style="color: #339933;">;</span>
&nbsp;
    <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;">route</span> instanceof sfObjectRoute<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOptions</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: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'object'</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;">routeObject</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemsData</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$routeName</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$itemData</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;">menuItems</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$routeName</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuItem<span style="color: #009900;">&#40;</span><span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$itemData</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;">menuItems</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$routeName</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">i18n</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Render all items of a given level of the menu.
   * 
   * By default, only items inside the current route branch will be rendered.
   * To render all items regardless of their branch set the $forceAll 
   * parameter to true.
   * 
   * @param int $level          Level to render. 0 = top level, 1 = second level and so on
   * @param boolean $forceAll   Set to true to render all items even if their part of the tree is inactive
   * 
   * @return array              Array of items' XHTML code grouped by position
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> renderLevel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forceAll</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;">$rendered</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">menuItems</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLevel</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rendered</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forceAll</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: #000088;">$rendered</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Render all menu items into a tree structure.
   * 
   * @param string $container   The XHTML container tag to use. Defaults to 'ul'.
   * 
   * @return string             Rendered items and child items, wrapped in container tag
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> renderTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ul'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$rendered</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">menuItems</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$rendered</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTree</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rendered</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></td></tr></table></div>

<p>As you can see now the sfRoute, its name and the sfI18n instance have to be injected into the <em>initInstance()</em> method. The constructor cannot be called from outside the class, so you have to use <em>initInstance()</em> and <em>getInstance()</em> in combination with <em>$name</em> (which defaults to &#8220;default&#8221;) to access your builder instances.</p>
<h3>sfMenuItem revisited</h3>
<p>The constructor then creates all the <em>sfMenuItem</em> objects and injects the routing and i18n information. Let&#8217;s take a look at the full <em>sfMenuItem</em> class next:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfMenuItem <span style="color: #009900;">&#123;</span>
  protected
    <span style="color: #000088;">$myRouteName</span>        <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$children</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: #000088;">$allRouteNames</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: #000088;">$title</span>              <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$position</span>           <span style="color: #339933;">=</span> <span style="color: #0000ff;">'default'</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$container</span>          <span style="color: #339933;">=</span> <span style="color: #0000ff;">'li'</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$requireObjectClass</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$customFunction</span>     <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$customUrl</span>          <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$route</span>              <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$routeName</span>          <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$routeObject</span>        <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$i18n</span>               <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Generate a new sfMenuItem object using its own route name and the node
   * data from the structural schema.
   * 
   * @param string $myRouteName   This item's sfRoute name (as in routing.yml)
   * @param array $itemData       The data definition for this item
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$myRouteName</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #000088;">$itemData</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;">myRouteName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$myRouteName</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$myRouteName</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'position'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'position'</span><span style="color: #009900;">&#93;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'container'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">container</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'container'</span><span style="color: #009900;">&#93;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'alias_routes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'alias_routes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'require_object_class'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'require_object_class'</span><span style="color: #009900;">&#93;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'custom_function'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">customFunction</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfCallable<span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'custom_function'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'custom_url'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">customUrl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'custom_url'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</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: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$subRouteName</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$subItemData</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;">children</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$subRouteName</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuItem<span style="color: #009900;">&#40;</span><span style="color: #000088;">$subRouteName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$subItemData</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;">allRouteNames</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$subRouteName</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllRouteNames</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>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Initialize the menu item and all child menu items using the current routing 
   * status of the application.
   * By passing the routing information you can either use routes from outside
   * the context (e.g. testing data) or just improve performance because this
   * would have to be repeated for all the child menu items. 
   * 
   * @param string $routeName   Name of the currently active route
   * @param sfRoute $route      Currently active route object
   * @param mixed $routeObject  Object that is transported through the route if it is an sfObjectRoute
   * @param sfI18n $i18n        An instance of sfI18n to perform translations using __()
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> sfRoute <span style="color: #000088;">$route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routeObject</span><span style="color: #339933;">,</span> sfI18n <span style="color: #000088;">$i18n</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$route</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$routeObject</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">i18n</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i18n</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">i18n</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get this menu item's route name.
   * 
   * @return string   Route name of this single menu item
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getMyRouteName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">myRouteName</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get all child sfMenuItem objects.
   * 
   * @return array    Array of sfMenuItem objects, using the route names as keys.
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getChildren<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get an array of all route names and alias route names this menu item
   * might use. Also includes all sub items' routes recursively.
   * 
   * @return array    Array of route names
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAllRouteNames<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the title that will be used to render this item.
   * 
   * @return string   Title text
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getTitle<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the position this item will be rendered at.
   * 
   * @return string   Position. Defaults to &quot;default&quot;
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getPosition<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get this menu item's wrapper container.
   * 
   * @return string   HTML wrapper Container name
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getContainer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">container</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the object class that is required for this item to 
   * be rendered as &quot;enabled&quot;.
   * 
   * @return string   Object class name 
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRequireObjectClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get this menu item's custom URL.
   * 
   * @return string   Custom URL
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getCustomUrl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">customUrl</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * If an i18n instance was provided, this will do the translation.
   * @see sfI18n::__()
   * 
   * @param string $string  The string to translate
   * 
   * @return string         Translated string
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __<span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</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: #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;">i18n</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;">$string</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Render the current menu item's content text.
   * 
   * The content always contains an 'a' tag containing either a href
   * link (if the item is enabled) or the item title only.
   * 
   * All titles are translated using i18n.
   * 
   * @return string   Rendered menu item content HTML code
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> renderContent<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;">customFunction</span> instanceof sfCallable<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">customFunction</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">call</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'a'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</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: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">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;">customUrl</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> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</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;">customUrl</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</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;">requireObjectClass</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> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@'</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">myRouteName</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: #b1b100;">return</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</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;">myRouteName</span><span style="color: #339933;">,</span> sfObjectResolver<span style="color: #339933;">::</span><span style="color: #004000;">resolve</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</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: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Check if the item is enabled or not.
   * An item will be disabled if it requires an object class
   * that cannot be found by the resolver.
   * 
   * @return boolean  True if the item is enabled
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isEnabled<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;">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;">requireObjectClass</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span>sfObjectResolver<span style="color: #339933;">::</span><span style="color: #004000;">resolve</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</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: #009933; font-style: italic;">/**
   * Check if the item is currently selected.
   * An item will be selected if the current routeName matches
   * any route in the items allRouteNames property.
   * 
   * @return boolean  True if the item is currently selected in the menu
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isCurrent<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;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Wrap an item with the container that is set. If no container
   * is defined, just return the item.
   * 
   * @param string $text    Text content
   * @param array $options  Options array passed to content_tag() helper
   * 
   * @return string         Rendered content tag
   */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> containerTag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</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;">container</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">container</span><span style="color: #339933;">,</span> <span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</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: #000088;">$text</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Render the current menu item.
   * 
   * The item is rendered inside the element given as &quot;container&quot; parameter.
   * The container defaults to the HTML list element (&quot;li&quot;).
   * 
   * Items that require an object route without existing object of that type
   * have their class attribute set to &quot;disabled&quot;. Items that match the current
   * route have their class attribute set to &quot;current&quot;.
   * 
   * @return string   Rendered menu item HTML code
   */</span>
  <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: #000088;">$text</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderContent</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: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</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: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isCurrent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'current'</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: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the sfRoute object associated with all the menu items.
   * 
   * @return sfRoute  sfRoute object
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRoute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the route name associated with all the menu items.
   * 
   * @return string   Route name
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRouteName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Get the route object out of sfObjectRoute.
   * 
   * @return mixed    Route object generated by sfObjectRoute
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRouteObject<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Render all menu items of a given child level related to this item.
   * 
   * The rendered items are added to the $rendered array parameter grouped 
   * by their position.
   * 
   * @param int $level          Level to render. 0 will return the current item, 1 all items of the first child level and so on.
   * @param array $rendered     Contains all items rendered so far. Rendered items will be appended to the array.
   * @param boolean $forceAll   Force the rendering of all sub items, even if their tree is not in the current route
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> renderLevel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$rendered</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forceAll</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;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</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: #000088;">$rendered</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">position</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</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>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$forceAll</span> <span style="color: #339933;">||</span> <span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$level</span><span style="color: #339933;">--;</span>
      <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLevel</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rendered</span><span style="color: #339933;">,</span> <span style="color: #000088;">$forceAll</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>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Render all menu items into a tree structure.
   * 
   * @param string $container   The HTML container tag to use. Defaults to 'ul'.
   * 
   * @return string             Rendered item and child items, wrapped in container tag
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> renderTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ul'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$children</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$children</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTree</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$text</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderContent</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: #000088;">$children</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$text</span> <span style="color: #339933;">.=</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #339933;">,</span> <span style="color: #000088;">$children</span><span style="color: #009900;">&#41;</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;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</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: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isCurrent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'current'</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: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</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></td></tr></table></div>

<h3>All the configuration options</h3>
<p>Now you can see the full parameter set of sfMenuItem &#8211; but what do all those values actually mean? I think looking at the commented parameter definitions in my sample yaml file will make it more understandable:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">all:
  menu:
    items:
&nbsp;
      # Each item must use its route name as in routing.yml as its index.
      # If you provide the custom_url parameter, the route name will be
      # ignored, so you may provide a name that does not exist.
      first_item_route_name:
&nbsp;
        # The title is the text that is displayed for the item.
        # This text will automatically be translated if an i18n instance is passed
        # to the sfMenuItem's initialize<span style="">&#40;</span><span style="">&#41;</span> method.
        title:                My first item title
&nbsp;
        # Alias routes are route names that should set the same menu item as current.
        # If your applications uses different routes for the same page <span style="">&#40;</span>e.g. <span style="color: #933;">&quot;update&quot;</span> 
        # routes in form actions<span style="">&#41;</span> you must provide them here, otherwise the menu
        # will not display correctly.
        alias_routes:         <span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>first_item_update_route_name, ...<span style="">&#93;</span></span>
&nbsp;
        # Using the position option items can be grouped into separate arrays.
        # This is used for the rendering of tab levels, where the level contains
        # an array with the positions as indexes.
        # Typical applications might use options like <span style="color: #933;">&quot;left&quot;</span> and <span style="color: #933;">&quot;right&quot;</span> to separate
        # the tabs of a level into different positions. If no position is provided it 
        # defaults to 'default'.
        position:             default
&nbsp;
        # This is the HTML container to use for rendering the item's content. If no container
        # is provided, it defaults to 'li'. You may also provide an empty container <span style="">&#40;</span>''<span style="">&#41;</span>, 
        # which will make the item content return without an outer tag. Beware though, that
        # without this tag the options <span style="color: #933;">&quot;disabled&quot;</span> and <span style="color: #933;">&quot;current&quot;</span> have no element to be applied to.
        container:            li
        container:            ''
&nbsp;
        # This option indicates that this item requires an object of a specific type.
        # The sfMenuItem will try to get this object through the sfObjectRoute
        # and <span style="">&#40;</span>if the route object is different<span style="">&#41;</span> through sfObjectResolver.
        # If no object of this type is found the item will be set to <span style="color: #933;">&quot;disabled&quot;</span>.
        require_object_class: SomeClass
&nbsp;
        # If you provide a custom function, it will be called instead of rendering the
        # item's content using the title. You can provide any callable, either a globally
        # accessible function name or an array holding a class name and a static method name.
        # The sfMenuItem object is passed to the function, so the item's public methods can 
        # be used to access nearly all the parameters and settings.
        # 
        # The function footprint should be something like this:
        # 
        # function some_function_name<span style="">&#40;</span>sfMenuItem $item<span style="">&#41;</span> <span style="">&#123;</span>
        #   // do custom rendering here
        #   return $itemContent<span style="color: #666666; font-style: italic;">;</span>
        # <span style="">&#125;</span>
        custom_function:      some_function_name
        custom_function:      <span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>SomeClass, someMethod<span style="">&#93;</span></span>
&nbsp;
        # Providing a custom url you can generate menu items that link somewhere else.
        # It will be used in an url_for<span style="">&#40;</span><span style="">&#41;</span> call, so everything that works in there will be fine.
        custom_url:           http://www.symfony-project.org/my_custom_url
&nbsp;
        # In the children option you can provide child items of the given menu item.
        # Each child item may have children itself, recursively. Of course all the options
        # as for this item may be defined for any child item.
        children:
          child1_route_name:
            child1_title:       Some title
&nbsp;
          child2_route_name:
            child2_title:       Some other title
&nbsp;
            children:
              # I think you get it...</pre></div></div>

<h3>Any questions?</h3>
<p>I think those comments should explain the options quite well. Since I can&#8217;t think of another example at the moment and also may not publish what the menu I use at work actually looks like I can only ask for <strong>user feedback</strong> if you don&#8217;t understand something or just can&#8217;t see its usage. If I see that something is still unclear I will try to make it more specific. I can only tell you that at the moment every single option except <em>custom_url</em> is in use in my application and I&#8217;m glad for having all of them (and I may need <em>custom_url</em> in the future myself).</p>
<h3>Dynamic menus</h3>
<p>As promised in part 3, I want to think about how sfMenuBuilder could be used dynamically. The first thing that comes to mind is having a tree-like database structure (if you need nested menus), using nestedSet features provided (AFAIK) both by Propel and Doctrine. The basic schema for a dynamic menu could look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">propel:
  menu_item:
    id:
    route_name:           <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, required: true <span style="">&#125;</span>
    title:                <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, required: true <span style="">&#125;</span>
    alias_routes:         <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, required: false <span style="">&#125;</span>
    position:             <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">10</span><span style="">&#41;</span>, required: false, default: 'default' <span style="">&#125;</span>
    container:            <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">10</span><span style="">&#41;</span>, required: false, default: 'li' <span style="">&#125;</span>
    require_object_class: <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, required: false <span style="">&#125;</span>
    custom_function:      <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, required: false <span style="">&#125;</span>
    custom_url:           <span style="">&#123;</span> type: varchar<span style="">&#40;</span><span style="">255</span><span style="">&#41;</span>, required: false <span style="">&#125;</span></pre></div></div>

<p>Just add the code for transforming these database objects into the arrays needed for sfMenuItem and you&#8217;re done!</p>
<p>You could also extend statically defined menu arrays by merging with dynamically created arrays. Due to the simple array syntax nearly anything can be used to describe a menu.</p>
<h3>That&#8217;s it!</h3>
<p>Finally we have come to an end and the sfMenuBuilder is ready to use. I hope my articles were not too bulky and rather helpful for you guys out there. When designing something as large as this and writing about it, I always want my readers to understand what goes through my mind and how I arrived at my destination. In the end, my articles shouldn&#8217;t be about the final code but more about designing things and working them out.</p>
<p>What started as a proof of concept for sfObjectResolver has in the end become a fully usable little library that will hopefully evolve and be used in various applications, and at the same time teach people about OOp and clean design. I know, I always exaggerate, but that&#8217;s just me&#8230;</p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/04/06/creating-a-routing-based-menu-in-symfony-12-part-4-the-full-package/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Creating a routing-based menu in symfony 1.2, part 3: the builder</title>
		<link>http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-3-the-builder/</link>
		<comments>http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-3-the-builder/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 19:55:48 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[menu]]></category>
		<category><![CDATA[OOp]]></category>
		<category><![CDATA[YAML]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=112</guid>
		<description><![CDATA[After defining a menu structure and describing the sfMenuItem object it&#8217;s time to show you how to pack the whole menu thing up to generate the menu with a few lines of code.
Up until now we have defined a tree structure in yaml and created a PHP class to generate menu items recursively as well [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://blog.vworld.at/2009/03/31/creating-a-routing-based-menu-in-symfony-12-part-1/">defining a menu structure</a> and <a href="http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-2-the-menuitem-object/">describing the sfMenuItem object</a> it&#8217;s time to show you how to pack the whole menu thing up to generate the menu with a few lines of code.</p>
<p>Up until now we have defined a tree structure in yaml and created a PHP class to generate menu items recursively as well as render their content. We are able to load the object assigned to an sfObjectRoute and even find related objects and create route links for those through the <em><a href="http://blog.vworld.at/2009/03/28/managing-soft-relations-between-php-objects/">sfObjectResolver</a></em> class.<br />
<span id="more-112"></span></p>
<h3>The next step</h3>
<p>Now I want to show you how to use those sfMenuItem objects to generate your menu HTML code. There are 2 typical menu variants I want to implement:</p>
<ul>
<li>Generate one flat level of a menu (e.g. for tab navigation)</li>
<li>Generate a complete tree menu (e.g. for a sidebar menu)</li>
</ul>
<p>During the first part I only showed the HTML code for the tab row version &#8211; this is mainly because I haven&#8217;t used the menu code for trees myself yet, but now I think the tree version might be even more important for some users, so I decided to implement it, too.</p>
<h3>Flat (tab) menu generation</h3>
<p>When designing a tab menu based on a tree structure you have to keep a few things in mind. Most important is that when providing sub level tabs, only tabs that are descendants (children) of the active tab one level above should be shown.</p>
<p>To achieve rendering of a single level, I added a renderLevel() method to sfMenuItem.class.php:</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> renderLevel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$rendered</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;">$level</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: #000088;">$rendered</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</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>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$level</span><span style="color: #339933;">--;</span>
      <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLevel</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rendered</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>The code more or less explains itself. If the $level parameter is 0 (when the level is the one that is to be rendered) the item is rendered and added to an array passed by reference. If the level is too high and the current item is parent of the route to display, the level is decreased by 1 and renderLevel() is called for all child items. Thus only the items of a specific level and inside the required route path are rendered.</p>
<p>To create the complete menu I added another class: sfMenuBuilder.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfMenuBuilder <span style="color: #009900;">&#123;</span>
  protected <span style="color: #000088;">$menuItems</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>
&nbsp;
  protected <span style="color: #000088;">$route</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  protected <span style="color: #000088;">$routeName</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  protected <span style="color: #000088;">$routeObject</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: #990000;">array</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$itemsData</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemsData</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$routeName</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$itemData</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;">menuItems</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$routeName</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuItem<span style="color: #009900;">&#40;</span><span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$itemData</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;">routeName</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouting</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCurrentRouteName</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;">route</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_route'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span> instanceof sfObjectRoute<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOptions</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: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'object'</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;">routeObject</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">menuItems</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> renderLevel<span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</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: #000088;">$rendered</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">menuItems</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLevel</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$level</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rendered</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: #000088;">$rendered</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now you can generate your menu like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000088;">$builder</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuBuilder<span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_menu_items'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$mainItems</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLevel</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$subItems</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderLevel</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$mainItemsHtml</span> <span style="color: #339933;">=</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ul'</span><span style="color: #339933;">,</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mainItems</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$subItemsHtml</span> <span style="color: #339933;">=</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ul'</span><span style="color: #339933;">,</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$subItems</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>You could place this code inside a helper function or directly in the view. But don&#8217;t do it until I&#8217;ve showed you how to do this even nicer in part 4 <img src='http://blog.vworld.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Tree menu generation</h3>
<p>To generate a tree menu we have to split up sfMenuItem::render() a little because we need to reach inside the <i>li</i> elements:</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> isCurrent<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;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</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> renderContent<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$i18n</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getI18n</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'a'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</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: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</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;">requireObjectClass</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> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@'</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">myRouteName</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: #b1b100;">return</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</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;">myRouteName</span><span style="color: #339933;">,</span> sfObjectResolver<span style="color: #339933;">::</span><span style="color: #004000;">resolve</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</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: #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: #000088;">$text</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderContent</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: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</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: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isCurrent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'current'</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: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now we can define a method to render the tree:</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> renderTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ul'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$children</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$children</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTree</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$text</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderContent</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: #000088;">$children</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$text</span> <span style="color: #339933;">.=</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #339933;">,</span> <span style="color: #000088;">$children</span><span style="color: #009900;">&#41;</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;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</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: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isCurrent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'current'</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: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>In sfMenuBuilder.class.php we also define a method to render the tree:</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> renderTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ul'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$rendered</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">menuItems</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$rendered</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTree</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rendered</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Creating the tree is even easier than creating the tab rows:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000088;">$builder</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuBuilder<span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_menu_items'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$treeHtml</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Using the code above we are able to create tree-like menus as well as tab menu rows out of the same sfMenuItem objects.</p>
<h3>We are not done yet</h3>
<p>Now you know how it all works out. But do you think that was all? Of course not! Just give me a little more time to write the 4th and final part to this series, showing the full classes including phpDoc comments and adding the following features to our menu system:</p>
<ul>
<li>Tab groups</li>
<li>Custom containers</li>
<li>Callback menu items</li>
<li>Static url menu items</li>
<li>A multi-instance sfMenuBuilder with named instances for several independent menus at once</li>
<li>&#8230; and some thoughts about how all this could be used dynamically</li>
</ul>
<p>Curious? You better be!</p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-3-the-builder/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating a routing-based menu in symfony 1.2, part 2: the MenuItem object</title>
		<link>http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-2-the-menuitem-object/</link>
		<comments>http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-2-the-menuitem-object/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 09:15:36 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[menu]]></category>
		<category><![CDATA[OOp]]></category>
		<category><![CDATA[YAML]]></category>

		<guid isPermaLink="false">http://blog.vworld.at/?p=79</guid>
		<description><![CDATA[During my last article I described how the structure of my routing-based menu is defined. This time I want to show you how to create menu item objects using this structure as the source. You will also learn how the items interact with the symfony environment.

The structure again
To make sure you understand what comes next [...]]]></description>
			<content:encoded><![CDATA[<p>During <a href="http://blog.vworld.at/2009/03/31/creating-a-routing-based-menu-in-symfony-12-part-1/">my last article</a> I described how the structure of my routing-based menu is defined. This time I want to show you how to create menu item objects using this structure as the source. You will also learn how the items interact with the symfony environment.<br />
<span id="more-79"></span></p>
<h3>The structure again</h3>
<p>To make sure you understand what comes next I want to bring the last version of the menu structure we defined in app.yml back to mind:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">all:
  menu:
    items:
      homepage:
        title:   Home
        children:
          homepage:
            title:   Home
          about:
            title:   About
&nbsp;
      article_index:
        title:   Articles
        children:
          article_index:
            title:   Article index
          article_view:
            title:   View article details
            require_object_class: Article
          article_edit:
            title:   Edit article
            require_object_class: Article
            alias_routes: <span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>article_update<span style="">&#93;</span></span>
          article_comments_edit:
            title:   Edit article comments
            require_object_class: Article
            alias_routes: <span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>article_comments_update<span style="">&#93;</span></span>
          user_view:
            title:   View article author
            require_object_class: User</pre></div></div>

<h3>The object constructor</h3>
<p>I want each item out of this menu definition to be a single PHP object. The object should be created using the route name (the key in the yaml structure) and an array containing the node&#8217;s data. Both parameters are passed to the constructor of sfMenuItem.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfMenuItem <span style="color: #009900;">&#123;</span>
  protected <span style="color: #000088;">$myRouteName</span><span style="color: #339933;">;</span>
  protected <span style="color: #000088;">$children</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>
  protected <span style="color: #000088;">$allRouteNames</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>
&nbsp;
  protected <span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
  protected <span style="color: #000088;">$requireObjectClass</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;">$myRouteName</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #000088;">$itemData</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;">myRouteName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$myRouteName</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$myRouteName</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'alias_routes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'alias_routes'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'require_object_class'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'require_object_class'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</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: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$itemData</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$subRouteName</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$subItemData</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;">children</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$subRouteName</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfMenuItem<span style="color: #009900;">&#40;</span><span style="color: #000088;">$subRouteName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$subItemData</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;">allRouteNames</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$subRouteName</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllRouteNames</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>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>As you can see the item&#8217;s data is stored in the object and child items are automatically added recursively. You can also see that both the own route name as well as all child route names are stored in the allRouteNames property. This will make it easy to find out if a specific node represents any route somewhere down below and thus has to be displayed.</p>
<h3>Injecting the routing information</h3>
<p>To make the intelligence of the sfMenuItem object work we need to initialize it using the real routing information. This information can be retrieved from the symfony context like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouting</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCurrentRouteName</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;">route</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_route'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span> instanceof sfObjectRoute<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOptions</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: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'object'</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;">routeObject</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Since it would be a little bloating to do this in all menu items and also prevents you from injecting testing data the best way is to retrieve the data outside the sfMenuItem class (I will show later where to do this) and inject it into each sfMenuItem. This is done in the <em>initialize()</em> method:</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> initialize<span style="color: #009900;">&#40;</span><span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> sfRoute <span style="color: #000088;">$route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routeObject</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;">routeName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$route</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$routeObject</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</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>

<h3>Rendering the output</h3>
<p>Now the sfMenuItem object is ready to be rendered. The basic <em>render()</em> method 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;">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: #000088;">$i18n</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getI18n</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isEnabled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span>content_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'a'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #009900;">&#41;</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;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</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: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</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;">requireObjectClass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$link</span> <span style="color: #339933;">=</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@'</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">myRouteName</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;">$link</span> <span style="color: #339933;">=</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$i18n</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</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;">myRouteName</span><span style="color: #339933;">,</span> sfObjectResolver<span style="color: #339933;">::</span><span style="color: #004000;">resolve</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #b1b100;">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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">allRouteNames</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'current'</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: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">containerTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</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>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isEnabled<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;">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;">requireObjectClass</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span>sfObjectResolver<span style="color: #339933;">::</span><span style="color: #004000;">resolve</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">routeObject</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">requireObjectClass</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;
  protected <span style="color: #000000; font-weight: bold;">function</span> containerTag<span style="color: #009900;">&#40;</span><span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #b1b100;">return</span> content_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'li'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$text</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>I&#8217;m loading the i18n instance inside the render() method to translate the title texts. Of course this could be left out if you either don&#8217;t need i18n for your menu or just translate the titles before they are inserted into the sfMenuItems.</p>
<h3>Why an object resolver is useful here</h3>
<p>You can see 3 additional method dependencies of <em>render()</em>: <em>isEnabled()</em>, <em>containerTag()</em> and the external calls to <em>sfObjectResolver::resolve()</em>. The <em>containerTag()</em> is easy: this way the embracing tag for the menu item (<em>li</em> by default here) can be modified. <em>isEnabled()</em> checks if the item requires a specific object class and looks it up in sfObjectResolver. If no matching object is found, no link can be generated, so the <em>a</em> tag is just left without the href attribute.</p>
<p>See <a href="http://blog.vworld.at/2009/03/28/managing-soft-relations-between-php-objects/">Managing “soft” relations between PHP objects</a> to learn more about the resolver &#8211; here it comes in really handy, because the sfMenuItem class has absolutely no clue about the objects it has to link to, but using the resolver <strong>moves this dependency into each object&#8217;s context</strong>. Using this little trick you can have a menu that automatically generates reference route links to objects without the need to know anything about the objects but their class names. Could it be any more comfortable?</p>
<p>That&#8217;s it again for today (the articles just grow so long!). In my next article I will show you how to wrap the menu building process in a small builder class and what additional options sfMenuItem may provide.</p>
<p>One small side note: you may have noticed that the code presented here doesn&#8217;t follow symfony&#8217;s PHP coding style guidelines in terms of bracket placement. I just like them more this way and symfony&#8217;s style would make the article even longer, but feel free to change them as you like <img src='http://blog.vworld.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vworld.at/2009/04/03/creating-a-routing-based-menu-in-symfony-12-part-2-the-menuitem-object/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
