mageekblog - Mot-clé - closureLe blog personnel de Frédéric Hardy. Au menu, PHP, agilité, FreeBSD, cuisine et photographies.2021-12-02T08:20:54+01:00Frédéric Hardyurn:md5:26874ca5b8cd4cac8d08b0e68e64f63aDotclearMort de PHP6 + 1[34]0 joursurn:md5:904afe665c4da69ddf2688af038b5df62010-08-04T09:00:00+02:002010-08-04T11:05:59+02:00mageekguyPHP Xclosurefermetureinternals@PHP 5.2PHP 5.3PHP XPHP6trunk<p>Pour cause de <a href="http://blog.mageekbox.net/?post/2010/07/15/Vacances-%21">vacances</a>, je n'ai pas pu assuré le suivi du développement de la prochaine version de <a href="http://www.php.net">PHP</a> sur les vingts derniers jours.</p>
<p>Je rattrape donc maintenant le temps perdu, et heureusement pour moi, et malheureusement pour le langage, je n'ai pas loupé énormément de choses.</p>
<p>Ce qui suit concerne donc ce qu'il s'est passé jusqu'au 30 juillet 2010 au niveau du <a href="http://svn.php.net/viewvc/php/php-src/trunk/">trunk</a> de <a href="http://www.php.net/">PHP</a>.</p> <p>L'actualité du développement a en effet été très calme sur cette période, puisque hormis la correction des bugs <a href="http://bugs.php.net?id=52037">#52037</a>,
<a href="http://bugs.php.net?id=51943">#51943</a>,
<a href="http://bugs.php.net?id=51583">#51583</a>,
<a href="http://bugs.php.net?id=52317">#52317</a>,
<a href="http://bugs.php.net?id=52380">#52380</a>,
<a href="http://bugs.php.net?id=52436">#52436</a>,
<a href="http://bugs.php.net?id=52476">#52476</a> et
<a href="http://bugs.php.net?id=52487">#52487</a>, il n'y a vraiment pas grand chose à se mettre sous la dent.</p>
<p>Il y a bien eu quelques optimisations, mais qui sont anecdotiques, et pour la plupart, elles ne concernent que les développeurs du langage et non ses utilisateurs.</p>
<p>Le développement de la prochaine version majeure de PHP s'est donc nettement ralentie au cours du dernier mois.</p>
<p>Cependant, je ne pense pas qu'il faille s'en inquiéter.</p>
<p>La période estivale est traditionnellement calme, et de plus, les version <a href="http://www.php.net/archive/2010.php#id2010-07-22-2">5.3.3</a> et <a href="http://www.php.net/archive/2010.php#id2010-07-22-1">5.2.14</a> du langage ont certainement phagocyté une bonne partie des ressources disponibles parmi la communauté des contributeurs.</p>
<p>Le développement devrait donc reprendre à un rythme plus soutenu dans les jours qui viennent, d'autant que la liste de diffusion des contributeurs, <a href="http://news.php.net/group.php?group=php.internals">internals@</a>, recommence à vivre.</p>
<p>Il y a eu en effet quelques gros débats, <a href="http://news.php.net/php.internals/49109">stériles</a> et <a href="http://news.php.net/php.internals/49138">stupides</a> pour la plupart, mais ils ont le mérite d'avoir eu lieu.</p>
<p>De plus, le débat autour du <a href="http://news.php.net/php.internals/49158">contrôle de type</a> redémarre, avec cette fois-ci pour point de départ la possibilité de définir le type de la valeur de retour des fonctions et des méthodes.</p>
<p>Enfin, il a été confirmé sur la liste de diffusion que le support de $this dans les <a href="http://blog.mageekbox.net/?post/2010/07/08/Les-fermetures%2C-c-est-trop...-ferm%C3%A9-%21">fermetures</a>, <abbr title="Also Known As">aka</abbr> closures, serait effectif dans la prochaine version majeure suivant la <a href="http://wiki.php.net/rfc/closures/object-extension"><abbr title="Request For Comment">RFC</abbr> correspondante</a>.</p>
<p>Nous pourrons donc écrire avec la prochaine version du langage le code suivant :</p>
<blockquote><pre><code>// $obj is not $this<br />$obj->method1 = function () { ... };<br />$obj->method1 (); // WARNING: Closure called as method but bound object differs from containing object.<br />$obj->method2 = Closure::bind ($obj, function () { ... });<br />$obj->method2 (); // No warning, objects match<br /> <br />// inside a class<br />$this->method = function () { ... };<br />$this->method (); // No warning, objects match</code></pre></blockquote>
<p>Cette récapitulation <q>king size</q> au niveau de l'intervalle de temps qu'elle résume et <q>small size</q> par son contenu est maintenant terminée.</p>
<p>Vous pouvez reprendre une activité normale jusqu'à la prochaine, qui je l'espère sera beaucoup plus riche et intéressante.</p>http://blog.mageekbox.net/?post/2010/08/04/Mort-de-PHP6-%C2%B0-1%5B34%5D0-jours#comment-formhttp://blog.mageekbox.net/?feed/atom/comments/164Les fermetures, c'est trop... fermé !urn:md5:8b6ce66a4cb7d9e1b9b4761eb369912d2010-07-08T11:30:00+02:002010-07-08T11:56:25+02:00mageekguyPHPclosureexceptionfermetureserialisation<p>J'utilise actuellement intensivement les <a href="http://blog.pascal-martin.fr/post/php-5.3-1-closures-et-lambdas">fermetures</a>, plus connues sous leur dénomination anglaise <q>closure</q>, dans mes développements <a href="http://www.php.net">PHP</a>.</p>
<p>Elles sont en effet extrêmement bien adapté à mon besoin, mais je viens de découvrir qu'elles ont un inconvénient de taille.</p> <p>Dans le cadre de mon projet, j'ai le code suivant :</p>
<blockquote><pre><code>class foo<br />{<br /> protected $methods = array();<br /><br /> public function __set($method, \closure $closure)<br /> {<br /> if (array_key_exists($method, $this->methods) === false)<br /> {<br /> throw new \logicException('Method \'' . $method . '\' does not exist');<br /> }<br /> } <br />}<br /></code></pre></blockquote>
<p>Ainsi, si je veux affecter une <a href="http://blog.pascal-martin.fr/post/php-5.3-1-closures-et-lambdas">fermeture</a> à une méthode qui n'est pas connue de l'objet, une exception sera lancée.</p>
<p>Ce code est utilisé par un processus <a href="http://www.php.net">PHP</a>, créé à l'aide de <code><a href="http://fr.php.net/proc_open">proc_open()</a></code>.</p>
<p>Ce processus doit communiquer le résultat de son exécution, représenter par un <q>score</q>, à son processus père.</p>
<p>Pour cela, il écrit sur la sortie standard le résultat de la sérialisation de son <q>score</q>, et la sortie standard est ensuite lue et interprétée par le processus père.</p>
<p>Or, ce <q>score</q> stocke les éventuelles exceptions générées lors de l’exécution du processus.</p>
<p>Donc, si le code du processus fait appel à la méthode <code>foo::__set()</code> avec un nom de méthode invalide qui génère une exception, cette dernière est stockée dans le <q>score</q>.</p>
<p>Et lorsque <a href="http://www.php.net">PHP</a> crée une exception, il stocke dans cette dernière la pile d’exécution qui a conduit à sa création.</p>
<p>Cette pile contient, entre autre chose, les arguments qui ont été passé aux différentes méthodes appelées.</p>
<p>Le <q>score</q> contient donc dans mon cas une exception qui contient une <a href="http://blog.pascal-martin.fr/post/php-5.3-1-closures-et-lambdas">fermeture</a>, puisque c'est l'un des arguments de <code>foo::__set()</code>.</p>
<p>Or, <a href="http://www.php.net">PHP</a> refuse catégoriquement de sérialiser les <a href="http://blog.pascal-martin.fr/post/php-5.3-1-closures-et-lambdas">fermetures</a>.</p>
<p>Si vous essayez, vous obtiendrez le message suivant :</p>
<blockquote><pre><code>PHP Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /usr/home/fch/tmp/closure.php:5<br /></code></pre></blockquote>
<p>Du coup, dans ce cas, ma communication inter-processus ne peut plus fonctionner, vu que :</p>
<ol><li>la sérialisation du <q>score</q> entraîne la sérialisation de l'exception</li>
<li>la sérialisation de l'exception entraîne celle de la <a href="http://blog.pascal-martin.fr/post/php-5.3-1-closures-et-lambdas">fermeture</a>, via la pile d'exécution contenue dans l'exception</li>
<li>Une exception est généré <a href="http://www.php.net/">PHP</a> et écrite sur la sortie standard, que le processus père n'est pas capable d'interpréter.</li>
</ol>
<p>La solution à ce problème ?</p>
<p>J'ai bien pensé à utiliser l'interface <code>serializable</code> au niveau de mon <q>score</q>, mais la pile d'exécution contient un objet de la classe <code>\closure</code>,
qui ne peut être redéfinie.</p>
<p>De plus, il n'est pas non plus possible de modifier la pile
d'exécution d'une exception puisque cette dernière est en lecture seule
et que la propriété correspondante est privée.</p>
<p>La seule solution consiste donc à ne pas utiliser d'exception si une fermeture est susceptible de se retrouver dans sa pile d'exécution et qu'elle est susceptible d'être sérialisée.</p>
<p>Autant dire que cette solution est inapplicable dans les faits, puisqu'il faudrait au minimum être voyant extralucide pour pouvoir dire comment sera utilisé dans le futur un code conçu maintenant.</p>
<p>Il est également possible d'utiliser <a href="http://fr.php.net/trigger_error"><code>trigger_error()</code></a> pour générer une erreur et non une exception, mais suivant le contexte, ce n'est pas forcément <a href="http://blog.mageekbox.net/?post/2010/03/11/Erreur-ou-exception">le comportement voulu</a>.</p>
<p>La meilleure solution est donc que le fonctionnement de <a href="http://www.php.net">PHP</a> soit modifié afin qu'il n'empêche plus la sérialisation d'objet contenant des <a href="http://blog.pascal-martin.fr/post/php-5.3-1-closures-et-lambdas">fermetures</a>.</p>http://blog.mageekbox.net/?post/2010/07/08/Les-fermetures%2C-c-est-trop...-ferm%C3%A9-%21#comment-formhttp://blog.mageekbox.net/?feed/atom/comments/155Mort de PHP6 + 40 joursurn:md5:f981589548d43ca29267be93a3a485262010-04-25T00:00:00+02:002010-06-09T18:24:31+02:00mageekguyPHP Xclosureinternals@PHP Xregister_globalssvntraitstrunk<p>Les dix derniers jours ont été calmes en terme de discussions et de décisions au sujet de la prochaine version de <a href="http://www.php.net">PHP</a>.</p>
<p>Cependant, cela ne veut aucunement dire que les choses n'avancent pas.</p>
<p>Il semble en effet que les développeurs aient décidé d'intégrer les décisions prises au cours du mois qui vient de s'écouler.</p>
<p>Pour preuve, l'activité sur <a href="http://svn.php.net/viewvc/php/php-src/trunk/">le trunk svn</a> a beaucoup augmenté ces derniers jours, avec parfois plus de vingt modifications par jour.</p> <p>Ainsi, plusieurs nouveautés ont été intégrées :</p>
<p>
C'est le cas notamment des <a href="http://fr.wikipedia.org/wiki/Trait_%28type_abstrait%29"><code>traits</code></a>, tel qu'ils sont définis par la <code><a href="http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior"><abbr title="Request for Comment">RFC</abbr></a></code> correspondante et qui introduisent deux nouveaux mots-clefs dans le langage, <code>trait</code> et <code>insteadof</code>.</p>
<p>Si, par hasard et malchance, vous utilisez ces deux mots dans votre code, je vous invite à modifier cela dans les meilleurs délais afin de ne pas être <del>emmerdé</del> géné lors d'une migration vers une version de <a href="http://www.php.net">PHP</a> supportant cette fonctionnalité.</p>
<p>Il est à noter que ce chantier n'est pas terminé et que pas mal de questions sont encore posées, notament au sujet de la gestion des <a href="http://fr.wikipedia.org/wiki/Trait_%28type_abstrait%29"><code>traits</code></a> par <a href="http://fr2.php.net/reflection">l'<abbr title="Application Programming Interface">API</abbr> de reflexion</a>.</p>
<p>Dans un autre registre, après bien des <a href="http://news.php.net/php.internals/47963">discusions</a>, le fichier de configuration de la <a href="http://wiki.php.net/rfc/fpm"><code>SAPI FPM</code></a> utilise dorénavant <a href="http://wiki.php.net/rfc/fpm/ini_syntax">la syntaxe des fichiers <code>ini</code></a> au lieu de la syntaxe <abbr title="eXtended Markup Language">XML</abbr> précédemment retenue.</p>
<p>A titre personnel, je ne peux qu'être content de cette modification puisqu'en tant qu'administrateur système, j'ai régulièrement le nez dans les fichiers de configuration et que, comme le démontre très bien <a href="http://news.php.net/php.internals/48068">Jérome</a>, le <abbr title="eXtended Markup Language">XML</abbr> est loin d'être le langage le plus adapté et le plus pratique dans ce contexte.</p>
<p>Cette parenthèse terminée, poursuivons l'inventaire des dernière fonctionnalités intégrées à <a href="http://www.php.net">PHP</a> : les <code>closures</code> supportent dorénavant les appels à <code>$this</code>, ce qui va démultiplier leur puissance et enfin permettre de faire entre autre de l'injection de dépendances proprement.</p>
<p>Par ailleurs, la directive <code>session.bug_compat_42</code> et sa cousine <code>session.bug_compat_warn</code> ont été supprimées, tout comme, et cela mérite vos applaudissements, <code>register_globals</code>, après des années de mauvais et loyaux services.</p>
<p>Enfin, les <a href="http://fr.wikipedia.org/wiki/Bug_informatique">bogues</a> <a href="http://bugs.php.net?id=51577">#51577</a>, <a href="http://bugs.php.net?id=51608">#51608</a>, <a href="http://bugs.php.net?id=48781">#48781</a>, <a href="http://bugs.php.net?id=51609">#51609</a>, <a href="http://bugs.php.net?id=49700">#49700</a>, <a href="http://bugs.php.net?id=51607">#51607</a>, <a href="http://bugs.php.net?id=51615">#51615</a>, <a href="http://bugs.php.net?id=51562">#51562</a>, <a href="http://bugs.php.net?id=51627">#51627</a> et <a href="http://bugs.php.net?id=51604">#51604</a> ont été corrigés, et il y a eu de nombreuses optimisations intégrées, que ce soit au niveau de la gestion des constantes, des variables, ou <a href="http://fr2.php.net/manual/en/book.mysqlnd.php">du pilote natif pour mysql</a>, ainsi que beaucoup de nettoyage effectué dans le code.</p>
<p>Bref, il y a enfin du concret après pas mal de palabres, et à titre personel, cela me fait plaisir.</p>
<p>A contrario du <a href="http://svn.php.net/viewvc/php/php-src/trunk/">trunk svn</a>, <a href="http://news.php.net/php.internals">internals@</a> a été plutôt calme, surtout cette dernière semaine, même si <del>un fou</del> quelqu'un a tenté de mettre de l'ambiance en <a href="http://news.php.net/php.internals/48023">critiquant PHP de manière constructive et en exprimant ses désirs</a> pour la prochaine version.</p>
<p>Je n'ai donc pour une fois rien de particulier à en dire.</p>http://blog.mageekbox.net/?post/2010/04/23/Mort-de-PHP6-40-jours#comment-formhttp://blog.mageekbox.net/?feed/atom/comments/115Mort de PHP6 + 30 joursurn:md5:82fa76f857439907063f6f08c89b3db62010-04-15T08:00:00+02:002011-02-25T16:39:22+01:00mageekguyPHP Xclosureinternals@PHP XPHP6RFCZend Engine<p>Elle est vivante.</p>
<p>Tel <a href="http://blog.mageekbox.net/?post/2010/04/10/">le monstre de Frankenstein</a>, la prochaine version majeure de <a href="http://blog.mageekbox.net/?post/2010/04/10/http;//www.php.net">PHP</a> est vivante.</p>
<p>Mais pourquoi cette référence à <a href="http://blog.mageekbox.net/?post/2010/04/10/../">Frankenstein</a> ?</p>
<p>Parce que, comme <a href="http://fr.wikipedia.org/wiki/Victor_Frankenstein" title="Victor Frankenstein">Victor Frankenstein</a>,
le PHP Group prend des morceaux de ce qui devait être PHP 6 et la
prochaine version de la branche 5.x pour créer la version suivante du
langage, qui, tout comme le monstre du roman, n'a pas (encore) de nom.</p> <p>Cependant, ce n'est pas parce qu'il y a de la vie que tout va bien.</p>
<p>Le pouls est encore faible, les choses avancent lentement et tout n'est pas encore clair au sein du groupe des développeurs de <a href="http://blog.mageekbox.net/?post/2010/04/10/http;//www.php.net">PHP</a>, et cela même si de <a href="http://news.php.net/php.internals/47806">bonnes</a> <a href="http://news.php.net/php.internals/47688">âmes</a> proposent leur aide et <a href="http://blog.mageekbox.net/?post/2010/04/07/Vous-souhaitez-participer-ou-vous-participez-d%C3%A9j%C3%A0-au-d%C3%A9veloppement-de-PHP">qu'un appel a été lancé</a> pour documenter le fonctionnement et le développement du <a href="http://fr.wikipedia.org/wiki/Zend_Engine">Zend Engine</a>.</p>
<p>Les choses se mettent tout de même en place, puisqu'un nettoyage de la documentation de feu PHP6 a débuté.</p>
<p>Les fonctionnalités qui sont déjà intégrées au langage via la branche 5.3 en sont supprimées, et peut être que d'autres viendront s'ajouter dans les <del>années mois</del> jours qui viennent, une fois que les diverses <a href="http://wiki.php.net/rfc"><abbr title="Request For Comment">RFC</abbr></a> auront été commentées et approuvées.</p>
<p>La liste des fonctionnalités actuellement supportées par PHP pour des raisons de compatibilité avec les versions antérieures est également <a href="http://news.php.net/php.internals/47839">en cours d'actualisation</a>.</p>
<p>Ainsi, il est pratiquement certain que le support des directives suivantes sera abandonné, et personnellement je ne pleurerais pas dessus.</p>
<ul><li><code>safe_mode</code></li>
<li><code>register_globals</code></li>
<li><code>register_long_arrays</code></li>
<li><code>magic_quotes_*</code></li>
<li><code>allow_call_time_pass_reference</code></li>
<li><code>sql_safe_mode</code></li>
</ul>
<p>L'abandon de la directive <code>register_globals</code> cause des dommages collatéraux puisque le support des fonctions <code>session_register()</code>, <code>session_is_registered()</code>, <code>session_register()</code> ne feront plus parties du langage à l'avenir, puisqu'elles dépendent de cette directive.</p>
<p>Par ailleurs, les balises d'ouverture et de fermeture de script à la sauce <code>asp</code>
sont également sur le départ, même s'il y a des discussion à leur sujet
car certain pensent qu'elles sont très utilisées et que cela pourrait
être pénalisant de ne plus les supporter.</p>
<p>il en va de même pour la fonction <code><a href="http://fr2.php.net/dl">dl()</a></code> qui pourrait totalement disparaître, et pour le coup, je n'étais déjà pas d'accord lorsqu'elle a disparu des <a href="http://php.net/manual/en/function.php-sapi-name.php"><code><abbr title="Server API">SAPI</abbr></code></a> autre que <code><abbr title="Command Line Interface">CLI</abbr></code>, et donc je ne suis toujours pas d'accord avec cette décision.</p>
<p>Le support de <code>Freetype</code> et de <code>GD</code> dans sa première version sera également abandonnée.</p>
<p>Évidement, si vous désirez plus de détails, vous pouvez vous référer à <a href="http://wiki.php.net/rfc/removal-of-deprecated-features">la <abbr title="Request for Comments">RFC</abbr></a> dédiée à ce sujet.</p>
<p>Si ce qui précéde est encore en cours de discussion, il y a des choses dont la suppression est acquise.</p>
<p>Ainsi, la directive <code>y2k_compliance</code>, qui n'a plus lieu d'être en 2010 et sera donc activée par défaut à la compilation.</p>
<p>
Dans un autre registre, la modification qui ne laisse que <code>__construct()</code> comme constructeur valide <a href="http://svn.php.net/viewvc?view=revision&sortby=date&revision=297482">a été commitée</a> dans le <a href="http://svn.php.net/viewvc/php/php-src/trunk/">trunk</a>.
</p>
<p>Autre modification faite sur le <a href="http://svn.php.net/viewvc/php/php-src/trunk/">trunk</a>, la constante <a href="http://fr.php.net/manual/en/function.php-uname.php">PHP_OS</a> retournera dorénavant la valeur <code>WINNT</code> lorsque <a href="http://www.php.net">PHP</a> sera compilé sous Windows et la nouvelle version de <a href="http://wiki.php.net/rfc/fpm">FPM</a> a également était ajoutée.</p>
<p>Par ailleurs, <a href="http://news.php.net/php.internals/46066">certain</a>, dont <a href="http://news.php.net/php.internals/47833">moi</a>, se sont également inquiété de savoir si la future version améliorera le support des closures, qui souffre de certaines limitations dommageable, pour le moins.</p>
<p>Apparemment, il y a une discussion à leur sujet autour de la <a href="http://wiki.php.net/rfc/closures/object-extension"><abbr title="Request for Comments">RFC</abbr> correspondante</a>, mais je n'ai pas pour le moment réussi à avoir d'informations plus précises.</p>
<p>De plus, une implémentation du <a href="http://fr.wikipedia.org/wiki/Multithreading">multithreading</a> <a href="http://news.php.net/php.internals/47786">a été réalisée et présentée</a>, mais pour l'instant, il n'y a malheureusement pas eu de retour au sujet d'une éventuelle intégration.</p>
<p>Et pour ceux qui se posent encore la question, les discussions à propos d'un support éventuel d'Unicode n'ont toujours pas débutées, même si <a href="http://news.php.net/php.internals/47854">une tentative de formalisation et d'état des lieux</a> est en cours.</p>http://blog.mageekbox.net/?post/2010/04/10/Mort-de-PHP6-30-jours#comment-formhttp://blog.mageekbox.net/?feed/atom/comments/109On ferme !urn:md5:7dedb704e5071599a72187a990440eb52010-02-22T09:30:00+01:002010-02-22T09:30:00+01:00mageekguyPHP5.3adapterbufferisationclosureechofermeturePHPtests unitairestips<p>Sous ce titre <del>idiot</del> ne se cache pas l'annonce de la fermeture de ce blog, mais bien un cas concret d'utilisation des <a hreflang="fr" href="http://blog.pascal-martin.fr/post/php-5.3-2-closures-et-lambdas">fermetures de PHP 5.3</a>.</p>
<p>Je me suis longtemps demandé ce que je pourrais bien en faire, et il semble que je ne sois pas le <a href="http://blog.pascal-martin.fr/post/php-5.3-2-closures-et-lambdas">seul</a>, au vu des commentaires sur le blog de <a href="http://blog.pascal-martin.fr">Pascal</a> et de la discussion que j'avais eu avec <a href="http://fr.linkedin.com/in/damienseguy">Damien Seguy</a> à ce sujet lors d'un apéro PHP à Lille.</p>
<p>J'avais bien une vague idée du potentiel du concept via mon expérience de développeur javascript, mais je n'en voyais aucun cas d'utilisation intéressant en <a href="http://www.php.net">PHP</a>, jusqu'à maintenant.</p> <p>En effet, aujourd'hui, dans le cadre des tests unitaires d'<a href="https://svn.mageekbox.net/repositories/ogo/trunk/">ogo</a>, j'ai eu besoin de tester non pas la valeur d'une variable, mais ce que PHP était censé afficher à l'aide de la commande <code>echo</code>.</p>
<p>Mon premier réflexe a été d'utiliser un <a href="http://blog.mageekbox.net/?post/2009/06/15/G%C3%A9n%C3%A9ricit%C3%A9-%21"><code>adapter</code></a>, mais<code> echo</code> est une construction du langage et non une fonction, et à ce titre, il n'est pas possible d'utiliser cette technique.</p>
<p>Pourtant, il fallait bien que je puisse tester ce que <code>echo</code> recevait comme argument...</p>
<p>Pour résoudre ce problème, ma première approche, très classique, a été d'utiliser les <a href="http://fr.php.net/manual/fr/ref.outcontrol.php">fonctions de bufferisation</a> de <a href="http://www.php.net">PHP</a>, qui permettent de stocker en mémoire l'intégralité de ce qui est envoyé à la commande <code>echo</code> et de ne l'afficher qu'à la demande ou à la fin du script, voir même de récupérer dans une variable la totalité des données.</p>
<p>Le code était alors le suivant :</p>
<blockquote><pre><code><?php<br />...<br />protected function testMakeReport()<br />{<br /> $score = new \ogo\test\cases\score($this);<br /> $reporter = new \ogo\test\cases\reporter\cli();<br /> $reporter->addScore($score);<br /><br /> ob_start();<br /> $reporter->makeReport(); // méthode utilisant la commande echo<br /> $echo = ob_get_clean();<br /> $this->assert->string($echo)->isEmpty();<br />}<br />...<br />?><br /></code></pre></blockquote>
<p>A première vue, ce n'est pas mal puisque ma problèmatique est résolue, mais en réalité, c'est de la merde !</p>
<p>En effet, à chaque fois que j'aurais besoin de tester le comportement de \<code>ogo\test\cases\reporter\cli::makeReport()</code> ou d'une méthode faisant appel à une commande du type d'<code>echo</code>, je serais obligé de dupliquer la séquence de code suivante :</p>
<blockquote><pre><code><?php<br />...<br />ob_start();<br />// des trucs faisant appel à echo<br />$echo = ob_get_clean();<br />$this->assert->string($echo)->...</code><br /><code>...<br />?><br /></code></pre></blockquote>
<p>Et je sais pas ce qu'il en a été pour vous, mais mes professeurs m'ont appris qu'un développeur qui fait de la duplication de code méritait le bûcher, et personnellement, je suis plutôt allergique aux flammes.</p>
<p>De plus, je <del>suis un fainéant</del> n'aime pas avoir le bout des doigts carrés à force de taper sur mon clavier.</p>
<p>Et c'est à ce moment que j'ai pensé aux fameuses fermetures de <a href="http://blog.pascal-martin.fr/post/php-5.3-2-closures-et-lambdas">PHP 5.3</a>.</p>
<p>En effet, pourquoi ne pas créer une méthode dans ma classe de test qui accepterait une fonction anonyme comme argument, qui démarrerait la bufferisation, éxécuterait la fonction anonyme, arrêterait la bufferisation et renverrait son contenu ?</p>
<p>C'est donc ce que j'ai fais, de la manière suivante.</p>
<p>J'ai ajouté à ma classe de test <code>\ogo\test\cases\base</code> la méthode <code>getOutput()</code>, dont le code est le suivant :</p>
<blockquote><pre><code><?php<br />...<br />protected function getOutput($function)<br />{<br /> ob_start();<br /> $function();<br /> $output = ob_get_clean();<br /><br /> return $output;<br />}<br />...<br />?><br /></code></pre></blockquote>
<p>Une fois cela fait, il ne me restait plus qu'à la mettre en oeuvre dans mon test à l'aide d'une <a href="http://blog.pascal-martin.fr/post/php-5.3-2-closures-et-lambdas">fermeture</a> :</p>
<blockquote><pre><code><?php<br />...<br />protected function testMakeReport()<br />{<br /> $score = new \ogo\test\cases\score($this);<br /> $reporter = new \ogo\test\cases\reporter\cli();<br /> $reporter->addScore($score);<br /><br /> $this->assert->string($this->getOutput(function() use ($reporter) { $reporter->makeReport(); }))->isEmpty();<br />}<br />...<br />?><br /></code></pre></blockquote>
<p>Et en poussant le vice un peu plus loin, il serait même possible de déporter ce traitement dans un <code>asserter</code> spécifique puisque finalement, la méthode <code>getOutput()</code> n'a rien à faire dans la classe de test.</p>
<p>De plus cela permettrait de réduire encore le code :</p>
<blockquote><pre><code><?php<br />...<br />protected function testMakeReport()<br />{<br /> $score = new \ogo\test\cases\score($this);<br /> $reporter = new \ogo\test\cases\reporter\cli();<br /> $reporter->addScore($score);<br /><br /> // nous passons maintenant directement par l'asserter<br /> $this->assert->output(function() use ($reporter) { $reporter->makeReport(); })->isEmpty();<br />}<br />...<br />?><br /></code></pre></blockquote>
<p>Ainsi, la duplication de code est supprimée, je ne brulerais pas sur un bûcher, mes doigts ne deviendront pas carrés, et j'ai un moyen standard pour tester tout ce qui est envoyé à <code>echo</code> et aux autres commandes <a href="http://www.php.net">PHP</a> du même type.</p>
<p>Pour ceux que cela intéresse, le <a href="https://svn.mageekbox.net/repositories/ogo/trunk/tests/cases/test/cases/asserter/output.php">code final</a> est disponible dans <a href="https://svn.mageekbox.net/repositories/ogo/trunk">le dépôt de <code>ogo</code></a>.</p>
<p>Et finalement, les <a hreflang="fr" href="http://blog.pascal-martin.fr/post/php-5.3-2-closures-et-lambdas">fermetures</a>, assez paradoxalement, m'ouvre tout un tas de perspectives intéressantes dans le cadre de futurs développements...</p>http://blog.mageekbox.net/?post/2010/02/19/On-ferme-%21#comment-formhttp://blog.mageekbox.net/?feed/atom/comments/89