<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Miximum</title>
	
	<link>http://www.miximum.fr</link>
	<description>Le blog d'un ingénieur web freelance</description>
	<lastBuildDate>Mon, 19 Apr 2010 12:22:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LeBlogDunDeveloppeur" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="leblogdundeveloppeur" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Montpellier web : parlons-en !</title>
		<link>http://www.miximum.fr/actus/493-montpellier-web-parlons-en</link>
		<comments>http://www.miximum.fr/actus/493-montpellier-web-parlons-en#comments</comments>
		<pubDate>Mon, 19 Apr 2010 12:22:05 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Actus]]></category>
		<category><![CDATA[mtpweb]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=493</guid>
		<description><![CDATA[Salut tout le monde,
Suite au premier post sur Montpellier web, quelques mesures concr&#232;tes ont &#233;t&#233; mises en place.

La mise en place d&#8217;un groupe de discussion, histoire de permettre aux bonnes volont&#233;s d&#8217;&#233;changer ailleurs que via twitter.
Mise en place d&#8217;un blog, pour centraliser les actus et infos sur l&#8217;&#233;v&#233;nement. (La propagation dns est en cours, vous [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F493-montpellier-web-parlons-en"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F493-montpellier-web-parlons-en" height="61" width="51" /></a></div><p>Salut tout le monde,</p>
<p>Suite au <a href="http://www.miximum.fr/actus/485-pour-un-montpellier-web-en-2011">premier post sur Montpellier web</a>, quelques mesures concr&egrave;tes ont &eacute;t&eacute; mises en place.</p>
<ul>
<li>La mise en place d&#8217;un <a href="http://groups.google.com/group/mtpweb">groupe de discussion</a>, histoire de permettre aux bonnes volont&eacute;s d&#8217;&eacute;changer ailleurs que via twitter.</li>
<li><a href="http://blog.mtp-web.fr">Mise en place d&#8217;un blog</a>, pour centraliser les actus et infos sur l&#8217;&eacute;v&eacute;nement. (La propagation dns est en cours, vous n&#8217;y aurez peut-&ecirc;tre pas acc&egrave;s imm&eacute;diatement)</li>
</ul>
<p>Premier d&eacute;bat&nbsp;: d&eacute;cider du nom (mtpweb vs sudweb). Le d&eacute;bat penche assez fortement vers mtpweb (d&#8217;o&ugrave; les noms de domaines choisis), j&#8217;ai toutefois cr&eacute;&eacute; un <a href="http://groups.google.com/group/mtpweb/browse_thread/thread/45c173d57e51fd0e">premier sujet de discussion</a>, afin de permettre &agrave; tout le monde de s&#8217;exprimer correctement.</p>
<p>Avis &agrave; tous les gens qui avaient l&#8217;air motiv&eacute;s&nbsp;: la discussion pr&eacute;c&egrave;de l&#8217;action. Donnez votre avis.</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F493-montpellier-web-parlons-en"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F493-montpellier-web-parlons-en" height="61" width="51" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/actus/493-montpellier-web-parlons-en/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Pour un Montpellier web en 2011 ?</title>
		<link>http://www.miximum.fr/actus/485-pour-un-montpellier-web-en-2011</link>
		<comments>http://www.miximum.fr/actus/485-pour-un-montpellier-web-en-2011#comments</comments>
		<pubDate>Sun, 11 Apr 2010 15:07:45 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Actus]]></category>
		<category><![CDATA[mtpweb]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=485</guid>
		<description><![CDATA[ photo credit&#160;: littlepois
Suite au dernier sfPot Montpellierain, qui s&#8217;est d&#233;roul&#233; entre autre en compagnie d&#8217;honorables membres du non moins honorable regroupement particul.es, l&#8217;id&#233;e a &#233;t&#233; lanc&#233;e d&#8217;organiser un Montpellier web, pendant sudiste au d&#233;sormais fameux Paris-web.
&#192; voir la temp&#232;te de tweets qui s&#8217;ensuivit, il semble que l&#8217;id&#233;e soul&#232;ve bel et bien l&#8217;enthousiasme des foules. [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F485-pour-un-montpellier-web-en-2011"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F485-pour-un-montpellier-web-en-2011" height="61" width="51" /></a></div><div class="postimg alignright"><a href="http://www.flickr.com/photos/16818323@N05/3806061556/" title="Ni queue - Ni t&ecirc;te" target="_blank"><img src="http://farm4.static.flickr.com/3543/3806061556_265837d272_m.jpg" alt="Ni queue - Ni t&ecirc;te" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/16818323@N05/3806061556/" title="littlepois" target="_blank">littlepois</a></small></div>
<p>Suite au <a href="http://particul.es/blog/index.php?post/sfPot-2.1-%C3%A0-montpellier-!">dernier sfPot Montpellierain</a>, qui s&#8217;est d&eacute;roul&eacute; entre autre en compagnie d&#8217;honorables membres du non moins <a href="http://particul.es/">honorable regroupement particul.es</a>, l&#8217;id&eacute;e a &eacute;t&eacute; lanc&eacute;e d&#8217;organiser un Montpellier web, pendant sudiste au <a href="http://www.paris-web.fr/">d&eacute;sormais fameux Paris-web</a>.</p>
<p>&Agrave; voir la <a href="http://twitter.com/#search?q=%23mtpweb">temp&egrave;te de tweets qui s&#8217;ensuivit</a>, il semble que l&#8217;id&eacute;e soul&egrave;ve bel et bien l&#8217;enthousiasme des foules. En fait, on dirait bien que l&#8217;id&eacute;e couvait dans pas mal de t&ecirc;tes, mais sans avoir r&eacute;ellement germ&eacute;, par manque d&#8217;enthousiasme, de motivation, ou tout b&ecirc;tement de temps.</p>
<p>En vrac, quelques pistes de motivations qui justifieraient d&#8217;organiser un tel &eacute;v&eacute;nement&nbsp;:</p>
<ul>
<li>Permettre au sud le la France de se doter de son propre &eacute;v&eacute;nement, et par l&agrave; m&ecirc;me, contribuer &agrave; donner une visibilit&eacute; aux professionnels du web de la r&eacute;gion (et oui, il y a des gens qui travaillent en province)&nbsp;<span class="fine">&nbsp;</span>;</li>
<li>Paris-web, c&#8217;est &agrave; Paris <img src='http://www.miximum.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Montpellier, c&#8217;est quand m&ecirc;me mieux pour un rendez-vous sur la plage apr&egrave;s une journ&eacute;e de conf&eacute;rence&nbsp;<span class="fine">&nbsp;</span>;</li>
</ul>
<p>L&#8217;id&eacute;e n&#8217;est donc pas de concurrencer Paris-web, mais au contraire d&#8217;en &ecirc;tre compl&eacute;mentaire. Autant que possible, il me semble int&eacute;ressant de faire intervenir en priorit&eacute; des gens de la r&eacute;gion et des alentours, les comp&eacute;tences ne manquent pas. Le projet pourrait donc int&eacute;resser du monde, et recruter des bonnes volont&eacute;s pour participer &agrave; l&#8217;organisation semble possible.</p>
<p>Histoire de lancer quelques pistes de r&eacute;flexions, voici une liste d&#8217;id&eacute;es de trucs &agrave; faire / &agrave; penser en vrac&nbsp;:</p>
<ul>
<li>Lancer un appel aux bonnes volont&eacute;s, et cr&eacute;er une &eacute;quipe d&#8217;organisation. D&eacute;finir des dates de r&eacute;unions (autour de bonnes pizzas / bi&egrave;res, pour joindre l&#8217;utile &agrave; l&#8217;agr&eacute;able), parce qu&#8217;en twitter, c&#8217;est bien, mais ce voir, c&#8217;est quand m&ecirc;me mieux<span class="fine">&nbsp;</span>;</li>
<li>D&eacute;finir le format de l&#8217;&eacute;venement. Un jour<span class="fine">&nbsp;</span>? Deux jours<span class="fine">&nbsp;</span>? Dans l&#8217;id&eacute;al, pour une premi&egrave;re &eacute;dition, je verrai bien s&#8217;&eacute;taler sur deux jours des conf&eacute;rences, avec des workshops en parall&egrave;le, et un espace stands pour les sponsors.</li>
<li>D&eacute;finir la date. Le printemps me semble une bonne date, pour faire un pendant aux conf&eacute;rence sur Paris en automne. En plus, Montpellier au printemps, qu&#8217;est-ce que c&#8217;est bien<span class="fine">&nbsp;</span>!</li>
<li>D&eacute;finir la philosophie de l&#8217;&eacute;v&eacute;nement. Quels sujets privil&eacute;gier<span class="fine">&nbsp;</span>? Qui inviter<span class="fine">&nbsp;</span>? &Agrave; qui veut-on s&#8217;adresser<span class="fine">&nbsp;</span>? Comment se d&eacute;marquer des &eacute;v&eacute;nements similaires existants<span class="fine">&nbsp;</span>?</li>
<li>D&eacute;finir les modalit&eacute;s d&#8217;inscription. Est-ce un &eacute;v&eacute;nement gratuit<span class="fine">&nbsp;</span>? Payant<span class="fine">&nbsp;</span>? Cher<span class="fine">&nbsp;</span>? Pas cher<span class="fine">&nbsp;</span>? Il me semble important d&#8217;en faire un &eacute;v&eacute;nement accessible au plus grand nombre, et par cons&eacute;quent de limiter le tarif au minimum n&eacute;cessaire pour ne pas en &ecirc;tre de notre poche.</li>
<li>Trouver un lieu. Voir avec les universit&eacute;s, la ville ou l&#8217;agglo si elles peuvent pr&ecirc;ter un espace appropri&eacute;.</li>
<li>Trouver des sponsors qui cautionneraient et financeraient l&#8217;&eacute;v&eacute;nement. D&eacute;finir les modalit&eacute;s d&#8217;adh&eacute;sion des sponsors. D&eacute;cider &agrave; quelle contrepartie leur sponsoring leur donne droit (stands<span class="fine">&nbsp;</span>? Logos sur les affiches ?)</li>
<li>D&eacute;finir et cr&eacute;er une structure juridique (association ?) pour servir d&#8217;interface avec les diverses et in&eacute;vitables administrations&nbsp;<span class="fine">&nbsp;</span>;</li>
<li>Lancer un appel aux conf&eacute;renciers, recruter les intervenants, d&eacute;finir le programme&nbsp;<span class="fine">&nbsp;</span>;</li>
<li>D&eacute;marcher les h&ocirc;tels des alentours pour proposer des formules d&#8217;h&eacute;bergements attractives aux visiteurs. S&#8217;organiser pour h&eacute;berger chez l&#8217;habitant les conf&eacute;renciers (couch-surfing power)<span class="fine">&nbsp;</span>?</li>
<li>Mettre en place le site, avec backend et outils de communication pour les GO (gentils organisateurs). Montpellier-web.fr est d&eacute;j&agrave; pris. &Agrave; tout hasard, j&#8217;ai r&eacute;serv&eacute; mtp-web.fr <img src='http://www.miximum.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li>Cr&eacute;er un visuel pour des affiches et des tracts. S&#8217;occuper de la com&#8217; de l&#8217;&eacute;v&eacute;nement. Contacter la presse<span class="fine">&nbsp;</span>;</li>
<li>Trouver une formule pour la bouffe lors de l&#8217;h&eacute;bergement.  Pr&eacute;voir un buffet<span class="fine">&nbsp;</span>? Un ap&eacute;ro<span class="fine">&nbsp;</span>? D&eacute;marcher les restos aux alentours pour proposer des formules attractives<span class="fine">&nbsp;</span>?</li>
</ul>
<p>Je dresse une liste de tout ce &agrave; quoi je pense, en me projettant volontairement assez loin dans l&#8217;avenir. L&#8217;id&eacute;e &eacute;tant de reccueillir les premiers avis, lancer les discussions, et peut-&ecirc;tre &eacute;tablir une liste des premi&egrave;res bonnes volont&eacute;s int&eacute;ress&eacute;es &agrave; donner de leur temps pour participer &agrave; l&#8217;organisation.</p>
<p>Si vous avez des avis utiles, n&#8217;h&eacute;sitez pas &agrave; les balancer en commentaire, o&ugrave; &agrave; les tweeter assortis du tag #mtpweb. Sur ce, bonne fin de week-end &agrave; tout le monde.</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F485-pour-un-montpellier-web-en-2011"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Factus%2F485-pour-un-montpellier-web-en-2011" height="61" width="51" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/actus/485-pour-un-montpellier-web-en-2011/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Comment PHP me rends fou</title>
		<link>http://www.miximum.fr/musee-des-horreurs/473-comment-php-me-rends-fou</link>
		<comments>http://www.miximum.fr/musee-des-horreurs/473-comment-php-me-rends-fou#comments</comments>
		<pubDate>Fri, 12 Mar 2010 18:07:21 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Musée des horreurs]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[wtf]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=473</guid>
		<description><![CDATA[Chers amis d&#233;veloppeurs bonsoir. Je vous &#233;cris car je souhaite soumettre &#224; votre sagacit&#233; un probl&#232;me &#233;trange. &#192; d&#233;faut de pouvoir me venir en aide (seule ma dignit&#233; m&#8217;emp&#234;che encore de verser des larmes de frustration), peut-&#234;tre au moins cela vous fera-t-il marrer. Je suis victime d&#8217;une version particuli&#232;rement vicieuse du bug de 17h30 (avec [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Fmusee-des-horreurs%2F473-comment-php-me-rends-fou"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Fmusee-des-horreurs%2F473-comment-php-me-rends-fou" height="61" width="51" /></a></div><p>Chers amis d&eacute;veloppeurs bonsoir. Je vous &eacute;cris car je souhaite soumettre &agrave; votre sagacit&eacute; un probl&egrave;me &eacute;trange. &Agrave; d&eacute;faut de pouvoir me venir en aide (seule ma dignit&eacute; m&#8217;emp&ecirc;che encore de verser des larmes de frustration), peut-&ecirc;tre au moins cela vous fera-t-il marrer. Je suis victime d&#8217;une version particuli&egrave;rement vicieuse du <a href="http://www.miximum.fr/tranche_vie/62-le-bug-de-17h30">bug de 17h30</a> (avec un combo &laquo;&nbsp;bug du vendredi de fin d&#8217;it&eacute;ration&nbsp;&raquo; compte triple).</p>
<p>Projet symfony. Je code, tout se d&eacute;roule bien, fin de semaine, je balance mon code sur le serveur de recette, et je jette un coup d&#8217;&oelig;il sur l&#8217;environnement de prod. Horreur<span class="fine">&nbsp;</span>! Page blanche<span class="fine">&nbsp;</span>! Je v&eacute;rifie la m&ecirc;me page sous l&#8217;environnement de dev. Elle s&#8217;affiche correctement.</p>
<p>Je jette un coup d&#8217;&oelig;il dans la log apache&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">child pid <span class="nu0">16813</span> <a href="http://www.php.net/exit"><span class="kw3">exit</span></a> signal Segmentation fault <span class="br0">&#40;</span><span class="nu0">11</span><span class="br0">&#41;</span></pre></div></div>

<p>Un sentiment d&#8217;immense lassitude m&#8217;envahit aussit&ocirc;t.</p>
<p>Apr&egrave;s une longue et p&eacute;nible session profilage / debugage avec xdebug, je finit par circonvenir plus ou moins l&#8217;endroit du probl&egrave;me, et parviens m&ecirc;me &agrave; le reproduire &agrave; l&#8217;envie. Vous allez voir, c&#8217;est surprenant&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re0">$category</span> <span class="sy0">=</span> Article<span class="sy0">-&gt;</span><span class="me1">getCategory</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// objet de classe 'Category'</span>
<span class="kw1">echo</span> <span class="re0">$category</span><span class="sy0">;</span>  <span class="co1">// Affiche le titre de la catégorie</span>
<a href="http://www.php.net/printf"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st_h">'%s'</span><span class="sy0">,</span> <span class="re0">$category</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Page blanche, segfault, sacrifice de chatons, etc.</span></pre></div></div>

<p>Amusant, non<span class="fine">&nbsp;</span>? Apr&egrave;s quelques recherches, il semblerait que dans le contexte d&#8217;une fonction *printf, php n&#8217;utilise pas la fonction magique __toString().</p>
<p>Je teste donc&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw2">class</span> Toto
<span class="br0">&#123;</span>
  <span class="kw2">private</span> <span class="re0">$tata</span><span class="sy0">;</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="re0">$tata</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">tata</span> <span class="sy0">=</span> <span class="re0">$tata</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="br0">&#40;</span>string<span class="br0">&#41;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">tata</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">$toto</span> <span class="sy0">=</span> <span class="kw2">new</span> Toto<span class="br0">&#40;</span><span class="st_h">'tutu'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="re0">$toto</span><span class="sy0">;</span>
<a href="http://www.php.net/printf"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st_h">'%s'</span><span class="sy0">,</span> <span class="re0">$toto</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// tutu</span>
<span class="co1">// tutu</span></pre></div></div>

<p>WTF<span class="fine">&nbsp;</span>? Mais &ccedil;a marche tr&eacute;s bien<span class="fine">&nbsp;</span>! C&#8217;est donc un probl&egrave;me sp&eacute;cifique &agrave; mon code<span class="fine">&nbsp;</span>? Je poursuis mon d&eacute;buggage, et j&#8217;arrive ici&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re0">$category</span> <span class="sy0">=</span> <span class="re0">$article</span><span class="sy0">-&gt;</span><span class="me1">getCategory</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co1">// $category est de la classe sfOutputEscaperIteratorDecorator</span>
<span class="co1">// qui hérite de sfOutputEscaperObjectDecorator</span>
<span class="co1">// qui définit une fonction __toString()</span>
&nbsp;
<a href="http://www.php.net/printf"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st_h">'%s'</span><span class="sy0">,</span> <span class="re0">$category</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co1">// Appelle sfOutputEscaperObjectDecorator::__toString</span></pre></div></div>

<p>Bon, allons voir sur place ce qui ne va pas.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">class</span> sfOutputEscaperObjectDecorator
<span class="br0">&#123;</span>
…
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="co1">// Jusqu'ici, tout va bien, mais dés l'instruction return, ça plante</span>
    <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escape</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escapingMethod</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="sy0">-&gt;</span>__toString<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co1">// Je modifie donc la fonction pour obtenir ceci :</span>
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$value</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escape</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escapingMethod</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="sy0">-&gt;</span>__toString<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><a href="http://www.php.net/gettype"><span class="kw3">gettype</span></a><span class="br0">&#40;</span><span class="re0">$value</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><span class="re0">$value</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">return</span> <span class="re0">$value</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
<span class="co1">// J'obtiens pour affichage :</span>
<span class="co1">// 'String'</span>
<span class="co1">// 'Titre de ma catégorie'</span>
&nbsp;
<span class="co1">// En revanche :</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$value</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escape</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escapingMethod</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="sy0">-&gt;</span>__toString<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><a href="http://www.php.net/gettype"><span class="kw3">gettype</span></a><span class="br0">&#40;</span><span class="re0">$value</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <a href="http://www.php.net/var_dump"><span class="kw3">var_dump</span></a><span class="br0">&#40;</span><span class="re0">$value</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="co1">// die();</span>
    <span class="kw1">return</span> <span class="re0">$value</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Page blanche. Continuons dans l'étrange, avec quelques modifications de la même méthode :</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$value</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escape</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escapingMethod</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="sy0">-&gt;</span>__toString<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">&#40;</span><span class="st_h">'ici'</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Affiche 'ici'</span>
    <span class="kw1">return</span> <span class="st_h">'toto'</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="st_h">'toto'</span><span class="sy0">;</span> <span class="co1">// Affiche 'toto'</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$value</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escape</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">escapingMethod</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="sy0">-&gt;</span>__toString<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">return</span> <span class="st_h">'toto'</span><span class="sy0">;</span> <span class="co1">// Page blanche</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Tout &ccedil;a, bien s&ucirc;r, c&#8217;est sur l&#8217;environnement de prod. En dev, tout se passe toujours normalement.</p>
<p>J&#8217;en suis l&agrave;. Si quelqu&#8217;un a une bonne explication. En attendant, je crois que je vais aller me coucher de bonne heure. Bon week-end &agrave; tous.</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Fmusee-des-horreurs%2F473-comment-php-me-rends-fou"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Fmusee-des-horreurs%2F473-comment-php-me-rends-fou" height="61" width="51" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/musee-des-horreurs/473-comment-php-me-rends-fou/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Symfony form : pick or create</title>
		<link>http://www.miximum.fr/tutos/466-symfony-form-pick-or-create</link>
		<comments>http://www.miximum.fr/tutos/466-symfony-form-pick-or-create#comments</comments>
		<pubDate>Tue, 02 Feb 2010 14:40:29 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Tutos]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=466</guid>
		<description><![CDATA[Here&#8217;s an other tutorial about the Symfony form framework. Last time, we managed to make embedded i18n forms optionals. In today&#8217;s howto, we will talk about embedded forms again.
In the last tutorials, we created a form to edit news. Today we will create another form to write interviews. An interview is just an article about [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F466-symfony-form-pick-or-create"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F466-symfony-form-pick-or-create" height="61" width="51" /></a></div><p>Here&#8217;s an other tutorial about the Symfony form framework. Last time, <a href="http://www.miximum.fr/tutos/449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine">we managed to make embedded i18n forms optionals</a>. In today&#8217;s howto, we will talk about embedded forms again.</p>
<p>In the last tutorials, we created a form to edit news. Today we will create another form to write interviews. An interview is just an article about a celebrity. So our Interview class will inherit from our Article one, so we can reuse our last time work.</p>
<p>Here&#8217;s the complete schema we will work with&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">Article:
  actAs:
    Timestampable: ~
    I18n:
      fields: [ title, body ]
      actAs:
        Sluggable: { fields: [ title ], uniqueBy: [ lang, title ] }
&nbsp;
  columns:
    title: { type: string(255), notnull: true }
    body: { type: clob, notnull: true }
    author: { type: string(255), notnull: false }
&nbsp;
News:
  inheritance:
    extends: Article
    type: concrete
&nbsp;
Celebrity:
  actAs:
    Sluggable:
      fields: [ firstname, lastname ]
  columns:
    firstname: { type: string(255), notnull: true }
    lastname: { type: string(255), notnull: true }
&nbsp;
Interview:
  inheritance:
    extends: Article
    type: concrete
&nbsp;
  columns:
    celebrity_id: { type: integer, notnull: true }
&nbsp;
  relations:
&nbsp;
    Celebrity:
      local: celebrity_id
      foreign: id
      type: one
      foreignType: one
      foreignAlias: Interviews</pre></div></div>

<p>And the fixtures&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">Interview:
  i1:
    Author: 'Thibault J.'
    Celebrity:
      firstname: Thibault
      lastname: Jouannic
    Translation:
      fr:
        title: Auto-interview
        body: |
          Bla bla bla question et réponses</pre></div></div>

<p>As usual&hellip;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">php symfony build <span class="re5">--all</span> <span class="re5">--and-load</span>
php symfony doctrine:generate-admin backend Interview</pre></div></div>

<h2>Before we start</h2>
<p>Before we start, let&#8217;s stop and think a few seconds. How do we want to manage our celebrity relation into our form<span class="fine">&nbsp;</span>? Take a look at the default form, without any modification&nbsp;:</p>
<div class="postimg"><a href="http://www.flickr.com/photos/24469297@N05/4324656195/" title="01_celebrity" target="_blank"><img src="http://farm3.static.flickr.com/2687/4324656195_1f90822fc6.jpg" alt="01_celebrity" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Attribution-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> </small></div>
<p>Quite bad, isn&#8217;t it<span class="fine">&nbsp;</span>? We could make a little better by adding a toString method.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/model/doctrine/Celebrity.class.php</span>
&nbsp;
<span class="kw2">class</span> Celebrity <span class="kw2">extends</span> BaseCelebrity
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st_h">'%s %s'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getFirstname</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getLastname</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<div class="postimg"><a href="http://www.flickr.com/photos/24469297@N05/4325392592/" title="02_celebrity" target="_blank"><img src="http://farm5.static.flickr.com/4066/4325392592_dc60d3e13d.jpg" alt="02_celebrity" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Attribution-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a></small></div>
<p>That&#8217;s a bit better. The problem with this form is that you cannot add a new celebrity. If you want to create a new interview, you&#8217;ll have to chose among the existing celebrities. Of course, you could create an other admin module to manage celebrities, but a good programmer is a lazy one. And that would be great if we could create a new celebrity directly in the interview form.</p>
<p>In fact, that&#8217;s quite easy, <a href="http://prendreuncafe.com/blog/post/2009/11/29/Embedding-Relations-in-Forms-with-Symfony-1.3-and-Doctrine">using the embedRelation function</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/InterviewForm.class.php</span>
<span class="kw2">class</span> InterviewForm <span class="kw2">extends</span> BaseInterviewForm
<span class="br0">&#123;</span>
  <span class="co4">/**
   * @see ArticleForm
   */</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">configure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embedRelation</span><span class="br0">&#40;</span><span class="st_h">'Celebrity'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<div class="postimg"><a href="http://www.flickr.com/photos/24469297@N05/4325392638/" title="03_celebrity" target="_blank"><img src="http://farm5.static.flickr.com/4015/4325392638_ecf4e66bb4.jpg" alt="03_celebrity" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Attribution-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a></small></div>
<p>Here&#8217;s the result, which is quite relevant to what we wanted. But<span class="fine">&nbsp;</span>!? Wait<span class="fine">&nbsp;</span>! There is a regression. What if we want to choose among existing celebrities, the way we used to do<span class="fine">&nbsp;</span>? What we really need is a way to combine both methods actually. We need to be able to choose an existing celebrity OR to create a new one.</p>
<h2>Pick or create</h2>
<p>We will have to use an intermediate form.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/InterviewForm.class.php</span>
<span class="kw2">class</span> InterviewForm <span class="kw2">extends</span> BaseInterviewForm
<span class="br0">&#123;</span>
  <span class="co4">/**
   * @see ArticleForm
   */</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">configure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$celebrityId</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">isNew</span><span class="br0">&#40;</span><span class="br0">&#41;</span> ? <span class="kw4">NULL</span> <span class="sy0">:</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getCelebrity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$form</span> <span class="sy0">=</span> <span class="kw2">new</span> InterviewCelebrityForm<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'celebrity_id'</span> <span class="sy0">=&gt;</span> <span class="re0">$celebrityId</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embedForm</span><span class="br0">&#40;</span><span class="st_h">'Celebrity'</span><span class="sy0">,</span> <span class="re0">$form</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// lib/form/doctrine/InterviewCelebrityForm.class.php</span>
<span class="kw2">class</span> InterviewCelebrityForm <span class="kw2">extends</span> sfForm
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">widgetSchema</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> sfWidgetFormDoctrineChoice<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'model'</span> <span class="sy0">=&gt;</span> <span class="st_h">'Celebrity'</span><span class="sy0">,</span>
      <span class="st_h">'add_empty'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">setDefault</span><span class="br0">&#40;</span><span class="st_h">'celebrity_id'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getOption</span><span class="br0">&#40;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$form</span> <span class="sy0">=</span> <span class="kw2">new</span> CelebrityForm<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embedForm</span><span class="br0">&#40;</span><span class="st_h">'new_celebrity'</span><span class="sy0">,</span> <span class="re0">$form</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">widgetSchema</span><span class="sy0">-&gt;</span><span class="me1">setLabel</span><span class="br0">&#40;</span><span class="st_h">'celebrity_id'</span><span class="sy0">,</span> <span class="st_h">'Choose one…'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">widgetSchema</span><span class="sy0">-&gt;</span><span class="me1">setLabel</span><span class="br0">&#40;</span><span class="st_h">'new_celebrity'</span><span class="sy0">,</span> <span class="st_h">'or create a new.'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<div class="postimg"><a href="http://www.flickr.com/photos/24469297@N05/4325392696/" title="04_celebrity" target="_blank"><img src="http://farm3.static.flickr.com/2702/4325392696_aa940a7fb8.jpg" alt="04_celebrity" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Attribution-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a></small></div>
<p>Try to edit the existing interview, and look at the nice result. However, if you try to save the form, you&#8217;ll have a lot of validations errors. There is still some work to do before we can get rid of all those red alerts.</p>
<div class="postimg"><a href="http://www.flickr.com/photos/24469297@N05/4324656371/" title="05_celebrity" target="_blank"><img src="http://farm5.static.flickr.com/4034/4324656371_64d6c5eb2f.jpg" alt="05_celebrity" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Attribution-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a></small></div>
<h2>Form validation</h2>
<p>The form validation strategy is quite simple. If an existing celebrity is chosen with the drop down list, the firstname and lastname should be ignored. If the list is empty, we must validate the firstname and lastname. At last, we must throw an error if all the fields are empty.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/InterviewCelebrityForm.class.php</span>
&nbsp;
    <span class="co1">// add this  at the end of the configure() function</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validatorSchema</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> sfValidatorPass<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$celebrityValidatorSchema</span> <span class="sy0">=</span> clone <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validatorSchema</span><span class="br0">&#91;</span><span class="st_h">'new_celebrity'</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validatorSchema</span><span class="br0">&#91;</span><span class="st_h">'new_celebrity'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> sfValidatorPass<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validatorSchema</span><span class="sy0">-&gt;</span><span class="me1">setPostValidator</span><span class="br0">&#40;</span>
      <span class="kw2">new</span> sfValidatorAnd<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
        <span class="kw2">new</span> sfValidatorOr<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
          <span class="kw2">new</span> sfValidatorSchemaFilter<span class="br0">&#40;</span><span class="st_h">'celebrity_id'</span><span class="sy0">,</span> <span class="kw2">new</span> sfValidatorDoctrineChoice<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
            <span class="st_h">'model'</span> <span class="sy0">=&gt;</span> <span class="st_h">'Celebrity'</span><span class="sy0">,</span>
            <span class="st_h">'required'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span>
          <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span>
          <span class="kw2">new</span> sfValidatorSchemaFilter<span class="br0">&#40;</span><span class="st_h">'new_celebrity'</span><span class="sy0">,</span> <span class="re0">$celebrityValidatorSchema</span><span class="br0">&#41;</span>
        <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span>
        <span class="kw2">new</span> sfValidatorCallback<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
          <span class="st_h">'callback'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">,</span> <span class="st_h">'checkCelebrity'</span><span class="br0">&#41;</span>
        <span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// add this function into the class</span>
  <span class="co4">/**
   * Either who choose an existing celebrity, either we create a new one
   *
   * Unset values according to the choice we made
   **/</span>
  <span class="kw2">public</span> <span class="kw2">function</span> checkCelebrity<span class="br0">&#40;</span><span class="re0">$validator</span><span class="sy0">,</span> <span class="re0">$values</span><span class="sy0">,</span> <span class="re0">$argument</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="sy0">!</span><a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span>
        <span class="re0">$this</span><span class="br0">&#91;</span><span class="st_h">'new_celebrity'</span><span class="br0">&#93;</span><span class="sy0">,</span>
        <span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'new_celebrity'</span><span class="br0">&#93;</span>
      <span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
    <span class="kw1">else</span>
    <span class="br0">&#123;</span>
      <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span>
        <span class="re0">$this</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span><span class="sy0">,</span>
        <span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span>
      <span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">return</span> <span class="re0">$values</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>

<p>Try differents combinations to submit your form. The validation should behave correctly now.</p>
<h2>Saving your form</h2>
<p>You may have noticed that our interview isn&#8217;t updated correctly after we submit the form. We will have to override the doUpdateObject method in order to update the object correctly on form validation.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/InterviewForm.class.php</span>
  <span class="kw2">public</span> <span class="kw2">function</span> doUpdateObject<span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="sy0">!</span><a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'Celebrity'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">setCelebrityId</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'Celebrity'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'celebrity_id'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
    <span class="kw1">else</span>
    <span class="br0">&#123;</span>
      <span class="re0">$celebrity</span> <span class="sy0">=</span> <span class="kw2">new</span> Celebrity<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">fromArray</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'Celebrity'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'new_celebrity'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">Celebrity</span> <span class="sy0">=</span> <span class="re0">$celebrity</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span>
      <span class="re0">$values</span><span class="br0">&#91;</span><span class="st_h">'Celebrity'</span><span class="br0">&#93;</span><span class="sy0">,</span>
      <span class="re0">$this</span><span class="br0">&#91;</span><span class="st_h">'Celebrity'</span><span class="br0">&#93;</span>
    <span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    parent<span class="sy0">::</span><span class="me2">doUpdateObject</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>

<p>That&#8217;s it<span class="fine">&nbsp;</span>! Everything should be alright now. But just to make sure, here&#8217;s a few tests.</p>
<h2>Test your forms</h2>
<p>We are reusing some code from the last day, so I just will output the new part here.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">// test/function/backend/interviewActions.class.php
&nbsp;
<span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw1">include</span><span class="br0">&#40;</span><a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../../bootstrap/functional.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$browser</span> <span class="sy0">=</span> <span class="kw2">new</span> sfBackendTestFunctional<span class="br0">&#40;</span><span class="kw2">new</span> sfBrowser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$browser</span><span class="sy0">-&gt;</span><span class="me1">loadData</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$browser</span><span class="sy0">-&gt;</span><span class="me1">setTester</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="sy0">,</span> <span class="st_h">'sfTesterDoctrine'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$interview</span> <span class="sy0">=</span> Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'Interview'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st_h">'i'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">leftJoin</span><span class="br0">&#40;</span><span class="st_h">'i.Translation t'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">andWhere</span><span class="br0">&#40;</span><span class="st_h">'t.lang = ?'</span><span class="sy0">,</span> <span class="st_h">'fr'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">orderBy</span><span class="br0">&#40;</span><span class="st_h">'i.id'</span><span class="sy0">,</span> <span class="st_h">'asc'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">fetchOne</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$celebrity</span> <span class="sy0">=</span> <span class="kw2">new</span> Celebrity<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">setFirstname</span><span class="br0">&#40;</span><span class="st_h">'toto'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">setLastname</span><span class="br0">&#40;</span><span class="st_h">'tutu'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">save</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$editUrl</span> <span class="sy0">=</span> <a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st_h">'/interview/%s/edit'</span><span class="sy0">,</span> <span class="re0">$interview</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$browser</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'/interview'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'1 - Interview list'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">checkElement</span><span class="br0">&#40;</span><span class="st_h">'h1'</span><span class="sy0">,</span> <span class="st_h">'/Interview List/'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">checkElement</span><span class="br0">&#40;</span><span class="st_h">'body'</span><span class="sy0">,</span> <span class="st_h">'/Thibault Jouannic/'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
<span class="co1">// …</span>
&nbsp;
   info<span class="br0">&#40;</span><span class="st_h">'  2.8 - The current celebrity is already selected'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">checkElement</span><span class="br0">&#40;</span><span class="st_h">'#interview_Celebrity_celebrity_id option[selected=&quot;selected&quot;]'</span><span class="sy0">,</span> <a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st_h">'/%s/'</span><span class="sy0">,</span> <span class="re0">$interview</span><span class="sy0">-&gt;</span><span class="me1">getCelebrity</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.9 - The current celebrity can be updated'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'interview'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'Celebrity'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'celebrity_id'</span> <span class="sy0">=&gt;</span> <span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
      <span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'Interview'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$interview</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'celebrity_id'</span> <span class="sy0">=&gt;</span> <span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.10 - Updating the celebrity does not create empty records'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'Celebrity'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.11 - A new celebrity can be created'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'interview'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'Celebrity'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'celebrity_id'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
      <span class="st_h">'NewCelebrity'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
        <span class="st_h">'firstname'</span> <span class="sy0">=&gt;</span> <span class="st_h">'oncle'</span><span class="sy0">,</span>
        <span class="st_h">'lastname'</span> <span class="sy0">=&gt;</span> <span class="st_h">'picsou'</span>
      <span class="br0">&#41;</span>
    <span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'Celebrity'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="nu0">5</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'Interview'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$interview</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'celebrity_id'</span> <span class="sy0">=&gt;</span> <span class="re0">$celebrity</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="nu0">1</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="sy0">;</span></pre></div></div>

<p>That&#8217;s all folks<span class="fine">&nbsp;</span>! See you soon.</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F466-symfony-form-pick-or-create"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F466-symfony-form-pick-or-create" height="61" width="51" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/tutos/466-symfony-form-pick-or-create/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>L’automobiliste du vendredi soir</title>
		<link>http://www.miximum.fr/tranche_vie/456-lautomobiliste-du-vendredi-soir</link>
		<comments>http://www.miximum.fr/tranche_vie/456-lautomobiliste-du-vendredi-soir#comments</comments>
		<pubDate>Fri, 29 Jan 2010 19:25:57 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Tranche de vie]]></category>
		<category><![CDATA[divers]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=456</guid>
		<description><![CDATA[ photo credit&#160;: ルーク.チャン.チャン
Il m&#8217;arrive d&#8217;&#234;tre stupide, parfois. Si si, &#231;a m&#8217;arrive. Tenez, aujourd&#8217;hui par exemple, j&#8217;ai &#233;t&#233; assez b&#234;te pour aller faire des courses en centre ville, un vendredi, &#224; 17h30. Moi qui suis freelance, et travaille &#224; domicile, avouez, faut quand m&#234;me pas &#234;tre fut&#233;.
Parce qu&#8217;&#224; 17h30, &#224; Montpellier, dans le cente-ville, il [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Ftranche_vie%2F456-lautomobiliste-du-vendredi-soir"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Ftranche_vie%2F456-lautomobiliste-du-vendredi-soir" height="61" width="51" /></a></div><div class="postimg alignleft"><a href="http://www.flickr.com/photos/82327812@N00/3909305503/" title="on the way back home" target="_blank"><img src="http://farm3.static.flickr.com/2487/3909305503_17aa1c7e0e_m.jpg" alt="on the way back home" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/82327812@N00/3909305503/" title="ルーク.チャン.チャン" target="_blank">ルーク.チャン.チャン</a></small></div>
<p>Il m&#8217;arrive d&#8217;&ecirc;tre stupide, parfois. Si si, &ccedil;a m&#8217;arrive. Tenez, aujourd&#8217;hui par exemple, j&#8217;ai &eacute;t&eacute; assez b&ecirc;te pour aller faire des courses en centre ville, un vendredi, &agrave; 17h30. Moi qui suis freelance, et travaille &agrave; domicile, avouez, faut quand m&ecirc;me pas &ecirc;tre fut&eacute;.</p>
<p>Parce qu&#8217;&agrave; 17h30, &agrave; Montpellier, dans le cente-ville, il y a beaucoup de voitures immobiles. &Agrave; la limite, dans la mesure ou je suis cycliste, ces voitures ne me d&eacute;rangeraient pas plus que &ccedil;a, si chacune d&#8217;entre elle ne contenait un petit automobiliste aigri et hargneux.</p>
<p>Car l&#8217;automobiliste du vendredi soir, ext&eacute;nu&eacute; par sa semaine de travail, et press&eacute; de rentrer chez lui s&#8217;affaler devant sa t&eacute;l&eacute;, a tout de la version bip&egrave;de du bichon. Mais si, ce petit monstre au poil blanc, version animale de la brosse &agrave; chiottes, &agrave; l&#8217;aboiement strident, et dont il est impossible de distinguer l&#8217;avant du derri&egrave;re.</p>
<p>C&#8217;est amusant l&#8217;&eacute;volution. Prenons le cas des chats, par exemple. &Agrave; l&#8217;instar d&#8217;un pigeon, un chat peut objectivement &ecirc;tre consid&eacute;r&eacute; comme un animal &agrave; faible valeur ajout&eacute;e. En gros, un chat, &ccedil;a bouffe, &ccedil;a dort, &ccedil;a casse deux ou trois trucs de temps en temps, mais &agrave; part &ccedil;a, &ccedil;a ne sert &agrave; rien</p>
<p> Seulement voil&agrave;, l&#8217;&eacute;volution a conf&eacute;r&eacute; au chat, notamment dans sa version juv&eacute;nile, un minois si adorable qu&#8217;il est tout bonnement impossible pour un &ecirc;tre humain normalement constitu&eacute; de ne pas s&#8217;y attacher. Et c&#8217;est ainsi que l&#8217;esp&egrave;ce du chat, si&egrave;cle apr&egrave;s si&egrave;cle, continue de se perp&eacute;tuer, comptant sur sa miraculeuses facult&eacute; &agrave; se faire offrir &agrave; bouffer. </p>
<p>Quand aux bichons, honn&ecirc;tement, je ne comprends pas comment ils ont r&eacute;ussi &agrave; ne pas tous se faire transformer en saucisses. Allons, je ne d&eacute;sesp&egrave;re pas.</p>
<div class="postimg alignright"><a href="http://www.flickr.com/photos/70757073@N00/131100622/" title="peque&ntilde;ita" target="_blank"><img src="http://farm1.static.flickr.com/51/131100622_f6c985bf36_m.jpg" alt="peque&ntilde;ita" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-nd/2.0/" title="Attribution-NonCommercial-NoDerivs License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/70757073@N00/131100622/" title="Difusa" target="_blank">Difusa</a></small></div>
<p>Mais je digresse, je divague, et je m&#8217;&eacute;loigne de mon sujet<sup><a href="#footnote-1-456" id="footnote-link-1-456" title="Voir la note.">[1]</a></sup>. Sujet qui est, je le rappelle pour les moins attentifs d&#8217;entres vous, l&#8217;aggressivit&eacute; hargneuses de l&#8217;automobiliste du vendredi soir. Car si le bichon aboie, l&#8217;automobiliste lui klaxonne rageusement, convaincu que gr&acirc;ce &agrave; un myst&eacute;rieux ph&eacute;nom&egrave;ne physique, plus il fera de bruit, plus vite il sera chez lui.</p>
<p>Les geeks le savent, le vendredi est le jour du troll. Le jour ou il est tol&eacute;r&eacute;, dans les limites impos&eacute;es par le bon sens, de prendre quelques libert&eacute;s avec la netiquette. Sans doute inspir&eacute;s par cette charmante coutume, les automobilistes, eux aussi, d&eacute;cident parfois de prendre quelques libert&eacute;s avec la &laquo;&nbsp;&nbsp;netiquette de la route&nbsp;&nbsp;&raquo;.</p>
<p>Seulement voil&agrave;, contrairement &agrave; la netiquette du web, qu&#8217;il est recommand&eacute; de suivre pour le confort de tous, la n&eacute;tiquette de l&#8217;automobiliste, plus connue sous le nom de &laquo;&nbsp;&nbsp;code de la route&nbsp;&nbsp;&raquo;, n&#8217;est pas facultative. En fait, le code de la route est m&ecirc;me un texte l&eacute;gislatif, un truc quand m&ecirc;me un peu s&eacute;rieux, du genre qu&#8217;on n&#8217;est pas cens&eacute; trop faire le guignol avec.</p>
<p>Alors, puisque j&#8217;ai la chance de disposer ici d&#8217;un espace d&#8217;expression libre, et que peut-&ecirc;tre, il reste un ou deux automobilistes &agrave; lire ces lignes, voici quelques r&egrave;gles que je souhaite rappeler &agrave; leur attention&nbsp;:</p>
<ol>
<li>En agglom&eacute;ration, l&#8217;usage de l&#8217;avertisseur sonore n&#8217;est autoris&eacute; qu&#8217;en cas de danger imm&eacute;diat. (art. R416-1 du code de la route). Je tiens &agrave; pr&eacute;ciser que l&#8217;hypoth&eacute;tique possibilit&eacute; de pouvoir esp&eacute;rer faire avancer sa voiture de quelques centim&egrave;tres ne constitue pas un danger imm&eacute;diat&nbsp;<span class="fine">&nbsp;</span>;</li>
<li>L&#8217;arr&ecirc;t ou le stationnement d&#8217;un v&eacute;hicule empi&eacute;tant sur un passage pr&eacute;vu &agrave; l&#8217;intention des pi&eacute;tons est interdit. (art. Article R417-5 du code de la route)&nbsp;<span class="fine">&nbsp;</span>;</li>
</ol>
<p>Bref<span class="fine">&nbsp;</span>!&nbsp;Tout ce que je viens de tartiner pourrait en fait &ecirc;tre r&eacute;sum&eacute; de mani&egrave;re assez concise&nbsp;: <strong>Si vous &ecirc;tes un automobiliste, que vous klaxonnez en agglom&eacute;ration juste parce que vous &ecirc;tes fatigu&eacute;, et/ou stationnez sur les passages pi&eacute;tons (m&ecirc;me quelques secondes), ne vous cherchez pas d&#8217;excuses&nbsp;: vous &ecirc;tes un con et vous me faites chier</strong>.</p>
<p>C&#8217;&eacute;tait vendredi, merci de votre attention, et bon week-end &agrave; vous.</p>
<h4>Notes&nbsp;:</h4><ol class="footnotes"><li id="footnote-1-456">Mais bon, pour une fois que je peux illustrer mon blog avec des photos de chats.  [<a href="#footnote-link-1-456">retour</a>]</li></ol><div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Ftranche_vie%2F456-lautomobiliste-du-vendredi-soir"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Ftranche_vie%2F456-lautomobiliste-du-vendredi-soir" height="61" width="51" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/tranche_vie/456-lautomobiliste-du-vendredi-soir/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Optional translation form for I18n objects with Symfony and Doctrine</title>
		<link>http://www.miximum.fr/tutos/449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine</link>
		<comments>http://www.miximum.fr/tutos/449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine#comments</comments>
		<pubDate>Fri, 29 Jan 2010 14:23:20 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Tutos]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[I18n]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=449</guid>
		<description><![CDATA[ photo credit&#160;: kevindooley
There are people around here claiming that the Symfony form framework is a gift from the gods. One might say that this statement is a bit exaggerated, but it&#8217;s true that the release of the 1.3/1.4 version of the Symfony brought many improvements, and yes, the form framework can save you a [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine" height="61" width="51" /></a></div><div class="postimg alignleft"><a href="http://www.flickr.com/photos/12836528@N00/2201791390/" title="Scaffolding: Not just for construction workers anymore" target="_blank"><img src="http://farm3.static.flickr.com/2037/2201791390_7bc614e27c_m.jpg" alt="Scaffolding: Not just for construction workers anymore" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by/2.0/" title="Attribution License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/12836528@N00/2201791390/" title="kevindooley" target="_blank">kevindooley</a></small></div>
<p>There are people around here claiming that the <a href="http://www.symfony-project.org/forms/1_4/">Symfony form framework</a> is a gift from the gods. One might say that this statement is a bit exaggerated, but it&#8217;s true that the release of the 1.3/1.4 version of the Symfony brought many improvements, and yes, the form framework can save you a lot of time.</p>
<p>In one of my current project, I had to developp some basic CMS-like features. In a back-office, an admin should be able to writes different kind of articles (news, interviews&hellip;). Hey<span class="fine">&nbsp;</span>! <a href="http://www.symfony-project.org/more-with-symfony/1_4/en/09-Doctrine-Form-Inheritance">That&#8217;s a job for inheritance<span class="fine">&nbsp;</span>!</a> But wait, there&#8217;s more. Articles can be translated in several languages. <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors#core-behaviors:i18n">Easy, with the Doctrine I18n behavior</a>.</p>
<p>One last requirement&nbsp;: article translations are optional. One might publish an article in english, an other in french, and a third in both languages. This is a little more tricky, so let&#8217;s see how to do this.</p>
<h2>Some references</h2>
<p>Before we start, here are the wonderful ressources I read to get my way out&nbsp;:</p>
<p><a href="http://prendreuncafe.com/blog/post/2009/11/29/Embedding-Relations-in-Forms-with-Symfony-1.3-and-Doctrine"> http://prendreuncafe.com/blog/post/2009/11/29/Embedding-Relations-in-Forms-with-Symfony-1.3-and-Doctrine</a><br />
<a href="http://symfonyguide.wordpress.com/2009/09/28/symfony-forms-saving-process/"> http://symfonyguide.wordpress.com/2009/09/28/symfony-forms-saving-process/</a><br />
<a href="http://vousavezchoisi.com/img/formsdiagram.png"> http://vousavezchoisi.com/img/formsdiagram.png</a><br />
<a href="http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_ignoring_embedded_forms"> http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_ignoring_embedded_forms</a><br />
<a href="http://www.ze-technology.com/2009/06/05/tests-fonctionnels-avec-symfony-gerer-lidentification/"> http://www.ze-technology.com/2009/06/05/tests-fonctionnels-avec-symfony-gerer-lidentification/</a></p>
<h2>Let&#8217;s start with the schema</h2>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">Article:
  actAs:
    Timestampable: ~
    I18n:
      fields: [ title, body ]
      actAs:
        Sluggable: { fields: [ title ], uniqueBy: [ lang, title ] }
&nbsp;
  columns:
    title: { type: string(255), notnull: true }
    body: { type: clob, notnull: true }
    author: { type: string(255), notnull: false }
&nbsp;
News:
  inheritance:
    extends: Article
    type: concrete</pre></div></div>

<p>As it&#8217;s friday, I will also give you some fixtures&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">News:
  n1:
    author: 'Fantomas'
    Translation:
      fr:
        title: 'OK, l''Ipad est sorti. Vous allez me foutre la paix maintentant ?'
        body: |
          Vous commencez serieusement à me gonfler avec vos articles et vos tweets sur
          une techno inutile et bardée de DRM.
&nbsp;
  n2:
    author: 'Garcin Fony'
    Translation:
      fr:
        title: 'Sinon, à part ça, ça va ?'
        body: |
          Allez, pour me calmer, je vais me refaire un p'tit café</pre></div></div>

<p>Let&#8217;s build the whole thing, and generate the admin in the same time.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">php symfony doctrine:build <span class="re5">--all</span> <span class="re5">--and-load</span>
php symfony generate:app backend
php symfony doctrine:generate-admin backend News</pre></div></div>

<p>Check the module admin we&#8217;ve just build. Click on the first &laquo;&nbsp;&nbsp;edit&nbsp;&nbsp;&raquo; button. Wait a minute<span class="fine">&nbsp;</span>? The I18n fields are just missing, how are we gonna edit our articles<span class="fine">&nbsp;</span>? If you&#8217;re not familiar with the I18n behavior, you must know that the content is split into two tables. The new table, &laquo;&nbsp;&nbsp;article_translation&nbsp;&nbsp;&raquo;, holds all the I18n fields.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">mysql<span class="sy0">&gt;</span> <span class="kw1">SELECT</span> <span class="sy0">*</span> <span class="kw1">FROM</span> news;
<span class="sy0">+</span><span class="co1">----+-------------+---------------------+---------------------+</span>
<span class="sy0">|</span> id <span class="sy0">|</span> author      <span class="sy0">|</span> created_at          <span class="sy0">|</span> updated_at          <span class="sy0">|</span>
<span class="sy0">+</span><span class="co1">----+-------------+---------------------+---------------------+</span>
<span class="sy0">|</span>  <span class="nu0">1</span> <span class="sy0">|</span> Fantomas    <span class="sy0">|</span> <span class="nu0">2010</span><span class="sy0">-</span>01<span class="sy0">-</span><span class="nu0">29</span> <span class="nu0">12</span>:<span class="nu0">14</span>:<span class="nu0">46</span> <span class="sy0">|</span> <span class="nu0">2010</span><span class="sy0">-</span>01<span class="sy0">-</span><span class="nu0">29</span> <span class="nu0">12</span>:<span class="nu0">14</span>:<span class="nu0">46</span> <span class="sy0">|</span> 
<span class="sy0">|</span>  <span class="nu0">2</span> <span class="sy0">|</span> Garcin Fony <span class="sy0">|</span> <span class="nu0">2010</span><span class="sy0">-</span>01<span class="sy0">-</span><span class="nu0">29</span> <span class="nu0">12</span>:<span class="nu0">14</span>:<span class="nu0">46</span> <span class="sy0">|</span> <span class="nu0">2010</span><span class="sy0">-</span>01<span class="sy0">-</span><span class="nu0">29</span> <span class="nu0">12</span>:<span class="nu0">14</span>:<span class="nu0">46</span> <span class="sy0">|</span> 
<span class="sy0">+</span><span class="co1">----+-------------+---------------------+---------------------+</span>
&nbsp;
mysql<span class="sy0">&gt;</span> <span class="kw1">SELECT</span> id<span class="sy0">,</span> lang<span class="sy0">,</span> title <span class="kw1">FROM</span> news_translation;
<span class="sy0">+</span><span class="co1">----+------+------------------------------------------------------------------+</span>
<span class="sy0">|</span> id <span class="sy0">|</span> lang <span class="sy0">|</span> title                                                            <span class="sy0">|</span>
<span class="sy0">+</span><span class="co1">----+------+------------------------------------------------------------------+</span>
<span class="sy0">|</span>  <span class="nu0">1</span> <span class="sy0">|</span> fr   <span class="sy0">|</span> OK<span class="sy0">,</span> l<span class="st0">'Ipad est sorti. Vous allez me foutre la paix maintentant ? | 
|  2 | fr   | Sinon, à part ça, ça va ?                                     | 
+----+------+------------------------------------------------------------------+</span></pre></div></div>

<p>So, to be able to edit our translations, you have to embed the I18n forms, using the embedI18 function. Let&#8217;s do that.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/NewsForm.class.php</span>
<span class="kw2">class</span> NewsForm <span class="kw2">extends</span> BaseNewsForm
<span class="br0">&#123;</span>
  <span class="co4">/**
   * @see ArticleForm
   */</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">configure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embedI18n</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'fr'</span><span class="sy0">,</span> <span class="st_h">'en'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Reload the edit page. Now you can edit your news in french and english. Pretty cool, isn&#8217;t it<span class="fine">&nbsp;</span>?</p>
<h2>Let&#8217;s refactor this mess</h2>
<p>Since now, it&#8217;s been pretty easy. However, the code we&#8217;ve written is bad. It&#8217;s bad, for the following reasons&nbsp;:</p>
<ol>
<li>Each time we will add a new article type (e.g. interview, etc.), we will have to update it&#8217;s configure method&nbsp;<span class="fine">&nbsp;</span>;</li>
<li>Each time we will change the available languages (to add a new one, or disable an existing one), we will have to edit every forms&nbsp;<span class="fine">&nbsp;</span>;</li>
</ol>
<p>Fortunately, since Symfony 1.3, <a href="http://www.symfony-project.org/tutorial/1_4/en/whats-new#chapter_a2fae23c9403b0e9ec99806fccf6b53e_sub_form_classes_inheritance">the form inheritance follow the model structure</a>. Notice that NewsForm extends BaseNewsForm, which extends ArticleForm.</p>
<p>Let&#8217;s refactor our code&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"># config/app.yml
all:
  cultures:
    enabled:
      fr: Français
      en: English</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/NewsForm.class.php</span>
&nbsp;
<span class="co1">// Revert the changes we added there</span>
<span class="kw2">class</span> NewsForm <span class="kw2">extends</span> BaseNewsForm
<span class="br0">&#123;</span>
  <span class="co4">/**
   * @see ArticleForm
   */</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">configure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// lib/form/doctrine/ArticleForm.class.php</span>
<span class="kw2">class</span> ArticleForm <span class="kw2">extends</span> BaseArticleForm
<span class="br0">&#123;</span>
  <span class="co4">/**
   * Available languages
   *
   * @var array $languages
   **/</span>
  protected <span class="re0">$langages</span><span class="sy0">;</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_cultures_enabled'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$langs</span> <span class="sy0">=</span> <a href="http://www.php.net/array_keys"><span class="kw3">array_keys</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embedI18n</span><span class="br0">&#40;</span><span class="re0">$langs</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span> <span class="kw1">as</span> <span class="re0">$lang</span> <span class="sy0">=&gt;</span> <span class="re0">$label</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">widgetSchema</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="sy0">-&gt;</span><span class="me1">setLabel</span><span class="br0">&#40;</span><span class="re0">$label</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Reload the edit form. Now, no matter how many articles sub-types you add, you still can configure available languages from one place.</p>
<h2>Translation edition</h2>
<p>Let&#8217;s try our brand new admin module by editing a news. If you used the fixtures I provided, you should have a french article, with no english translation. Try to update the french version, and click on the &#8216;Save&#8217; button.</p>
<p>This is a miserable failure. We can&#8217;t save the form, because the english fields are required. We&#8217;re stuck, we have to fill every translation for an article before we can save it. Wouldn&#8217;t it be nice if we could make a translation form optional<span class="fine">&nbsp;</span>? Let&#8217;s add a requirement&nbsp;: if every fields in a translation form are empty, it just should be ignored.</p>
<p>To achieve this goal, we will update the doBind method. Here&#8217;s the new ArticleForm class.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/ArticleForm.class.php</span>
<span class="kw2">class</span> ArticleForm <span class="kw2">extends</span> BaseArticleForm
<span class="br0">&#123;</span>
  <span class="co4">/**
   * Available languages
   *
   * @var array $languages
   **/</span>
  protected <span class="re0">$langages</span><span class="sy0">;</span>
&nbsp;
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_cultures_enabled'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$langs</span> <span class="sy0">=</span> <a href="http://www.php.net/array_keys"><span class="kw3">array_keys</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embedI18n</span><span class="br0">&#40;</span><span class="re0">$langs</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span> <span class="kw1">as</span> <span class="re0">$lang</span> <span class="sy0">=&gt;</span> <span class="re0">$label</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">widgetSchema</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="sy0">-&gt;</span><span class="me1">setLabel</span><span class="br0">&#40;</span><span class="re0">$label</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co4">/**
   * Cleans and binds values to the current form
   *
   * Ignore i18n forms when all their fields are empty
   *
   * @see sfForm::doBind
   **/</span>
  protected <span class="kw2">function</span> doBind<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a> <span class="re0">$values</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span> <span class="kw1">as</span> <span class="re0">$lang</span> <span class="sy0">=&gt;</span> <span class="re0">$label</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embeddedI18nFormIsEmpty</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span>
          <span class="re0">$values</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="sy0">,</span>
          <span class="re0">$this</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span>
        <span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    parent<span class="sy0">::</span><span class="me2">doBind</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co4">/**
   * Check if every fields, except for id and lang, are empty
   **/</span>
  protected <span class="kw2">function</span> embeddedI18nFormIsEmpty<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a> <span class="re0">$values</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$values</span> <span class="kw1">as</span> <span class="re0">$key</span> <span class="sy0">=&gt;</span> <span class="re0">$value</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/in_array"><span class="kw3">in_array</span></a><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'id'</span><span class="sy0">,</span> <span class="st_h">'lang'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        <span class="kw1">continue</span><span class="sy0">;</span>
&nbsp;
      <span class="kw1">if</span><span class="br0">&#40;</span><span class="st_h">''</span> <span class="sy0">!==</span> <a href="http://www.php.net/trim"><span class="kw3">trim</span></a><span class="br0">&#40;</span><span class="re0">$value</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="kw4">false</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
    <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>In the overidden doBind method, we check, for every I18n form, if some values has been submited. If not, we just unset the corresponding fields.</p>
<p>Reload the edit form, update the french translation, leave the english field empty, and click on &#8216;Save&#8217;. Hurray, the forms is saved correctly.</p>
<p>However, you should keep reading, because you&#8217;re gonna have a surprise. Let&#8217;s look into the database.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">mysql<span class="sy0">&gt;</span> <span class="kw1">SELECT</span> id<span class="sy0">,</span> lang<span class="sy0">,</span> slug <span class="kw1">FROM</span> news_translation;
<span class="sy0">+</span><span class="co1">----+------+--------------------------------------------------------------+</span>
<span class="sy0">|</span> id <span class="sy0">|</span> lang <span class="sy0">|</span> slug                                                         <span class="sy0">|</span>
<span class="sy0">+</span><span class="co1">----+------+--------------------------------------------------------------+</span>
<span class="sy0">|</span>  <span class="nu0">1</span> <span class="sy0">|</span> en   <span class="sy0">|</span>                                                              <span class="sy0">|</span> 
<span class="sy0">|</span>  <span class="nu0">1</span> <span class="sy0">|</span> fr   <span class="sy0">|</span> ok<span class="sy0">-</span>l<span class="sy0">-</span>ipad<span class="sy0">-</span>est<span class="sy0">-</span>sorti<span class="sy0">-</span>vous<span class="sy0">-</span>allez<span class="sy0">-</span>me<span class="sy0">-</span>foutre<span class="sy0">-</span>la<span class="sy0">-</span>paix<span class="sy0">-</span>maintentant <span class="sy0">|</span> 
<span class="sy0">|</span>  <span class="nu0">2</span> <span class="sy0">|</span> fr   <span class="sy0">|</span> sinon<span class="sy0">-</span>a<span class="sy0">-</span>part<span class="sy0">-</span>ca<span class="sy0">-</span>ca<span class="sy0">-</span>va                                        <span class="sy0">|</span> 
<span class="sy0">+</span><span class="co1">----+------+--------------------------------------------------------------</span></pre></div></div>

<p>Something went wrong<span class="fine">&nbsp;</span>! Somewhere in the process, Symfony created an empty translation object for our article. Notice the void &laquo;&nbsp;&nbsp;slug&nbsp;&nbsp;&raquo; field<span class="fine">&nbsp;</span>? If you try to edit another news, you will receive a duplicate content error. WTF<span class="fine">&nbsp;</span>?</p>
<p>I must admit that I don&#8217;t fully understand why this happens (sometimes I think I do, and a few minutes later, I realize I don&#8217;t). However, here&#8217;s the solution to overcome this problem.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/ArticleForm.class.php</span>
&nbsp;
  <span class="co1">// Add this at the beginnig of the class:</span>
  <span class="co4">/**
   * I18n ignored forms
   **/</span>
  protected <span class="re0">$I18nFormsIgnored</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// update the doBind method:</span>
  <span class="co4">/**
   * Unset i18n forms values when every field is empty
   **/</span>
  protected <span class="kw2">function</span> doBind<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a> <span class="re0">$values</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">languages</span> <span class="kw1">as</span> <span class="re0">$lang</span> <span class="sy0">=&gt;</span> <span class="re0">$label</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">embeddedI18nFormEmpty</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">I18nFormsIgnored</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re0">$lang</span><span class="sy0">;</span>
        <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span>
          <span class="re0">$values</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="sy0">,</span>
          <span class="re0">$this</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span>
        <span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    parent<span class="sy0">::</span><span class="me2">doBind</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co1">// And override the doUpdateObject method:</span>
  <span class="co4">/**
   * Updates the values of the object with the cleaned up values.
   *
   * @param  array $values An array of values
   *
   * @see sfFormDoctrine::doUpdateObject()
   */</span>
  protected <span class="kw2">function</span> doUpdateObject<span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">doUpdateObject</span><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">I18nFormsIgnored</span> <span class="kw1">as</span> <span class="re0">$lang</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">object</span><span class="sy0">-&gt;</span><span class="me1">Translation</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$values</span><span class="br0">&#91;</span><span class="re0">$lang</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span></pre></div></div>

<p>Delete the useless line in the mysql database, so we can start on a clean base. Once more, reload the edit form, leave the english translation empty, save the form, et voil&agrave;<span class="fine">&nbsp;</span>! The form is saved, the translation is updated, and no empty line is added in the table.</p>
<h2>Adding and deleting a translation</h2>
<p>Just to be sure, add some data in the english translation title, and try to save the form. You should get a &laquo;&nbsp;&nbsp;body is required&nbsp;&nbsp;&raquo; error, which is the expected behavior. Try to fill correctly the english translation, and save again. Check that the english translation is correctly added in the database. Erase all french fields, save one more time, and check that the french translation is definitly removed from the DB (no dummy entry).</p>
<p>Well, it seems that our form is pretty functional. One last thing&nbsp;: there is still a &laquo;&nbsp;&nbsp;slug&nbsp;&nbsp;&raquo; field in each translation form, that you might want to unset. Easy, just edit the ArticleTranslationForm.class.php file&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/ArticleTranslationForm.class.php</span>
&nbsp;
<span class="kw2">class</span> ArticleTranslationForm <span class="kw2">extends</span> BaseArticleTranslationForm
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$this</span><span class="br0">&#91;</span><span class="st_h">'slug'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Edit a news. If you&#8217;re using Symfony 1.{3,4}.1, you&#8217;ll see that the damn slug field is still there. It&#8217;s a Symfony bug. Indeed, <a href="http://trac.symfony-project.org/ticket/8199">the translations forms don&#8217;t follow the inheritance schema</a>. Notice that BaseNewsTranslationForm extends BaseFormDoctrine instead of ArticleNewsTranslation.</p>
<p>You&#8217;ll have to manually change that, however, this will be overidden each time you rebuild your forms.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/form/doctrine/base/BaseNewsTranslationForm.class.php</span>
<span class="co1">// Replace</span>
abstract <span class="kw2">class</span> BaseNewsTranslationForm <span class="kw2">extends</span> BaseFormDoctrine
&nbsp;
<span class="co1">// with</span>
abstract <span class="kw2">class</span> BaseNewsTranslationForm <span class="kw2">extends</span> ArticleTranslationForm
&nbsp;
<span class="co1">// lib/form/doctrine/NewsTranslationForm.class.php</span>
<span class="co1">// Edit the configure method</span>
<span class="kw2">class</span> NewsTranslationForm <span class="kw2">extends</span> BaseNewsTranslationForm
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">configure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Now, the slug field should disapear. At the present moment, the bug is still open.</p>
<h2>Let&#8217;s test everything</h2>
<p>As it&#8217;s friday, I feel generous, so as a bonus, I will give you the functional tests to cover our magical form. Enjoy.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/sfBackendTestFunctional.class.php</span>
<span class="co4">/**
 * This class is used to run functional tests in a secured backend
 *
 * Takes care of the login action, and the fixtures loading
 */</span>
<span class="kw2">class</span> sfBackendTestFunctional <span class="kw2">extends</span> sfTestFunctional
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="re0">$browser</span><span class="sy0">,</span> <span class="re0">$lime</span> <span class="sy0">=</span> <span class="kw4">null</span><span class="sy0">,</span> <span class="re0">$testers</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span>__construct<span class="br0">&#40;</span><span class="re0">$browser</span><span class="sy0">,</span> <span class="re0">$lime</span><span class="sy0">,</span> <span class="re0">$testers</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
&nbsp;
  <span class="co4">/**
   * Perform user authentication
   *
   * @param   array of String         $user_data
   * @return  sfGuardTestFunctional   $this
   */</span>
  <span class="kw2">public</span> <span class="kw2">function</span> signin<span class="br0">&#40;</span><span class="re0">$user_data</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
   <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">info</span><span class="br0">&#40;</span><a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st_h">'Login as &quot;%s&quot;'</span><span class="sy0">,</span> <span class="re0">$user_data</span><span class="br0">&#91;</span><span class="st_h">'username'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
     <span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'/login'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
     <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'sign in'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'signin'</span> <span class="sy0">=&gt;</span> <span class="re0">$user_data</span><span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
     <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
     <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
     <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'user'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <span class="me1">isAuthenticated</span><span class="br0">&#40;</span><span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
     <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
     <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'request'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <span class="me1">isParameter</span><span class="br0">&#40;</span><span class="st_h">'module'</span><span class="sy0">,</span> <span class="st_h">'sfGuardAuth'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <span class="me1">isParameter</span><span class="br0">&#40;</span><span class="st_h">'action'</span><span class="sy0">,</span> <span class="st_h">'signin'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
     <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
     <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <span class="me1">isRedirected</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <span class="me1">followRedirect</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
       <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="sy0">;</span>
  <span class="br0">&#125;</span>
  <span class="co4">/**
   * Load project fixtures
   **/</span>
  <span class="kw2">public</span> <span class="kw2">function</span> loadData<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    Doctrine<span class="sy0">::</span><span class="me2">loadData</span><span class="br0">&#40;</span>sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_data_dir'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/fixtures'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// test/functional/backend/newsActionsTest.php</span>
&nbsp;
<span class="kw1">include</span><span class="br0">&#40;</span><a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../../bootstrap/functional.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$browser</span> <span class="sy0">=</span> <span class="kw2">new</span> sfBackendTestFunctional<span class="br0">&#40;</span><span class="kw2">new</span> sfBrowser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$browser</span><span class="sy0">-&gt;</span><span class="me1">loadData</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$browser</span><span class="sy0">-&gt;</span><span class="me1">setTester</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="sy0">,</span> <span class="st_h">'sfTesterDoctrine'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$languages</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_cultures_enabled'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$news</span> <span class="sy0">=</span> Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'News'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st_h">'n'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">leftJoin</span><span class="br0">&#40;</span><span class="st_h">'n.Translation t'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">andWhere</span><span class="br0">&#40;</span><span class="st_h">'t.lang = ?'</span><span class="sy0">,</span> <span class="st_h">'fr'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">orderBy</span><span class="br0">&#40;</span><span class="st_h">'n.id'</span><span class="sy0">,</span> <span class="st_h">'asc'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">fetchOne</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$editUrl</span> <span class="sy0">=</span> <a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st_h">'/news/%s/edit'</span><span class="sy0">,</span> <span class="re0">$news</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$browser</span><span class="sy0">-&gt;</span>
  <span class="co1">// Uncomment this if your backend is protected by a login</span>
  <span class="co1">//signin(array(</span>
  <span class="co1">//  'username' =&gt; 'admin',</span>
  <span class="co1">//  'password' =&gt; 'admin'</span>
  <span class="co1">//)))-&gt;</span>
  get<span class="br0">&#40;</span><span class="st_h">'/news'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'1 - News list'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">checkElement</span><span class="br0">&#40;</span><span class="st_h">'h1'</span><span class="sy0">,</span> <span class="st_h">'/News List/'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">checkElement</span><span class="br0">&#40;</span><span class="st_h">'body'</span><span class="sy0">,</span> <span class="st_h">'/Fantomas/'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'2 - News edit'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.1 - I18n forms for all languages are embedded'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'response'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">isStatusCode</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">checkElement</span><span class="br0">&#40;</span><span class="st_h">'input[name$=&quot;[title]&quot;]'</span><span class="sy0">,</span> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">&#40;</span><span class="re0">$languages</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.2 - I18n forms are validated'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'news'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'en'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">'toto'</span><span class="sy0">,</span>
      <span class="st_h">'body'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">isError</span><span class="br0">&#40;</span><span class="st_h">'en[body]'</span><span class="sy0">,</span> <span class="st_h">'required'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.3 - Empty forms are validated'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'news'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'en'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
      <span class="st_h">'body'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.4 - Translations are updated'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'news'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'fr'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">'toto tutu tata'</span><span class="sy0">,</span>
      <span class="st_h">'body'</span> <span class="sy0">=&gt;</span> <span class="st_h">'riri fifi loulou'</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'NewsTranslation'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$news</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'lang'</span> <span class="sy0">=&gt;</span> <span class="st_h">'fr'</span><span class="sy0">,</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">'toto tutu tata'</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.5 - No empty translation is created'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'NewsTranslation'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$news</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'lang'</span> <span class="sy0">=&gt;</span> <span class="st_h">'en'</span><span class="sy0">,</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.6 - New translations can be added'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'news'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'en'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">'toto tutu tata'</span><span class="sy0">,</span>
      <span class="st_h">'body'</span> <span class="sy0">=&gt;</span> <span class="st_h">'riri fifi loulou'</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'NewsTranslation'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$news</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'lang'</span> <span class="sy0">=&gt;</span> <span class="st_h">'en'</span><span class="sy0">,</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">'toto tutu tata'</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">info</span><span class="br0">&#40;</span><span class="st_h">'  2.7 - Existing translations can be deleted'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$editUrl</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">click</span><span class="br0">&#40;</span><span class="st_h">'Save'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'news'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
    <span class="st_h">'fr'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'title'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
      <span class="st_h">'body'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'_with_csrf'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span>
  <span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'form'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">hasErrors</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
&nbsp;
  <span class="me1">with</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
    <span class="me1">check</span><span class="br0">&#40;</span><span class="st_h">'NewsTranslation'</span><span class="sy0">,</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
      <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$news</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'lang'</span> <span class="sy0">=&gt;</span> <span class="st_h">'fr'</span><span class="sy0">,</span>
    <span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span>
  <a href="http://www.php.net/end"><span class="kw3">end</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="sy0">;</span></pre></div></div>

<p>Here we are. Hope you find this helpful. I thought some kind of requirement would be pretty common, however, I didn&#8217;t find any directly related howto&#8217;s. If you can think of any other way to achieve this, please, let me know.</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.miximum.fr%2Ftutos%2F449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine" height="61" width="51" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/tutos/449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
