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

<channel>
	<title>technique @PMSIpilot &#187; symfony</title>
	<atom:link href="http://www.pmsipilot.org/tag/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pmsipilot.org</link>
	<description>Blog du service technique de PMSIpilot</description>
	<lastBuildDate>Fri, 20 Jan 2012 09:07:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Les valeurs par défaut dans les sfForms</title>
		<link>http://www.pmsipilot.org/2011/05/12/les-valeurs-par-defaut-dans-les-sfforms/</link>
		<comments>http://www.pmsipilot.org/2011/05/12/les-valeurs-par-defaut-dans-les-sfforms/#comments</comments>
		<pubDate>Thu, 12 May 2011 08:09:23 +0000</pubDate>
		<dc:creator>Olivier Balais</dc:creator>
				<category><![CDATA[développement informatique]]></category>
		<category><![CDATA[default values]]></category>
		<category><![CDATA[sfForms]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[widgets]]></category>

		<guid isPermaLink="false">http://www.pmsipilot.org/?p=783</guid>
		<description><![CDATA[Aujourd&#8217;hui chez PMSIpilot, je suis tombé sur le problème suivant : après avoir passé une valeur par défaut à un des widgets de mon formulaire, je ne parvenais pas à la récupérer dans mon action ni dans mon template. L&#8217;appel à la méthode getDefault du sfForm me renvoyait systématiquement null,. Le code en question : [...]]]></description>
			<content:encoded><![CDATA[<p>Aujourd&#8217;hui chez PMSIpilot, je suis tombé sur le problème suivant : après avoir passé une valeur par défaut à un des widgets de mon formulaire, je ne parvenais pas à la récupérer dans mon action ni dans mon template.<br />
L&#8217;appel à la méthode getDefault du sfForm me renvoyait systématiquement <em>null,</em>.</p>
<p>Le code en question :</p>
<p><code>// Dans le code de mon formulaire :<br />
$this-&gt;setWidgets(array(<br />
  ...<br />
  'my_field' =&gt; new sfMyWidget(array('default' =&gt; 'my_value')),<br />
));<br />
</code><br />
<code>// Dans le code de mon action :<br />
if ($my_form-&gt;getDefault('my_field') == 'some_value')<br />
{<br />
  ...<br />
}</code></p>
<p>Dans ce cas, la méthode getDefault() appelée sur mon formulaire me renvoie null alors que j&#8217;ai explicitement donné une valeur par défaut à mon widget. Pourtant, en lisant la doc de symfony sur le sujet je retiens ceci :</p>
<blockquote><p>The setDefault(), getDefault(), setDefaults(), and getDefaults() methods manages the default values for the embedded widgets. <span style="text-decoration: underline">They are proxy methods </span>for the getDefault() and setDefault() widget methods.</p></blockquote>
<p>Les méthodes setDefault() et getDefault() au niveau de la classe sfForm sont censées êtres des raccourcis pour les méthodes setDefault() et getDefault() de la classe sfWidgetForm().</p>
<p>En fait il s&#8217;avère que ce n&#8217;est absolument pas le cas et que la méthode getDefault() du formulaire ne fait jamais appel à la méthode getDefault() du widget associé.</p>
<p>L&#8217;appel à <strong>$my_form-&gt;getDefault(&#8216;my_field&#8217;)</strong> n&#8217;est donc pas équivalent à <strong>$my_form['my_field']-&gt;getWidget()-&gt;getDefault()</strong>.</p>
<p>Par conséquent, il est important de bien comprendre quelle méthode appeler et dans quel cas.</p>
<p>A savoir, <strong>$my_form-&gt;getDefault(&#8216;my_field&#8217;)</strong> quand le setDefault a été utilisé<strong> au niveau du formulaire</strong>. Exemple :</p>
<p><code>// Valeurs passées dans mon formulaire :<br />
$this-&gt;setWidgets(array(<br />
  ...<br />
  'my_field' =&gt; new sfMyWidget(),<br />
));<br />
$this-&gt;setDefault('my_field', 'my_value');<br />
</code><br />
<code>// Ou alors valeurs passées dans mon action :<br />
$my_form = new myFormClass(array(<br />
  ...<br />
  'my_field' =&gt; 'my_value',<br />
));<br />
</code></p>
<p>Et, <strong>$my_form['my_field']-&gt;getWidget()-&gt;getDefault()</strong> quand le setDefault() a été utilisé <strong>au niveau du widget</strong>. Exemple :</p>
<p><code>// Dans le code de mon formulaire :<br />
$this-&gt;setWidgets(array(<br />
  ...<br />
  'my_field' =&gt; new sfMyWidget(array('default' =&gt; 'my_value')),<br />
));<br />
</code></p>
<p>Voilà, désormais vous êtes prévenus&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pmsipilot.org/2011/05/12/les-valeurs-par-defaut-dans-les-sfforms/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Code coverage des tests unitaires d&#8217;un projet symfony et intégration dans Hudson CI</title>
		<link>http://www.pmsipilot.org/2010/06/16/code-coverage-des-tests-unitaires-dun-projet-symfony-et-integration-dans-hudson-ci/</link>
		<comments>http://www.pmsipilot.org/2010/06/16/code-coverage-des-tests-unitaires-dun-projet-symfony-et-integration-dans-hudson-ci/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 07:25:19 +0000</pubDate>
		<dc:creator>adrien.gallou</dc:creator>
				<category><![CDATA[développement informatique]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.pmsipilot.org/?p=405</guid>
		<description><![CDATA[Après avoir écrit quelques tests unitaires, on peut se demander si les tests écrits couvrent une partie assez importante du code de la classe testée, quelles peuvent être les classes restantes à tester ou tout simplement avoir une idée de l&#8217;étendue du projet couverte par des tests unitaires. Pour cela nous utiliseront le plugin Hudson [...]]]></description>
			<content:encoded><![CDATA[<p>Après avoir écrit quelques tests unitaires, on peut se demander si les tests écrits couvrent<br />
 une partie assez importante du code de la classe testée, quelles peuvent être les classes restantes à tester ou tout simplement avoir une idée de l&#8217;étendue du projet couverte par des tests unitaires.</p>
<p>  Pour cela nous utiliseront le plugin Hudson <a href="http://wiki.hudson-ci.org/display/HUDSON/Emma+Plugin">Emma</a> pour l&#8217;affichage dans Hudson, ainsi que le plugin symfony <a href="http://www.symfony-project.org/plugins/agEmmaCoverageReportPlugin">agEmmaCoverageReport</a> pour générer le fichier xml au format emma.<br />
  Le format &laquo;&nbsp;emma&nbsp;&raquo; est à la basée utilisé en java, plus d&#8217;infos sur le <a href="http://emma.sourceforge.net/">site</a> du projet.</p>
<p><strong>Utilisation de la tache de génération du rapport xml</strong></p>
<p><em>L&#8217;extension xdebug doit être installée (mais pas forcément activée).</em></p>
<p>Les fichiers testés sont trouvés en utilisant l&#8217;autoload, les fichiers de tests doivent être nommés de la façon suivante : <code>nomDeLaClasseTesteeTest.php</code>, par exemple le classe &laquo;&nbsp;qualifactCellFormatterEuro&nbsp;&raquo; aura pour fichier de test &laquo;&nbsp;qualifactCellFormatterEuroTest.php&nbsp;&raquo;.</p>
<p>  Voyons tout d&#8217;abord comment fonctionne la génération du fichier xml de rapport :</p>
<p>Si xdebug est activé par défaut : </p>
<p><code>./symfony ecr:report --xml=cheminOuSauverLeXml.xml</code></p>
<p>Mais sur le serveur d&#8217;intégration cela n&#8217;est probablement pas le cas, et il serait<br />
gênant d&#8217;avoir à l&#8217;activer pour les autres tests alors que qu&#8217;il est seulement utilisé pour le coverage.<br />
Pour cela on peut indiquer à la tache le chemin ou se situe l&#8217;extension xdebug (par exemple sur une Mandriva il se situe ici : &laquo;&nbsp;/usr/lib/php/extensions/xdebug.so&nbsp;&raquo;). La tâche sera alors appelée de cette façon.</p>
<p><code>./symfony ecr:report --xml=cheminOuSauverLeXml.xml --xdebug-extension-path=/usr/lib/php/extensions/xdebug.so</code></p>
<p><strong>Intégration dans Hudson CI</strong></p>
<p> Création et configuration du job </p>
<ul>
<li>Dans le menu de gauche : &laquo;&nbsp;Nouvelle Tache&nbsp;&raquo;</li>
<li>Cliquez sur &laquo;&nbsp;Construire un projet free-style&nbsp;&raquo;</li>
<li>Donnez un nom au job</li>
<li> Entrez alors l&#8217;url du dépôt</li>
<li>Après checkout nous voulons lancer les tests unitaires ainsi que la tache créant</li>
<p> le rapport de coverage, nous allons donc ajouter une étape au build. Celle ci sera de<br />
 type &laquo;&nbsp;Executer un script shell&nbsp;&raquo; </p>
<li>Dans la liste des commandes nous allons donc lancer les tests et le coverage de cette façon :</li>
<p><code>$WORKSPACE/symfony test:unit --xml=log/unit.xml<br />
$WORKSPACE/symfony ecr:report --xml=log/coverage.xml</code></p>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/06/executer_script.png"><img src="http://www.pmsipilot.org/wp-content/uploads/2010/06/executer_script-300x45.png" alt="executer_script" width="300" height="45" class="aligncenter size-medium wp-image-425" /></a></p>
<li>Pour les résultats des tests unitaires, cochons la case &laquo;&nbsp;Publier le rapport des résultats de tests JUnit&nbsp;&raquo; puis dans &laquo;&nbsp;XML des rapports de test&nbsp;&raquo; nous indiquons ou chercher le fichier XML en saisissant : &laquo;&nbsp;log/unit.xml&nbsp;&raquo;</li>
<li>Pour le code coverage, cochons la case &laquo;&nbsp;Record Emma coverage report&nbsp;&raquo; puis dans &laquo;&nbsp;Folders or files containing Emma XML reports&nbsp;&raquo; nous indiquons où chercher le fichier XML en saisissant : &laquo;&nbsp;log/coverage.xml&nbsp;&raquo;</li>
<li>Il faudra ensuite exécuter le job</li>
</ul>
<p> <strong>Affichage du rapport de code coverage</strong></p>
<p>Après lancement du job les résultats du code coverage apparaissent dans la section &laquo;&nbsp;Coverage Trend&nbsp;&raquo;. </p>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/06/graph.png"><img src="http://www.pmsipilot.org/wp-content/uploads/2010/06/graph-300x224.png" alt="graph" width="300" height="224" class="aligncenter size-medium wp-image-431" /></a></p>
<p>   Pour un détail du coverage il faut cliquer sur le graphique.</p>
<p>La couverture du code par les tests unitaire est alors présentée par package ainsi que par classe, méthode, bloc et ligne.</p>
<p>Les blocs sont tous à 0 car c&#8217;est une notion seulement utilisée en java. Une méthode ou une classe est couverte si toutes les lignes qui la contiennent sont couvertes. Ainsi certaines classes, ne contenant aucune ligne de code, ayant juste leur déclaration, seront indiquées comme couvertes à 100%.</p>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/06/tableau_floute.png"><img src="http://www.pmsipilot.org/wp-content/uploads/2010/06/tableau_floute-300x161.png" alt="tableau_floute" width="300" height="161" class="aligncenter size-medium wp-image-440" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pmsipilot.org/2010/06/16/code-coverage-des-tests-unitaires-dun-projet-symfony-et-integration-dans-hudson-ci/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Symfony chez PMSIpilot</title>
		<link>http://www.pmsipilot.org/2010/04/23/symfony-chez-pmsipilot/</link>
		<comments>http://www.pmsipilot.org/2010/04/23/symfony-chez-pmsipilot/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 14:35:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[développement informatique]]></category>
		<category><![CDATA[PMSIpilot (meet the team)]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.pmsipilot.org/?p=282</guid>
		<description><![CDATA[PMSIpilot conçoit et réalise une suite informatique dédiée à l&#8217;amélioration de la gouvernance des hopitaux publics. Le périmètre fonctionnel peut s&#8217;apparenter à un outil décisionnel ou de Business Intelligence concernant l&#8217;activité, d&#8217;un point de vue financier et médical, de l&#8217;hôpital. Il y a deux ans, le projet a connu un virage technologique important. D&#8217;une technologie [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="background-color: #fff; border-color: #fff;" title="logo symfony" src="http://www.symfony-project.org/downloads/logos/symfony.gif" alt="" width="314" height="85" /><a href="http://www.pmsipilot.com">PMSIpilot</a> conçoit et réalise une suite informatique dédiée à l&#8217;amélioration de la gouvernance des hopitaux publics. Le périmètre fonctionnel peut s&#8217;apparenter à un outil décisionnel ou de <em>Business Intelligence</em> concernant l&#8217;activité, d&#8217;un point de vue financier et médical, de l&#8217;hôpital.</p>
<p>Il y a deux ans, le projet a connu un virage technologique important. D&#8217;une technologie obsolète et d&#8217;un conception un peu hasardeuse (PHP4, framesets, &#8230;), un projet de refonte vers symfony 1.2 a été lancé. Cette refonte a durée un peu plus de 20 mois / homme et a abouti à un seul projet symfony contenant plusieurs applications. PMSIpilot a, dès le début, pris le parti d&#8217;utiliser les conventions de symfony et le paradigme MVC.</p>
<h2>En chiffres, aujourd&#8217;hui</h2>
<ul>
<li>12 développeurs (en constante augmentation !),</li>
<li>410 déploiements,</li>
<li>environ 50 000 utilisateurs répartis sur toutes ces instances,</li>
<li>environ 220 000 lignes de code PHP écrites et maintenues,</li>
<li>la prochaine release importante intégrera symfony 1.4.</li>
</ul>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/04/lines_of_code-1.png"><img class="aligncenter size-medium wp-image-310" title="lines of code" src="http://www.pmsipilot.org/wp-content/uploads/2010/04/lines_of_code-1-300x218.png" alt="lines of code" width="300" height="218" /></a></p>
<h2>Comment symfony nous aide</h2>
<h3>La documentation et la communauté</h3>
<p>La documentation de symfony nous permet d&#8217;intégrer rapidement une nouvelle recrue. Le fait de trouver de nombreuses contributions au framework (sur <a href="http://www.symfony-project.org/">symfony-project.org</a> ou bien ailleurs) est très facilitant également. Nous utilisons de nombreux plugins comme :</p>
<ul>
<li>sfPropelPlugin</li>
<li>dwJpGraphPlugin</li>
<li>sfDB4toPropelPlugin</li>
<li>sfPropelSqlDiffPlugin</li>
<li>sfJqueryReloadedPlugin</li>
<li>sfValidatorHtmlPlugin</li>
<li>sfJobQueuePlugin</li>
<li>sfFormExtraPlugin</li>
<li>&#8230;</li>
</ul>
<p>Parfois tels quels, parfois un peu modifiés pour nos besoins.</p>
<h3>Le développement</h3>
<ul>
<li>le framework nous donne une bonne structure de base pour l&#8217;organisation du code source ainsi que des normes de codage, sur une équipe aussi importante cela permet de gagner du temps,</li>
<li>mis à part i18n et l&#8217;<em>admin générator</em>, on utilise la quasi totalité de la <em>stack</em> de symfony : MVC, le cache, les filtres, les évènements, le système de gestion des utilisateur, l&#8217;ORM, les tasks, &#8230;</li>
<li>symfony est suffisament flexible pour que nous puissions facilement l&#8217;adapter à nos besoins parfois bien spécifiques ; aujourd&#8217;hui nous avons étendu : sessionStorage, viewCacheManager, ApplicationConfiguration et ProjectConfiguration, sfAction, sfComponent, sfView, frontWebController, plein de choses autour de propel &#8230;</li>
<li>nous ajoutons des fonctionnalités tous les jours, et une grande réactivité nous est demandé pour suivre l&#8217;évolution de la réglementation ; le framework de test nous permet de garantir aucune régression et de livrer des correctifs très rapidement si nécessaire (voir plus bas),</li>
<li>le système de task, de gestions des fixtures, d&#8217;environnement de développement permet de proposer des méthodes faciles d&#8217;accès au développeur permettant d&#8217;instancier un environnement de dev complet et identique à ses collègues.</li>
</ul>
<h3>L&#8217;intégration continue</h3>
<p>Dès la refonte du projet, sécuriser ces mises à jours a été une priorité. C&#8217;est pourquoi nous avons investi dans le développements d&#8217;un grand nombre de tests fonctionnels et leur suivi au sein d&#8217;une instance <a title="Le projet Hudson" href="https://hudson.dev.java.net/">Hudson</a>.<br />
<a href="http://www.pmsipilot.org/wp-content/uploads/2010/04/Capture-6.7-Hudson-Google-Chrome.png"><img class="aligncenter size-medium wp-image-292" title="Hudson" src="http://www.pmsipilot.org/wp-content/uploads/2010/04/Capture-6.7-Hudson-Google-Chrome-300x242.png" alt="Hudson" width="300" height="242" /></a><br />
Les tests fonctionnels chez PMSIpilot vérifient des cas d&#8217;utilisation standards mais sont surtout utilisés pour valider la totalité des données chiffrées présentées. A ce titre les quelques <strong>250 000 tests fonctionnels</strong> sont majoritairement générés (on ne teste pas vraiment &laquo;&nbsp;les tests&nbsp;&raquo; mais &laquo;&nbsp;les étalons des tests&nbsp;&raquo;).</p>
<p>La création de nouvelles classes a entrainé l&#8217;écriture d&#8217;<strong>une centaine de tests unitaires </strong>(avec des efforts pour optimiser la couverture du code).</p>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/04/emma.png"><img class="aligncenter size-medium wp-image-304" title="emma code coverage" src="http://www.pmsipilot.org/wp-content/uploads/2010/04/emma-300x243.png" alt="emma code coverage" width="300" height="243" /></a></p>
<p>Enfin, nous avons commencé l&#8217;écriture de <strong>tests d&#8217;interface</strong> avec Selenium (une dizaine aujourd&#8217;hui) afin de gérer plus facilement les différents navigateurs (parfois un peu datés) de nos clients. (oui, ça n&#8217;a rien à voir avec symfony &#8230;)</p>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/04/image.png"><img class="aligncenter size-medium wp-image-306" title="navigateurs" src="http://www.pmsipilot.org/wp-content/uploads/2010/04/image-300x159.png" alt="navigateurs" width="300" height="159" /></a></p>
<p><a href="http://www.pmsipilot.org/wp-content/uploads/2010/04/selenium.png"><img class="aligncenter size-medium wp-image-312" title="tests selenium" src="http://www.pmsipilot.org/wp-content/uploads/2010/04/selenium-300x187.png" alt="tests selenium" width="300" height="187" /></a></p>
<p>Pour boucler la boucle on a, en projet, l&#8217;intégration automatique de tests de montée en charge. (un outil à suggérer ?)</p>
<h2>Comment nous tentons d&#8217;aider symfony</h2>
<p>Dans la mesure du possible, nous tentons de faire <a title="nos contributions à Symfony" href="http://links.pmsipilot.com/sfcontrib">bénéficier la communauté symfony de nos travaux</a>, en remontant des bugs et en proposant des plugins . Nous essayons également de <a title="Les réunions techniques" href="http://www.pmsipilot.org/?s=r%C3%A9union+technique">partager les slides des réunions</a> techniques organisées au sein de l&#8217;équipe afin de diffuser les compétences au sein des équipes.</p>
<p>Chez PMSIpilot, on aime symfony. Si c&#8217;est votre cas aussi, n&#8217;hésitez pas à<a href="http://www.glagla.org/weblog/2009/01/07/pmsipilot-recrute-sur-lyon-des-developpeurs-symfony/"> proposer votre candidature</a> au service technique.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pmsipilot.org/2010/04/23/symfony-chez-pmsipilot/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Contributions à Symfony</title>
		<link>http://www.pmsipilot.org/2010/03/25/contributions-a-symfony/</link>
		<comments>http://www.pmsipilot.org/2010/03/25/contributions-a-symfony/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 13:30:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[développement informatique]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sf_contrib]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://localhost/pmsipilotorg/?p=5</guid>
		<description><![CDATA[So far, voici la liste de nos très modestes contribution à Symfony, le framework PHP utilisé chez nous : tickets : #1776 (fixed) [PATCH] checkbox arrays not checked with fillin enabled #2916 (wontfix) Bug in Spyc : losing data with successive load/dump #3792 (fixed) i18n XLIFF do not handle entities correctly #4306 (wontfix) sfDebugConnection does [...]]]></description>
			<content:encoded><![CDATA[<p>So far, voici la liste de nos très modestes contribution à <a href="http://www.symfony-project.org/">Symfony</a>, le framework PHP utilisé chez nous :</p>
<p>tickets :</p>
<ul>
<li><a href="http://trac.symfony-project.org/ticket/1776">#1776</a> (fixed) [PATCH] checkbox arrays not checked with fillin enabled</li>
<li><a href="http://trac.symfony-project.org/ticket/2916">#2916</a> (wontfix) Bug in Spyc : losing data with successive load/dump</li>
<li><a href="http://trac.symfony-project.org/ticket/3792">#3792</a> (fixed) i18n XLIFF do not handle entities correctly</li>
<li><a href=" http://trac.symfony-project.org/ticket/4306">#4306</a> (wontfix) sfDebugConnection does not handle correctly logging of nested transactions</li>
<li><a href="http://trac.symfony-project.org/ticket/4620">#4620</a> (fixed) [PATCH] &#8211; PHP5NestedSetBuilder generate a require to lib/model/om/Basesometing</li>
<li><a href="http://trac.symfony-project.org/ticket/5374">#5374</a> (fixed) Changeset [14122] breaks config parsing</li>
<li><a href="http://trac.symfony-project.org/ticket/5402">#5402</a> (fixed) sf doc refer to the getDispatcher() method but it doesnt exist</li>
<li><a href="http://trac.symfony-project.org/ticket/5964">#5964</a> (fixed) Notice sur sfTestBrowser</li>
<li><a href="http://trac.symfony-project.org/ticket/7446">#7446</a> (fixed) sfOutputEscaper::unescape($vars) appelé systématiquement dans _call_component</li>
<li><a href="http://trac.symfony-project.org/ticket/6639">#6639</a> (fixed) Option passed to a widget schema do not get passed through to an sfWidgetFormChoice&#8217;s renderer</li>
<li><a href="http://trac.symfony-project.org/ticket/8365">#8365</a> (opened) sfFinder not_name does not works if results intersects due to #6589</li>
<li><a href="http://trac.symfony-project.org/ticket/8384">#8384</a> (opened) sfPropelPluginConfiguration::filterAutoloadConfig should exclude vendor dir just like in the plugin autoload file</li>
<li><a href="http://trac.symfony-project.org/ticket/8402">#8402</a> (opened) sfPropelBaseTask should add propel include path by using sf_propel_runtime_path</li>
<li><a href="http://trac.symfony-project.org/ticket/8457">#8457</a> (fixed) sort the parameters in order to compute the cache key the same way when parameters are submited in different order</li>
</ul>
<p>plugins :</p>
<ul>
<li><a href="http://www.symfony-project.org/plugins/omCredentialsMapPlugin">omCredentialsMapPlugin</a> : This plugin allows you to check  all the credentials in your project and detect action not or badly securised</li>
<li><a href="http://www.symfony-project.org/plugins/omCrossAppUrlPlugin">omCrossAppUrlPlugin</a> : Simple helper to get cross app urls</li>
<li><a href="http://www.symfony-project.org/plugins/elXHProfPlugin">elXHProfPlugin</a> : Integration of XHProf profiler (simple API to profile + web debug toolbar integration)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.pmsipilot.org/2010/03/25/contributions-a-symfony/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Profiling PHP / symfony : merci XHProf</title>
		<link>http://www.pmsipilot.org/2010/02/08/profiling-php-symfony-merci-xhprof/</link>
		<comments>http://www.pmsipilot.org/2010/02/08/profiling-php-symfony-merci-xhprof/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 17:08:02 +0000</pubDate>
		<dc:creator>Eric Lemoine</dc:creator>
				<category><![CDATA[développement informatique]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[xhprof]]></category>

		<guid isPermaLink="false">http://www.pmsipilot.org/?p=205</guid>
		<description><![CDATA[Introduction Il arrive souvent lors d&#8217;un développement informatique que l&#8217;on soit confronté à un problème de performances. On essaie souvent d&#8217;optimiser des bouts de code que l&#8217;on croit être la cause des ralentissements mais sur des projets assez complexes il arrive qu&#8217;on ne regarde pas forcément au bon endroit. Les étapes à suivre pour résoudre [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Il arrive souvent lors d&#8217;un développement informatique que l&#8217;on soit confronté à un problème de performances.</p>
<p>On essaie souvent d&#8217;optimiser des bouts de code que l&#8217;on croit être la cause des ralentissements mais sur des projets assez complexes il arrive qu&#8217;on ne regarde pas forcément au bon endroit.</p>
<p>Les étapes à suivre pour résoudre des problèmes de performances sont donc les suivantes :</p>
<ol>
<li>Mesurer : il est indispensable de connaître les performances actuelles de l&#8217;application/bout de code qui sous-performe.</li>
<li>Optimiser (ou en tout cas essayer) : cela est lié à votre code, je vous laisse faire cette partie :)</li>
<li> Comparer : est-ce que l&#8217;optimisation effectuée est vraiment efficace ? Tant qu&#8217;on n&#8217;est pas satisfait on revient à l&#8217;étape 2.</li>
</ol>
<p>Je vais aborder dans cet article des solutions disponibles dans l&#8217;univers PHP pour permettre de travailler sur les étapes 1 et 3.</p>
<p><span id="more-205"></span></p>
<h2>Mesurer les performances : le profiling.</h2>
<h3>Xdebug</h3>
<p>Beaucoup de développeurs PHP connaissent <a href="http://xdebug.org/" target="_blank">xdebug</a> qui propose des fonctionnalités de <a href="http://xdebug.org/docs/profiler" target="_blank">profiling</a>.<br />
Sous la forme d&#8217;extension PHP il permet d&#8217;avoir un fichier de profil de performances à partir du moment où l&#8217;on a activé le profiling.<br />
On analyse ensuite ce fichier de résultat à l&#8217;aide d&#8217;outils comme KCacheGrind, WinCacheGrind, MacCallGrind&#8230; suivant notre plateforme.<br />
Cela fonctionne bien pour du code PHP pas trop gros mais dès que le code se complexifie, les fichiers de profil peuvent devenir énorme (nous avons déjà ici vu des fichiers de plusieurs Go !).<br />
L&#8217;activation du profiling a aussi pour effet de bord pas très pratique un gros ralentissement du code profilé.</p>
<p>En bref, on a longtemps utilisé xdebug par manque d&#8217;alternatives.</p>
<h3>XHProf</h3>
<p>Développé par Facebook et assez récent dans le monde PHP (il a été diffusé en mars 2009), <a href="http://mirror.facebook.net/facebook/xhprof/" target="_blank">XHProf</a> est un profiler qui a énormément d&#8217;avantages sur xdebug.<br />
Les fichiers de profil sont ridiculement petits quand on vient de xdebug (400ko vs 1.2Go pour un même code profilé sur notre projet).<br />
L&#8217;activation de xhprof n&#8217;a quasiment aucun impact sur les performances du code analysé.<br />
Facebook fournit des scripts PHP pour analyser directement en web les résultats du profiling.<br />
Un dernier avantage, et non des moindres, est que l&#8217;on n&#8217;est pas obligé de profiler tout notre process PHP mais uniquement une portion de code. Cela n&#8217;est pas possible avec xdebug qui profile le process entier.</p>
<h2>Comparer les résultats</h2>
<h3>Xdebug</h3>
<p>Il est très difficile de comparer précisément deux profils de performances issus de xdebug. Si en plus les fichiers sont énormes cela rend la tâche impossible.</p>
<h3>XHProf</h3>
<p>La comparaison de profils est native dans XHProf ce qui permet très rapidement de voir si nos optimisations sont concluantes.</p>
<h2>Intégration avec symfony</h2>
<p>Après avoir commencé à utiliser XHProf, il nous a semblé judicieux de voir comment l&#8217;intégrer facilement dans un projet symfony. C&#8217;est ainsi que j&#8217;ai développé le plugin <a href="http://www.symfony-project.org/plugins/elXHProfPlugin" target="_blank">elXHProfPlugin</a> qui nous permet d&#8217;avoir directement au niveau de la web debug toolbar de symfony la liste des profils de performances ainsi que la possibilité de comparer deux fichiers de profil (et ainsi profiter de la fonction native de comparaison de XHProf).<br />
Voici 2 captures d&#8217;écrans qui illustrent l&#8217;intégration dans la web debug toolbar et la comparaison de profils.</p>
<div id="attachment_219" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.pmsipilot.org/wp-content/uploads/2010/02/xhprof_debug_toolbar.png" target="_blank"><img class="size-medium wp-image-219" title="Intégration de XHProf à la web debug toolbar de symfony" src="http://www.pmsipilot.org/wp-content/uploads/2010/02/xhprof_debug_toolbar-300x131.png" alt="Intégration de XHProf à la web debug toolbar de symfony" width="300" height="131" /></a><p class="wp-caption-text">Intégration de XHProf à la web debug toolbar de symfony</p></div>
<div id="attachment_224" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.pmsipilot.org/wp-content/uploads/2010/02/xhprof_comparaison.png" target="_blank"><img class="size-medium wp-image-224" title="Comparaison de runs avec XHProf" src="http://www.pmsipilot.org/wp-content/uploads/2010/02/xhprof_comparaison-300x154.png" alt="Comparaison de runs avec XHProf" width="300" height="154" /></a><p class="wp-caption-text">Comparaison de runs avec XHProf</p></div>
<h2>Conclusion</h2>
<p>Après avoir utilisé Xdebug pendant des années, nous utilisons XHProf avec beaucoup de facilité. Sa légéreté et son intégration à la debug toolbar de symfony nous permet de faire facilement des optimisations là où nous serions allé à reculons en utilisant Xdebug.</p>
<p>Et surtout n&#8217;oubliez pas cette phrase de Donald Knuth lors de vos développements :<br />
&laquo;&nbsp;We should forget about small efficiencies, say about 97% of the time: <strong>premature optimization is the root of all evil</strong>&laquo;&nbsp;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pmsipilot.org/2010/02/08/profiling-php-symfony-merci-xhprof/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

