<?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>Blog de Jonathan Petitcolas &#187; PEJO Framework</title>
	<atom:link href="http://www.jonathan-petitcolas.com/tag/pejo-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jonathan-petitcolas.com</link>
	<description>Geek, développeur Web, passionné de high-tech</description>
	<lastBuildDate>Sat, 21 Aug 2010 14:47:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>I need you for the PEJO framework!</title>
		<link>http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/</link>
		<comments>http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/#comments</comments>
		<pubDate>Tue, 18 May 2010 00:17:12 +0000</pubDate>
		<dc:creator>Jonathan Petitcolas</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[bénévolat]]></category>
		<category><![CDATA[PEJO Framework]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.jonathan-petitcolas.com/fr/?p=2519</guid>
		<description><![CDATA[Suite à mon manque cruel de temps, je recherche des volontaires pour m'aider à publier le framework PEJO : rédaction de la documentation, amélioration du code, ajout de fonctionnalités... N'hésitez pas à me contacter si vous êtes intéressés ! :)]]></description>
			<content:encoded><![CDATA[<p class="center"><img src="http://www.jonathan-petitcolas.com/wp-content/uploads/2010/05/i-want-you-263x300.gif" alt="I want you for the PEJO framework!" title="I want you for the PEJO framework!" width="263" height="300" class="aligncenter size-thumbnail wp-image-2520" /></p>
<p>Me revoilà après quelques semaines (on peut même dire quelques mois) d'absence. <em>Mea culpa, mea maxima culpa.</em> :)</p>
<p>Qu'on se rassure, ce blog n'est pas mort. C'est juste qu'en ce moment, le temps me manque cruellement. Entre la gestion d'une flopée de blogs pour le compte d'institutionnels chez <a href="http://www.tlconseil.com">TL Conseil</a>, la gestion en parallèle de deux projets personnels dont je ne manquerai pas de vous parler très prochainement, mon déménagement imminent, etc... je réduis forcément le temps consacré à ce blog, seul créneau que je peux diminuer sans (trop) de problèmes. Bref, assez parlé de moi, et parlons plutôt de technique ! Après tout, vous êtes sur un blog de développeurs, non ? :p</p>
<p>Comme certains d'entre vous le savent déjà, je m'apprête (depuis trop longtemps) à publier mon framework personnel, déjà utilisé sur une bonne vingtaine de sites. Pour ce faire, il faut bien entendu rédiger toute la documentation utilisateur et développeur. Et c'est là où le bas blesse. Car cela prend un temps démesuré. C'est pourquoi je m'en remets à vous, fidèles lecteurs de ce blog. :)</p>
<p>Je recherche en effet des âmes motivées pour m'aider dans cette tâche. Le travail sera bien entendu bénévole, n'ayant à vous offrir qu'une place dans les crédits. Quelques conditions sont tout de même requises (ce serait trop facile :p) :</p>
<ul>
<li>Orthographe et grammaire irréprochable,</li>
<li>Être développeur PHP 5,</li>
<li>Idéalement être en région parisienne -mais ce n'est pas une obligation - histoire de pouvoir <em>brainstormer</em> physiquement (et après finir en pizza/Dot-A :p).</li>
</ul>
<p>Au programme : rédaction de la documentation, rédaction de tutoriaux pour s'initier au framework, amélioration de celui-ci (sécurité, fonctionnalités, rapidité, etc.). </p>
<p>S'il y a des volontaires, n'hésitez pas à vous signaler dans les commentaires. Pour les autres, encore un peu de patience ! :)</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;t=I+need+you+for+the+PEJO+framework%21" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Jonathan+Petitcolas+%3A+I+need+you+for+the+PEJO+framework%21+-+http://tinyurl.com/2wcznhq&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-netvibes">
			<a href="http://www.netvibes.com/share?title=I+need+you+for+the+PEJO+framework%21&amp;url=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/" rel="nofollow" class="external" title="Submit this to Netvibes">Submit this to Netvibes</a>
		</li>
		<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;title=I+need+you+for+the+PEJO+framework%21&amp;summary=Suite%20%C3%A0%20mon%20manque%20cruel%20de%20temps%2C%20je%20recherche%20des%20volontaires%20pour%20m%27aider%20%C3%A0%20publier%20le%20framework%20PEJO%20%3A%20r%C3%A9daction%20de%20la%20documentation%2C%20am%C3%A9lioration%20du%20code%2C%20ajout%20de%20fonctionnalit%C3%A9s...%20N%27h%C3%A9sitez%20pas%20%C3%A0%20me%20contacter%20si%20vous%20%C3%AAtes%20int%C3%A9ress%C3%A9s%20%21%20%3A%29&amp;source=Blog de Jonathan Petitcolas" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;title=I+need+you+for+the+PEJO+framework%21&amp;srcUrl=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;srcTitle=I+need+you+for+the+PEJO+framework%21&amp;snippet=Suite%20%C3%A0%20mon%20manque%20cruel%20de%20temps%2C%20je%20recherche%20des%20volontaires%20pour%20m%27aider%20%C3%A0%20publier%20le%20framework%20PEJO%20%3A%20r%C3%A9daction%20de%20la%20documentation%2C%20am%C3%A9lioration%20du%20code%2C%20ajout%20de%20fonctionnalit%C3%A9s...%20N%27h%C3%A9sitez%20pas%20%C3%A0%20me%20contacter%20si%20vous%20%C3%AAtes%20int%C3%A9ress%C3%A9s%20%21%20%3A%29" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;title=I+need+you+for+the+PEJO+framework%21" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/&amp;title=I+need+you+for+the+PEJO+framework%21" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.jonathan-petitcolas.com/i-need-you-for-the-pejo-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convertir une phrase pour l&#039;URL Rewriting en PHP</title>
		<link>http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/</link>
		<comments>http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 09:35:58 +0000</pubDate>
		<dc:creator>Jonathan Petitcolas</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[PEJO Framework]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[URL rewriting]]></category>

		<guid isPermaLink="false">http://www.jonathan-petitcolas.com/?p=2219</guid>
		<description><![CDATA[Comment convertir une phrase en une chaîne de caractères optimisée pour l'URL Rewriting en PHP ? Voici une fonction répondant à cette problématique, ce qui vous permettra par la même occasion d'optimiser votre référencement.]]></description>
			<content:encoded><![CDATA[<p>Cela faisait bien longtemps qu'il n'y avait pas eu d'article technique. Voici donc une petite fonction bien utile afin de transformer, un peu à la WordPress, une phrase en un lien optimisé pour le référencement. Par exemple, on peut transformer la phrase :</p>
<blockquote><p>Télécharger le bulletin d'adhésion à notre association</p></blockquote>
<p>En :</p>
<blockquote><p>telecharger-bulletin-adhesion-notre-association</p></blockquote>
<p>On aura alors gardé les mots-clefs essentiels, tout en supprimant les caractères spéciaux qui pourraient poser problème dans les navigateurs. Très utile pour l'URL Rewriting, cela vous permettra d'optimiser simplement votre référencement. Abusez-en, c'est gratuit ! :p</p>
<pre class="brush: php;">/**
 * Convert into filename by removing all accents and special characters. Useful for URL Rewriting.
 * @param $text
 * @return string
 */
public function ConvertIntoFilename($text)
{
	// Remove all accents.
	$convertedCharacters = array(
		&amp;quot;À&amp;quot; =&amp;gt; &amp;quot;A&amp;quot;, &amp;quot;Á&amp;quot; =&amp;gt; &amp;quot;A&amp;quot;, &amp;quot;Â&amp;quot; =&amp;gt; &amp;quot;A&amp;quot;, &amp;quot;Ã&amp;quot; =&amp;gt; &amp;quot;A&amp;quot;, &amp;quot;Ä&amp;quot; =&amp;gt; &amp;quot;A&amp;quot;, &amp;quot;Å&amp;quot; =&amp;gt; &amp;quot;A&amp;quot;,
		&amp;quot;à&amp;quot; =&amp;gt; &amp;quot;a&amp;quot;, &amp;quot;á&amp;quot; =&amp;gt; &amp;quot;a&amp;quot;, &amp;quot;â&amp;quot; =&amp;gt; &amp;quot;a&amp;quot;, &amp;quot;ã&amp;quot; =&amp;gt; &amp;quot;a&amp;quot;, &amp;quot;ä&amp;quot; =&amp;gt; &amp;quot;a&amp;quot;, &amp;quot;å&amp;quot; =&amp;gt; &amp;quot;a&amp;quot;,
		&amp;quot;Ò&amp;quot; =&amp;gt; &amp;quot;O&amp;quot;, &amp;quot;Ó&amp;quot; =&amp;gt; &amp;quot;O&amp;quot;, &amp;quot;Ô&amp;quot; =&amp;gt; &amp;quot;O&amp;quot;, &amp;quot;Õ&amp;quot; =&amp;gt; &amp;quot;O&amp;quot;, &amp;quot;Ö&amp;quot; =&amp;gt; &amp;quot;O&amp;quot;, &amp;quot;Ø&amp;quot; =&amp;gt; &amp;quot;O&amp;quot;,
		&amp;quot;ò&amp;quot; =&amp;gt; &amp;quot;o&amp;quot;, &amp;quot;ó&amp;quot; =&amp;gt; &amp;quot;o&amp;quot;, &amp;quot;ô&amp;quot; =&amp;gt; &amp;quot;o&amp;quot;, &amp;quot;õ&amp;quot; =&amp;gt; &amp;quot;o&amp;quot;, &amp;quot;ö&amp;quot; =&amp;gt; &amp;quot;o&amp;quot;, &amp;quot;ø&amp;quot; =&amp;gt; &amp;quot;o&amp;quot;,
		&amp;quot;È&amp;quot; =&amp;gt; &amp;quot;E&amp;quot;, &amp;quot;É&amp;quot; =&amp;gt; &amp;quot;E&amp;quot;, &amp;quot;Ê&amp;quot; =&amp;gt; &amp;quot;E&amp;quot;, &amp;quot;Ë&amp;quot; =&amp;gt; &amp;quot;E&amp;quot;,
		&amp;quot;é&amp;quot; =&amp;gt; &amp;quot;e&amp;quot;, &amp;quot;è&amp;quot; =&amp;gt; &amp;quot;e&amp;quot;, &amp;quot;ê&amp;quot; =&amp;gt; &amp;quot;e&amp;quot;, &amp;quot;ë&amp;quot; =&amp;gt; &amp;quot;e&amp;quot;,
		&amp;quot;Ç&amp;quot; =&amp;gt; &amp;quot;C&amp;quot;, &amp;quot;ç&amp;quot; =&amp;gt; &amp;quot;c&amp;quot;,
		&amp;quot;Ì&amp;quot; =&amp;gt; &amp;quot;I&amp;quot;, &amp;quot;Í&amp;quot; =&amp;gt; &amp;quot;I&amp;quot;, &amp;quot;Î&amp;quot; =&amp;gt; &amp;quot;I&amp;quot;, &amp;quot;Ï&amp;quot; =&amp;gt; &amp;quot;I&amp;quot;,
		&amp;quot;ì&amp;quot; =&amp;gt; &amp;quot;i&amp;quot;, &amp;quot;í&amp;quot; =&amp;gt; &amp;quot;i&amp;quot;, &amp;quot;î&amp;quot; =&amp;gt; &amp;quot;i&amp;quot;, &amp;quot;ï&amp;quot; =&amp;gt; &amp;quot;i&amp;quot;,
		&amp;quot;Ù&amp;quot; =&amp;gt; &amp;quot;U&amp;quot;, &amp;quot;Ú&amp;quot; =&amp;gt; &amp;quot;U&amp;quot;, &amp;quot;Û&amp;quot; =&amp;gt; &amp;quot;U&amp;quot;, &amp;quot;Ü&amp;quot; =&amp;gt; &amp;quot;U&amp;quot;,
		&amp;quot;ù&amp;quot; =&amp;gt; &amp;quot;u&amp;quot;, &amp;quot;ú&amp;quot; =&amp;gt; &amp;quot;u&amp;quot;, &amp;quot;û&amp;quot; =&amp;gt; &amp;quot;u&amp;quot;, &amp;quot;ü&amp;quot; =&amp;gt; &amp;quot;u&amp;quot;,
		&amp;quot;ÿ&amp;quot; =&amp;gt; &amp;quot;y&amp;quot;,
		&amp;quot;Ñ&amp;quot; =&amp;gt; &amp;quot;N&amp;quot;, &amp;quot;ñ&amp;quot; =&amp;gt; &amp;quot;n&amp;quot;
	);

	$text = strtr($text, $convertedCharacters);

	// Put the text in lowercase.
	$text = mb_strtolower($text, 'utf-8');

	// Remove all special characters.
	$text = preg_replace('#[^a-z0-9\-]#', '-', $text);

	// Remove two consecutive dashes (that's not very pretty).
	$text = preg_replace('/--/U', '-', $text);

	// Remove words containing less than 2 characters (non significant for the meaning)
	$return = array();
	$text = explode('-', $text);

	foreach($text as $word)
	{
		if(mb_strlen($word, 'utf-8') &amp;lt;= 2)	continue;
		$return[] = $word;
	}

	return implode('-', $return);
}</pre>
<p>Voici le processus technique, même si cela risque d'être redondant par rapport aux commentaires.</p>
<ol>
<li>On commence par supprimer tous les accents et caractères un peu litigieux (comme le c cédille) en les remplaçant par leur équivalent littéral, grâce à la fonction <em>strtr</em>,</li>
<li>On met alors la phrase en minuscules, grâce à la fonction <em>mb_strtolower</em>. Pourquoi ne pas utiliser la fonction <em>strtolower</em> plus simplement ? Car celle-ci ne gère pas l'UTF-8. Il est donc bon d'avoir le réflexe <em>mb_</em> pour toutes les fonctions standards de chaînes de caractères, qui possède un second argument : l'encodage de la chaîne de caractères.</li>
<li>On supprime alors, à l'aide d'une expression régulière (pour ne pas en oublier), tous les caractères autres que les chiffres et les lettres minuscules, en les remplaçant par des tirets.</li>
<li>Puis, on supprime tous les double-tirets consécutifs. Simple raison d'esthétisme, car ce n'est pas franchement très beau. ^^</li>
<li>Enfin, on supprime les petits mots de deux lettres, qui n'ont que peu d'intérêt (en règle général), comme par exemple <em>de</em>, <em>le</em>, <em>un</em>, etc. Pour ce faire, on découpe la chaîne au niveau des tirets, et on regarde la taille, de nouveau avec une fonction <em>mb_</em>.</li>
<li>Il ne nous reste alors plus qu'à retourner la chaîne reconstruite avec des tirets.</li>
</ol>
<p>Cette fonction fait également partie du PEJO Framework, dont le site est actuellement en stand-by, étant donné le peu de temps que j'ai en ce moment. Mais il sortira bientôt... un jour... :)</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;t=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Jonathan+Petitcolas+%3A+Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP+-+http://tinyurl.com/yc4oe6v&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-netvibes">
			<a href="http://www.netvibes.com/share?title=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP&amp;url=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/" rel="nofollow" class="external" title="Submit this to Netvibes">Submit this to Netvibes</a>
		</li>
		<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;title=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP&amp;summary=Comment%20convertir%20une%20phrase%20en%20une%20cha%C3%AEne%20de%20caract%C3%A8res%20optimis%C3%A9e%20pour%20l%27URL%20Rewriting%20en%20PHP%20%3F%20Voici%20une%20fonction%20r%C3%A9pondant%20%C3%A0%20cette%20probl%C3%A9matique%2C%20ce%20qui%20vous%20permettra%20par%20la%20m%C3%AAme%20occasion%20d%27optimiser%20votre%20r%C3%A9f%C3%A9rencement.&amp;source=Blog de Jonathan Petitcolas" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;title=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP&amp;srcUrl=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;srcTitle=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP&amp;snippet=Comment%20convertir%20une%20phrase%20en%20une%20cha%C3%AEne%20de%20caract%C3%A8res%20optimis%C3%A9e%20pour%20l%27URL%20Rewriting%20en%20PHP%20%3F%20Voici%20une%20fonction%20r%C3%A9pondant%20%C3%A0%20cette%20probl%C3%A9matique%2C%20ce%20qui%20vous%20permettra%20par%20la%20m%C3%AAme%20occasion%20d%27optimiser%20votre%20r%C3%A9f%C3%A9rencement." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;title=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/&amp;title=Convertir+une+phrase+pour+l%27URL+Rewriting+en+PHP" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.jonathan-petitcolas.com/convertir-une-phrase-pour-lurl-rewriting-en-php/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Vérifier la validité d&#039;une URL en PHP</title>
		<link>http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/</link>
		<comments>http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 08:33:24 +0000</pubDate>
		<dc:creator>Jonathan Petitcolas</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[contrôle]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[PEJO Framework]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[url]]></category>

		<guid isPermaLink="false">http://www.jonathan-petitcolas.com/?p=1945</guid>
		<description><![CDATA[Fonction permettant de contrôler la validité d'une URL saisie dans un formulaire en PHP. Le contrôle se fera en trois étapes : champ renseigné, syntaxe valide, et vérification de l'existence du site. ]]></description>
			<content:encoded><![CDATA[<p>Le contrôle des données utilisateurs dans vos formulaires est primordial pour la sécurité de votre système d'informations. Cela passe bien évidemment par le contrôle des injections SQL et autres failles XSS. Cependant, cette protection n'assure pas forcément l'intégrité de vos données. Un internaute peut très bien saisir en guise de site Internet son numéro de téléphone. Voyons donc une fonction permettant de contrôler la validité d'une URL.</p>
<pre class="brush: php;">/**
 * Checks that an URL is valid and really exists (checking with a basic ping).
 * @param $url Address to check.
 * @param $required Required field?
 * @return string
 */
function ValidateUrl($url, $required = false)
{
	if(empty($url))
	{
		if(!$required) return '';
		else throw new Exception('Please fill in all mandatory fields.');
	}
	else
	{
		$regex = '#(((http|ftp|https|ftps)://)|(www\.))+(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(/[a-zA-Z0-9\&amp;amp;%_\./-~-]*)?#';

		// Checking only syntax
		if(preg_match($regex, $url))
		{
			// And checking that the website really exists.
			$curl = curl_init($url);

			// Setting the URL.
			curl_setopt($curl, CURLOPT_URL, $url);
			// We want to read the header.
			curl_setopt($curl, CURLOPT_HEADER, 1);
			// We do not need the page content.
			curl_setopt($curl, CURLOPT_NOBODY, 1);
			// Do not display the page, just return us its content.
			curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

			$datas = curl_exec($curl);

			curl_close($curl);

			if(!empty($datas)) return $url;
			else throw new Exception('Unable to join site at '.$url.'.');
		}
		else throw new Exception('Please enter a valid address.');
	}
}</pre>
<p>La vérification de l'URL se déroule en trois temps.</p>
<ol>
<li><strong>Champ obligatoire :</strong> on vérifie tout d'abord que l'utilisateur a bien rempli le champ correspondant dans le formulaire. Si celui-ci est obligatoire (attribut <em>$required</em>), alors on lève une exception.</li>
<li><strong>Vérification syntaxique :</strong> on s'assure que l'URL est correctement formée syntaxiquement, à travers une expression régulière plutôt lourde. Vous pouvez lui faire confiance, elle fonctionne. Elle prend tout aussi bien un nom de domaine qu'une adresse IP.</li>
<li><strong>Existence du site :</strong> enfin, on effectue un ping vers le site indiqué, grâce à l'extension <em>curl</em>. Si le site n'existe pas, nous ne retrouverons rien dans la variable <em>$datas</em>, et donc nous léverons une exception afin d'indiquer à l'internaute qu'il s'est trompé dans l'adresse.</li>
</ol>
<p>Comme vous l'aurez compris, cette fonction nécessite l'utilisation de l'extension PHP <em>curl</em>, permettant la lecture de pages Web via PHP.</p>
<p>Le code est à mon sens suffisamment commenté. N'hésitez pas cependant à demander plus d'informations dans les commentaires, ainsi qu'à donner des suggestions d'amélioration. :)</p>
<p>Cette fonction fait partie du framework PEJO. Petit changement de stratégie le concernant : je ne vais publier que des snippets de code sur ce blog. Un site (en cours de construction) sera réservé à ce framework, et permettra un suivi bien plus simple : centralisation de toutes les classes sans billets parasites, suivi des modifications, mise en ligne de certains utilitaires forts pratiques (générateur de classes, de formulaires, etc.). Patience donc...</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;t=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Jonathan+Petitcolas+%3A+V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP+-+http://tinyurl.com/yjhuoot&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-netvibes">
			<a href="http://www.netvibes.com/share?title=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP&amp;url=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/" rel="nofollow" class="external" title="Submit this to Netvibes">Submit this to Netvibes</a>
		</li>
		<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;title=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP&amp;summary=Fonction%20permettant%20de%20contr%C3%B4ler%20la%20validit%C3%A9%20d%27une%20URL%20saisie%20dans%20un%20formulaire%20en%20PHP.%20Le%20contr%C3%B4le%20se%20fera%20en%20trois%20%C3%A9tapes%20%3A%20champ%20renseign%C3%A9%2C%20syntaxe%20valide%2C%20et%20v%C3%A9rification%20de%20l%27existence%20du%20site.%20&amp;source=Blog de Jonathan Petitcolas" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;title=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP&amp;srcUrl=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;srcTitle=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP&amp;snippet=Fonction%20permettant%20de%20contr%C3%B4ler%20la%20validit%C3%A9%20d%27une%20URL%20saisie%20dans%20un%20formulaire%20en%20PHP.%20Le%20contr%C3%B4le%20se%20fera%20en%20trois%20%C3%A9tapes%20%3A%20champ%20renseign%C3%A9%2C%20syntaxe%20valide%2C%20et%20v%C3%A9rification%20de%20l%27existence%20du%20site.%20" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;title=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/&amp;title=V%C3%A9rifier+la+validit%C3%A9+d%27une+URL+en+PHP" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.jonathan-petitcolas.com/verifier-la-validite-dune-url-en-php/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PEJO Framework : moteur de templates (classe TemplateEngine)</title>
		<link>http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/</link>
		<comments>http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 10:55:51 +0000</pubDate>
		<dc:creator>Jonathan Petitcolas</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[moteur de templates]]></category>
		<category><![CDATA[PEJO Framework]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.jonathan-petitcolas.com/?p=1084</guid>
		<description><![CDATA[Le PEJO framework sépare toute la partie interface utilisateur (en HTML) et la partie métier (en PHP). Pour ce faire, une classe de liaison entre ces deux composantes est essentielle : c'est la classe du moteur de templates, TemplateEngine.]]></description>
			<content:encoded><![CDATA[<p style="text-align: center; width: 200px; margin: auto;"><img src="http://www.jonathan-petitcolas.com/wp-content/uploads/2009/06/pejo-framework.png" alt="PEJO Framework" title="PEJO Framework" width="200" height="200" class="size-full wp-image-1803" style="border: 0;"/></p>
<p>Première étape dans la compréhension du <a href="http://www.jonathan-petitcolas.com/mes-realisations/">framework PEJO</a>, et pierre angulaire de tout cet édifice complexe, le moteur de templates permet la séparation du code PHP et du code HTML, et ce afin de simplifier un maximum le développement, et d'optimiser la répartition du travail entre intégrateur et développeur. Voyons donc le fonctionnement de cette classe centrale.</p>
<p>A noter que pour une meilleur compréhension de l'utilité des moteurs de templates, je vous invite à (re)lire mon article <a href="http://www.jonathan-petitcolas.com/creation-dun-moteur-de-templates-en-php-5-objet/">"Création d’un moteur de templates en PHP 5 objet"</a>.</p>
<p>La première partie de cette article comprendra la <a href="#utilisation">documentation de la classe</a>, ainsi qu'un <a href="#exemple">exemple d'utilisation</a>. La <a href="#details#">deuxième</a>, réservée aux développeurs souhaitant m'aider à optimiser cette classe, expliquera en détail l'intérieur des différentes méthodes. Elle ne sera en rien nécessaire à l'utilisation de ce framework.</p>
<p><span id="more-1084"></span></p>
<p style="text-align: center;"><a href="http://www.jonathan-petitcolas.com/wp-contentpejo-framework/class/common/templateEngine.php.txt">Télécharger la classe TemplateEngine, moteur de templates du framework PEJO</a></p>
<h3><a href="#" name="utilisation"></a>Méthodes de la classe TemplateEngine</h3>
<p>Cette classe contient différentes méthodes. Nous ne verrons ici, dans cette partie réservée aux utilisateurs du framework PEJO, uniquement les méthodes accessibles depuis l'extérieur, et requise pour la manipulation quotidienne de la classe.</p>
<h4>Constructeur :</h4>
<p>Tout d'abord, commençons à instancier notre moteur de template, dans le fichier <em>index.php</em> par exemple.</p>
<pre class="brush: php;">&lt; ?php 

	require_once('templateEngine.php');

	$tpl = new TemplateEngine();

?&gt;</pre>
<p>Ce constructeur prend un paramètre booléen, <em>$localization</em>. Celui-ci permettra d'indiquer au moteur s'il doit internationaliser notre application en utilisant l'extension PHP <em>gettext</em>. Par défaut, il ne cherchera pas à le faire. Et nous non plus, pour simplifier les choses. :)</p>
<h4>Affichage de sous-templates</h4>
<p>Il est possible de séparer un fichier HTML en plusieurs sous parties. Ce que nous allons faire ici. Créons donc un fichier <em>index.html</em>, et insérons-y le code suivant :</p>
<pre class="brush: xml;">&lt;!---===== tpl_name = bonjour =====---&gt;
&lt;p&gt;Bonjour le monde !&lt;/p&gt;

&lt;!---===== tpl_name = main =====---&gt;
&lt;h1&gt;Test du moteur de templates !&lt;/h1&gt;</pre>
<p>Ce fichier est séparé en une sous-partie d'identifiant <em>bonjour</em> et en une autre d'identifiant <em>main</em>. On remarque la syntaxe particulière de séparation des sous-parties :</p>
<pre class="brush: xml;">&lt;!---===== tpl_name = IDENTIFIANT =====---&gt;</pre>
<p>A noter qu'il faut au minimum une sous-partie par fichier, afin de pouvoir l'utiliser.</p>
<p>Comment récupérer une sous-partie depuis notre moteur de templates ? C'est le rôle de la méthode <em>GetHTMLCode</em>.</p>
<pre class="brush: php;">&lt; ?php 

	require_once('templateEngine.php');

	$tpl = new TemplateEngine();
	$buffer = $tpl-&gt;GetHTMLCode('index.html', 'bonjour');

?&gt;</pre>
<p>La méthode <em>GetHTMLCode</em> prend deux arguments. Le premier est le nom du fichier où aller récupérer la sous-partie, et le deuxième l'identifiant de la sous-partie. Dans ce cas, notre variable <em>$buffer</em> cmoprendra donc le paragraphe <em>"Bonjour le monde !"</em>.</p>
<p>On pourra constater que ce code n'affiche rien à l'heure actuel. Pour afficher quelque chose, il nous faudra passer par la méthode <em>Output</em>.</p>
<h4>Affichage</h4>
<p>La méthode <em>Output</em> va nous permettre d'afficher le contenu de la variable passée en argument.</p>
<pre class="brush: php;">TemplateEngine::Output($buffer);</pre>
<p>Cette méthode peut-être utile au cas où vous auriez des problèmes d'affichage (problèmes d'encodage, d'échappement d'apostrophes, etc.). En effet, il vous suffira de mettre votre fonction de traitement à l'intérieur de cette méthode, sans avoir à manipuler les buffers.</p>
<h4>Utilisation de variables</h4>
<p>A présent, nous allons voir comment interfacer notre code PHP avec notre code HTML. Imaginons le code PHP suivant :</p>
<pre class="brush: php;">&lt;?php 

	require_once('templateEngine.php');

	$prenom = 'Jonathan';
	$nom = 'Petitcolas';

	$tpl = new TemplateEngine();
	$bonjour = $tpl-&gt;GetHTMLCode('index.html', 'bonjour');
	TemplateEngine::Output($tpl-&gt;GetHTMLCode('index.html', 'main'));

?&gt;</pre>
<p>Et effectuons quelques modifications à notre code HTML :</p>
<pre class="brush: xml;">&lt;!---===== tpl_name = bonjour =====---&gt;
&lt;p&gt;Bonjour ${prenom} ${nom} !&lt;/p&gt;

&lt;!---===== tpl_name = main =====---&gt;
&lt;h1&gt;Test du moteur de templates !&lt;/h1&gt;

${bonjour}</pre>
<p>En observant le résultat, on aura le code source suivant :</p>
<pre class="brush: xml;">&lt;h1&gt;Test du moteur de templates !&lt;/h1&gt;
&lt;p&gt;Bonjour Jonathan Petitcolas !&lt;/p&gt;</pre>
<p>Que s'est-il passé ? A la ligne 9 du code PHP, nous avons récupéré le sous-template <em>bonjour</em>. A l'intérieur, nous avons deux variables, repérées par l'écriture <em>${VARIABLE}</em>. Le moteur de templates s'est alors chargé de remplacer ces étiquettes par les valeurs des variables respectives, par l'intermédiaire de la méthode <em>GetHTMLCode</em>.</p>
<p>Après avoir placé ce code modifié dans une variable, nous l'avons affiché dans la partie <em>main</em>, avant de tout envoyer au navigateur, via la méthode statique <em>Output</em>. Rien de plus compliqué. :)</p>
<p>A présent, vous connaissez toute la théorie de niveau supérieur pour utiliser ce moteur de templates. Vous pourrez ainsi développer proprement, en séparant à la fois partie PHP et partie HTML. En effet, pour obtenir un taux de maintenabilité le plus élevé possible, il est important de séparer le code de votre application en ses différentes composantes : PHP, HTML, Javascript, CSS, etc... Tout doit être dans un fichier différent (idéalement). Nous veillerons particulièrement à cette <em>best-pratice</em> dans l'utilisation du framework PEJO.</p>
<h3><a href="#" name="exemple"></a>Exemple d'utilisation</h3>
<p>Nous allons voir ici un exemple d'utilisation de cette classe, exemple que nous aurons souvent besoin de retrouver dans la suite de nos développements, à savoir l'affichage d'un tableau (mais on pourrait aussi prendre l'affichage d'une liste, ou de tout autre élément).</p>
<p>Imaginons que nous récupérons un tableau de la couche métier de notre application. Ce tableau peut par exemple provenir d'une base de données. Pour des raisons de simplification, nous déclarerons ce tableau "en dur" dans le code.</p>
<pre class="brush: php;">$datas[0]['titre'] = 'Les Misérables'; 	$datas[0]['auteur'] = 'Victor Hugo';
$datas[1]['titre'] = 'Candide'; 		$datas[1]['auteur'] = 'Voltaire';
$datas[2]['titre'] = 'Le Cid'; 			$datas[2]['auteur'] = 'Corneille';
$datas[2]['titre'] = 'L\'Avare'; 		$datas[3]['auteur'] = 'Molière';</pre>
<p>A présent, nous voulons afficher le tout dans un tableau. Pour ce faire, modifions notre fichier HTML :</p>
<pre class="brush: xml;">&lt;!---===== tpl_name = main =====---&gt;
&lt;h1&gt;Librairie&lt;/h1&gt;
&lt;table&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th&gt;Titre&lt;/th&gt;
			&lt;th&gt;Auteur&lt;/th&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		${livres}
	&lt;/tbody&gt;
&lt;/table&gt;

&lt;!---===== tpl_name = livre =====---&gt;
&lt;tr&gt;
	&lt;td&gt;${titre}&lt;/td&gt;
	&lt;td&gt;${auteur}&lt;/td&gt;
&lt;/tr&gt;</pre>
<p>Rien qu'en voyant ce code, vous devriez être en mesure de deviner le cheminement. Nous allons concaténer dans une variable <em>${livres}</em> le contenu du sous-template <em>livre</em>, en faisant varier <em>${titre}</em> et <em>${auteur}</em> grâce aux données de notre tableau. </p>
<p>Traduisons donc cela en PHP :</p>
<pre class="brush: php;">&lt;?php 

	require_once('templateEngine.php');

	$datas[0]['titre'] = 'Les Misérables'; 	$datas[0]['auteur'] = 'Victor Hugo';
	$datas[1]['titre'] = 'Candide'; 		$datas[1]['auteur'] = 'Voltaire';
	$datas[2]['titre'] = 'Le Cid'; 			$datas[2]['auteur'] = 'Corneille';
	$datas[2]['titre'] = 'L\'Avare'; 		$datas[3]['auteur'] = 'Molière';

	$tpl = new TemplateEngine();

	foreach($datas as $livre)
	{
		$titre 	= $livre['titre'];
		$auteur = $livre['auteur'];

		$livres .= $tpl-&gt;GetHTMLCode('index.html', 'livre');
	}

	TemplateEngine::Output($tpl-&gt;GetHTMLCode('index.html', 'main'));

?&gt;</pre>
<p>Je ne m'étendrais pas davantage dans les explications, étant donné que le paragraphe précédant est suffisamment explicite.</p>
<p>Une petite remarque cependant, destinée aux développeurs. De nombreux stagiaires ayant travaillé sur mon moteur de templates me posent la : pourquoi ne pas prévoir une méthode nous permettant d'écrire directement dans le HTML une variable sous la forme (par exemple) : <em>${livre['titre']}</em>. Je refuse ce développement, et ce pour une simple raison.</p>
<p>Si nous insérons l'élément du tableau directement dans le HTML, cela nous fera perdre la possibilité d'effectuer une mise en forme sur l'élément avant de l'afficher. Par exemple, si notre tableau contient un élément de type <em>timestamp</em> (à savoir le nombre de secondes écoulées depuis le 1er janvier 1970), il est bien plus ergonomique d'afficher la date au format humain (par exemple 12/03/2008) plutôt que cet entier incompréhensible. La conversion se fait en PHP, et doit donc être dans le fichier <em>index.php</em>. Suivant cette logique, la question n'a plus lieu d'être.</p>
<p>Ainsi s'achève cet exemple. Ainsi que la partie "grand public" (bien que public très restreint) se termine. La suite est réservée aux développeurs souhaitant comprendre les fondations de ce framework, et pourquoi pas le faire évoluer. :)</p>
<h3>Documentation technique</h3>
<p>Si vous êtes encore là, c'est que vous n'avez pas peur de mettre les mains dans le cambouis. Bravo ! :)</p>
<p>Voici donc une petite documentation technique, qui vous permettra d'approfondir davantage le fonctionnement de la classe, au cas où certains commentaires vous sembleraient obscurs. Allons-y donc méthode par méthode. :)</p>
<h4>Constructeur</h4>
<pre class="brush: php;">/**
* Initializes all options of our templates engine.
* @param $localization		Will our application be internationalized (with PHP extension gettext)? Default: no.
* @return void
*/
public function __construct($localization = false)
{
	$this-&gt;files = array();
	$this-&gt;subtemplates = array();
	$this-&gt;localization = $localization;
}</pre>
<p>Ici, rien de particulier à indiquer, si ce n'est l'utilité des variables. L'attribut <em>$files</em> contiendra les fichiers déjà parsés de notre moteur de templates, ce qui permettra une sorte de mise en cache, dans le but d'optimiser les performances. L'attribut <em>subtemplates</em>, quant à lui, permettra de stocker le contenu de chacune des parties, afin de faciliter les traitements ultérieurs internes au moteur. Quant à <em>$localization</em>, cela nous permettra de garder en mémoire si nous devons utiliser l'extension PHP <em>gettext</em> ou non, pour internationaliser notre application.</p>
<h4>Méthode GetHTMLCode</h4>
<pre class="brush: php;">/**
 * Transforms a sub-template to the HTML output.
 * @param $filename	File containing the used sub-template.
 * @param $subtemplate Name of the subtempalte to use.
 * @return string HTML code ready to be displayed.
 */
public function GetHTMLCode($filename, $subtemplate)
{
	$this-&gt;ParseFile($filename);					// Reads the sub-template
	return $this-&gt;Evaluate($filename, $subtemplate);	// Replaces all HTML variables.
}</pre>
<p>Pas grand chose à dire sur cette fonction, les commentaires se suffisant à eux-mêmes. :)</p>
<h4>Méthode ParseFile</h4>
<pre class="brush: php;">/**
 * Reads the file and extracts all sub-templates.
 * @param $filename File to parse.
 * @return void
 */
private function ParseFile($filename)
{
	// If the file has already be parsed, we do not parse it again.
	if($this-&gt;files[$filename] !== true)
	{
		// Retrieving file content.
		$filename = addslashes($filename);
		if(!file_exists($filename))	throw new Exception('File '.$filename.' does not exist.');
		$this-&gt;files[$filename] = file_get_contents($filename);

		// Retrieving all sub-templates from file.
		$this-&gt;GetSubTemplates($filename);
	}
}</pre>
<p>Ce code est légèrement plus complexe. Cette méthode va lire le contenu du fichier <em>$filename</em>, s'il n'a pas déjà été lu. En effet, si on a déjà parsé ce fichier dans le passé, l'attribut <em>$this->files[$filename]</em> vaudra <em>true</em>. Et ainsi, il sera inutile de relire ce fichier, étant donné que nous avons déjà ses sous-parties en mémoire dans l'attribut <em>subtemplates</em>. On ne rentrera pas dans la structure de contrôle.</p>
<p>Afin de simplifier la saisie de l'utilisateur, on échappe automatiquement les slashes. Sans cette ligne, le nom du fichier aurait dû, pour un maximum de compatibilité, contenir des doubles slashes, chose assez rébarbative, il faut bien l'avouer.</p>
<p>Le fichier est alors lu (s'il existe) et son contenu placé dans <em>$this->files</em>.</p>
<h4>Méthode GetSubTemplates</h4>
<p>Comme indiqué dans la documentation utilisateur un peu plus haut dans cet article, chaque fichier sera décomposé en plusieurs sous-parties, appelées sous-templates. Chaque sous-partie sera séparée par : <em><!---===== tpl_name = TEMPLATE_NAME =====---></em>, où TEMPLATE_NAME sera remplacé par un nom unique dans chaque fichier, identifiant de cette partie.</p>
<pre class="brush: php;">/**
 * Retrieving all sub-templates from a given file.
 * @param $filename	File from which to extract sub-templates.
 * @return void
 */
private function GetSubTemplates($filename)
{
	/**
	 * All sub-templates will look like the following:
	 *
	 * 		&lt;!---===== tpl_name = TEMPLATE_NAME =====---&gt;
	 * 		&lt;h1&gt;This is my sub-templates&lt;/h1&gt;
	 *
	 * No closing tags are required.
	 */

	// Splitting the file in sub-templates.
	$explosion = explode('&lt;!---===== tpl_name = ', $this-&gt;files[$filename]);

	// Retrieving the name and content for each sub-template.
	foreach($explosion as $tmp)
	{
		$tmp = 	explode(' =====---&gt;', $tmp);

		$subTemplateName	= $tmp[0];
		$subTemplateContent = $tmp[1];

		// If internationalized, we translate it now with gettext extension.
		$this-&gt;subtemplates[$filename][$subTemplateName] = ($this-&gt;localization ? $this-&gt;Localize($subTemplateContent) : $subTemplateContent);
	}

	// If the file is parsed, we replace the textual content heavy in memory by a single bit.
	$this-&gt;files[$filename] = true;
}</pre>
<p>On découpe notre fichier en sous-templates ligne 18 grâce à la fonction <em>explode</em>. Nous aurons alors dans <em>$explosion</em> l'ensemble de nos sous-templates, contenant encore l'identifiant et le morceau parasite <em>=====---></em>. Qu'à cela ne tienne, nous séparons le nom du contenu grâce à l'explosion de la ligne 23. </p>
<p>Pourquoi ne pas avoir pris une expression régulière pour effectuer cette découpe ? Pour des raisons de performances, un <em>explode</em> étant bien plus rapide qu'une REGEX. D'autre part, cela est bien plus simple à appréhender. Et comme le disait si justement mon prof de mécanique en hypotaupe : <em>on va pas prendre un char d'assaut pour percer un trou de 8 !</em>. Tout est dit. :p</p>
<p>On range alors le contenu de notre template (éventuellement internationalisé grâce à l'extension <em>php_gettext</em> grâce à la méthode <em>Localize</em>) dans le tableau associatif <em>$subtemplates</em>, classé par nom de fichier et nom de template.</p>
<p>Enfin, pour nous assurer que nous ne relirons pas le même fichier deux fois et donc mettre en place une mise en cache de base, nous remplaçons le contenu de notre fichier dans la variable <em>$files</em> relativement coûteux en mémoire par un simple <em>true</em>, codé sur un seul et simple bit.</p>
<h4>Méthode Evaluate</h4>
<p>Cette méthode va nous permettre de remplacer nos variables (de la forme <em>${VARIABLE}</em>) par leur valeur dans notre code HTML.</p>
<pre class="brush: php;">/**
 * Replaces all variables by their content in the HTML file.
 * @param $filename File where to replace the variables.
 * @param $subtemplate Sub-template to use.
 * @return string HTML code ready to be displayed.
 */
private function Evaluate($filename, $subtemplate)
{
	/**
	 * All variables will be written in the HTML code with ${VARIABLE_NAME}.
	 */

	// Retrieving the localized (or not) HTML content, without replacing variables.
	$evaluatedCode = $this-&gt;subtemplates[$filename][$subtemplate];

	// Retrieving all variables names from the sub-template.
	preg_match_all('#\${(.*)}#U', $evaluatedCode, $variables);
	$variables = $variables[1];

	// Replacing the value of each variable.
	foreach ($variables as $variable)
	{
		global $$variable;
		$evaluatedCode = str_replace('${'.$variable.'}', $$variable, $evaluatedCode);
	}

	// Returns the code with variable values inside.
	return $evaluatedCode;
}</pre>
<p>Nous récupérons d'abord tous les noms de variables grâce à l'expression régulière ligne 17.</p>
<p>Puis, pour chaque noms de variables contenus dans <em>$variables</em>, on travaille sur la variable <em>$$variable</em>. On va en fait utiliser une variable du nom la valeur contenue dans <em>$variable</em>. Petit exemple, qui sera sans doute bien plus explicite :</p>
<pre class="brush: php;">$a = 1;
$variable = 'a';
echo $$variable;</pre>
<p>Ici, afficher <em>$$variable</em> est équivalent à afficher <em>$a</em>, donc 1. Pratique n'est-ce pas ? :p</p>
<p>On place donc notre variable en <em>global</em>, ce qui nous permettra de récupérer la valeur de celle-ci lors de son initialisation dans notre script PHP (nous évitant ainsi de devoir la passer en paramètre de notre méthode). Puis, nous remplaçons simplement l'écriture <em>${variable}</em> dans notre code HTML avec la fonction <em>str_replace</em>, plus performant qu'une autre expression régulière.</p>
<h4>Méthode Localize</h4>
<p>Nous n'allons pas nous étendre très profondément sur cette méthode, un futur article traitant de l'internationalisation de nos applications (prévue par le framework : je vous avais dit que c'était un truc sympa ! (-:) étant prévu.</p>
<pre class="brush: php;">/**
 * Translates the content of a sub-template thanks to gettext PHP extension.
 * @param $content Content of the sub-template to translate.
 * @return string Translated content.
 */
private function Localize($content)
{
	/**
	 * All texts to internationalize will be written like the following: _(&quot;Text to translate.&quot;).
	 */

	// Retrieving text to internationalize.
	preg_match_all('#_\(\&quot;(.+)\&quot;\)#Us', $content, $unlocalizedTexts);
	$unlocalizedTexts = $unlocalizedTexts[1];

	// Translating all pieces of text.
	foreach($unlocalizedTexts as $unlocalizedText)
	{
		$content = preg_replace('#_\(\&quot;'.$unlocalizedText.'\&quot;\)#Us', gettext($unlocalizedText), $content);
	}

	// Returns the translated text.
	return $content;
}</pre>
<p>Dans notre template, il est possible d'internationaliser du texte. Celui-ci devra être compris entre les chaînes de caractères : <em>_("Texte à traduire")</em>. Il s'agit de la syntaxe la plus proche de l'extension <em>gettext</em>, d'où ce choix. Cependant, étant donné que la traduction passe par le moteur de templates, vous pouvez modifier celle-ci si elle ne vous plaît pas.</p>
<p>Nous récupérons donc tous les textes à traduire ligne ligne 13, et nous les remplaçons par leurs versions traduites à la ligne 19, en utilisant la méthode <em>gettext</em>, qui cherchera des correspondances dans notre fichier de langue.</p>
<p>Ainsi s'achève les méthodes plutôt techniques. Voyons donc les deux dernières, qui reposeront le cerveau. </p>
<h4>Méthode Output</h4>
<p>Cette méthode va permettre d'afficher le contenu d'une variable, en lui appliquant éventuellement un ou plusieurs traitements.</p>
<pre class="brush: php;">/**
 * Writes a buffer, results of some templates engine treatments. Static function for better performances.
 * @param $buffer Text to write.
 * @return void
 */
public static function Output($buffer)
{
	// You will be able to use here some display functions depending your configuration, as the following:

	// $buffer = utf8_encode($buffer);
	// $buffer = strip_slashes($buffer);

	echo $buffer;
}</pre>
<p>Tout d'abord, on remarque que cette méthode est statique. Et pour cause, une méthode statique est 4 fois plus efficace (environ) qu'une méthode non statique (dynamique ?). </p>
<p>Cette fonction affiche simplement notre variable. C'est une sur-couche de <em>echo</em> en quelques sortes. Pourquoi avoir fait cela ? Simplement pour vous permettre d'encoder en UTF-8, de retirer des slashes en trop, ou que sais-je encore... avant l'affichage. Un comportement un peu similaire aux filtres WordPress pour les connaisseurs. Cela vous évitera donc de manipuler les buffers, à la documentation plutôt énigmatique et à l'utilité contestable, si on pense bien son code. ;)</p>
<h4>Méthode Debug</h4>
<p>Cette méthode se retrouve dans toutes les classes du framework PEJO, et permet d'afficher à l'instant <em>t</em> le contenu de notre classe.</p>
<pre class="brush: php;">/**
 * Used to print the content of our template engine. For debug purposes.
 * @return void
 */
public function Debug()
{
	echo '&lt;pre&gt;';
	print_r($this);
	die('&lt;/pre&gt;');
}</pre>
<p>Cela se passe de commentaires.</p>
<p style="text-align: center;"><a href="http://www.jonathan-petitcolas.com/wp-contentpejo-framework/class/common/templateEngine.php.txt">Télécharger la classe TemplateEngine, moteur de templates du framework PEJO</a></p>
<p>Ainsi s'achève cet article sur le moteur de templates du framework PEJO. N'hésitez surtout pas à me faire part de vos remarques (c'est après tout le but de la publicisation de ce framework) ou de vos questions. Les commentaires sont faits pour ça après tout. ;)</p>
<p>Prochaine étape dans notre découverte de ce framework : l'arborescence normalisée et le routeur de navigation. Patience... :)</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;t=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Jonathan+Petitcolas+%3A+PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29+-+http://tinyurl.com/yem8gt6&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-netvibes">
			<a href="http://www.netvibes.com/share?title=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29&amp;url=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/" rel="nofollow" class="external" title="Submit this to Netvibes">Submit this to Netvibes</a>
		</li>
		<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;title=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29&amp;summary=Le%20PEJO%20framework%20s%C3%A9pare%20toute%20la%20partie%20interface%20utilisateur%20%28en%20HTML%29%20et%20la%20partie%20m%C3%A9tier%20%28en%20PHP%29.%20Pour%20ce%20faire%2C%20une%20classe%20de%20liaison%20entre%20ces%20deux%20composantes%20est%20essentielle%20%3A%20c%27est%20la%20classe%20du%20moteur%20de%20templates%2C%20TemplateEngine.&amp;source=Blog de Jonathan Petitcolas" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;title=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29&amp;srcUrl=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;srcTitle=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29&amp;snippet=Le%20PEJO%20framework%20s%C3%A9pare%20toute%20la%20partie%20interface%20utilisateur%20%28en%20HTML%29%20et%20la%20partie%20m%C3%A9tier%20%28en%20PHP%29.%20Pour%20ce%20faire%2C%20une%20classe%20de%20liaison%20entre%20ces%20deux%20composantes%20est%20essentielle%20%3A%20c%27est%20la%20classe%20du%20moteur%20de%20templates%2C%20TemplateEngine." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;title=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/&amp;title=PEJO+Framework+%3A+moteur+de+templates+%28classe+TemplateEngine%29" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.jonathan-petitcolas.com/pejo-framework-moteur-templates-classe-templateengine/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Générer une chaîne aléatoire en PHP</title>
		<link>http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/</link>
		<comments>http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/#comments</comments>
		<pubDate>Sun, 01 Feb 2009 20:24:21 +0000</pubDate>
		<dc:creator>Jonathan Petitcolas</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[PEJO Framework]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.jonathan-petitcolas.com/?p=756</guid>
		<description><![CDATA[Comment générer une chaîne aléatoire en PHP, pour par exemple attribuer un nouveau mot de passe à un utilisateur ? Une réponse possible sous la forme d'une fonction PHP, extraite du PEJO Framework.]]></description>
			<content:encoded><![CDATA[<p>Voici aujourd'hui une petite fonction (présente dans le PEJO framework) dont je me sers pour générer des chaînes aléatoires :</p>
<pre class="brush: php;">/**
* Generates a random string within a range of given characters.
* @param $length Length of the randomly generated string.
* @return string
*/
function GenerateRandomString($length = 8)
{
	// 67 allowed characters.
	$allowedCharacters = &quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_@$%*&quot;;

	$randomKey = '';

	for($i = 1; $i &lt; = $length; $i++)
	{
		$randomKey .= $allowedCharacters[rand(0, 66)];
	}

	return $randomKey;
}</pre>
<p>Libre à vous par la suite d'inclure (ou d'exclure) certains caractères que vous pourrez considérer comme gênant. Par exemple, si vous voulez insérer une chaîne aléatoire dans un fichier XML, on évitera le symbole chevron. ;)</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;t=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Jonathan+Petitcolas+%3A+G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP+-+http://tinyurl.com/l8cl9x&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-netvibes">
			<a href="http://www.netvibes.com/share?title=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP&amp;url=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/" rel="nofollow" class="external" title="Submit this to Netvibes">Submit this to Netvibes</a>
		</li>
		<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;title=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP&amp;summary=Comment%20g%C3%A9n%C3%A9rer%20une%20cha%C3%AEne%20al%C3%A9atoire%20en%20PHP%2C%20pour%20par%20exemple%20attribuer%20un%20nouveau%20mot%20de%20passe%20%C3%A0%20un%20utilisateur%20%3F%20Une%20r%C3%A9ponse%20possible%20sous%20la%20forme%20d%27une%20fonction%20PHP%2C%20extraite%20du%20PEJO%20Framework.&amp;source=Blog de Jonathan Petitcolas" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;title=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP&amp;srcUrl=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;srcTitle=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP&amp;snippet=Comment%20g%C3%A9n%C3%A9rer%20une%20cha%C3%AEne%20al%C3%A9atoire%20en%20PHP%2C%20pour%20par%20exemple%20attribuer%20un%20nouveau%20mot%20de%20passe%20%C3%A0%20un%20utilisateur%20%3F%20Une%20r%C3%A9ponse%20possible%20sous%20la%20forme%20d%27une%20fonction%20PHP%2C%20extraite%20du%20PEJO%20Framework." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;title=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/&amp;title=G%C3%A9n%C3%A9rer+une+cha%C3%AEne+al%C3%A9atoire+en+PHP" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.jonathan-petitcolas.com/generer-une-chaine-aleatoire-en-php/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Class Chronometer, ou comment benchmarker vos scripts PHP ?</title>
		<link>http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/</link>
		<comments>http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 13:27:25 +0000</pubDate>
		<dc:creator>Jonathan Petitcolas</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[chronomètre]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[PEJO Framework]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.jonathan-petitcolas.com/?p=651</guid>
		<description><![CDATA[Comment benchmarker différents scripts PHP, afin de récupérer un script aux performances optimisées ? En partie grâce à une classe <em>Chronometer</em> que je vous propose de construire ensemble, pas à pas, dans cet article.]]></description>
			<content:encoded><![CDATA[<p>Suite à quelques demandes d'astuces d'optimisation de la part de mes followers sur <a href="http://www.twitter.com/sethpolma">Twitter</a>, voici un premier article sur une série assez longue concernant l'optimisation de vos scripts PHP. Pour ce premier billet, nous n'allons pas réellement examiner les manières d'améliorer les performances de ses scripts, mais plus un outil nous permettant de nous aider à cette tâche.</p>
<p>Nous allons ici créer une classe <em>Chronometer</em>, qui nous permettra facilement de détecter la rapidité d'exécution d'une fonction, et de repérer les différences de performances entre deux fonctions.</p>
<p>Définissons donc tout d'abord notre classe :</p>
<pre class="brush: php;">&lt;?php
     class Chronometer
     {
     }
?&gt;</pre>
<p>Nous allons, pour commencer, définir une méthode <em>Start</em> et <em>Stop</em> qui nous permettront de démarrer ou d'arrêter nos tests. Et, pour bien faire, nous développerons aussi une méthode nous permettant de déterminer la différence entre ces deux temps.</p>
<pre class="brush: php;">public function Start()
{
     $this-&gt;beginTime = microtime(true);
}

public function Stop()
{
     $this-&gt;stopTime = microtime(true);
}

public function GetLength()
{
     return $this-&gt;stopTime - $this-&gt;beginTime;
}</pre>
<p>Que fait donc cette mystérieuse fonction, <em>microtime</em> ? Elle nous retourne simplement le timestamp (nombre de secondes écoulées depuis le 1er janvier 1970) UNIX. Depuis PHP 5, cette fonction prend en argument un booléen, qui nous permet de récupérer ce temps sous forme d'un flottant. En effet, sous PHP 4, le format était un peu étrange : <em>millisecondes</em> <em>secondes</em>. Plutôt moyen pour traiter tout cela correctement, non ?</p>
<p>A présent, nous pouvons détecter facilement la durée de génération de notre page PHP. Mais, nous allons plutôt l'améliorer afin de regarder plus précisément le temps d'exécution d'une fonction. Pour ce faire, la fonction <em>call_user_func_array</em> va nous servir. Cette fonction au si joli nom nous permet d'exécuter une fonction (premier paramètre) prenant un ou plusieurs arguments (deuxième paramètre sous forme d'un tableau). Sachant cela, on peut créer une méthode pour déterminer la durée d'exécution d'une fonction :</p>
<pre class="brush: php;">public function GetExecutionLength($function, $arguments)
{
	if( !is_array($arguments) )	throw new Exception(&quot;&lt;strong&gt;Invalid argument:&lt;/strong&gt; expected &lt;em&gt;array&lt;/em&gt; rather than '.gettype($arguments).' for argument 2 of &lt;em&gt;&quot;.__METHOD__.'&lt;/em&gt;.');

	ob_start();

	$this-&gt;Start();
	call_user_func_array($function, $arguments);
	$this-&gt;Stop();

	ob_end_clean();

	return $this-&gt;GetLength();
}</pre>
<p>On vérifie tout d'abord que le second argument est bien un tableau (condition à suivre obligatoirement pour la fonction <em>call_user_func_array</em>), en levant une exception si tel n'est pas le cas (nous sommes en PHP 5, ce qui implique une gestion plus orientée objet des erreurs). Puis nous démarrons notre chronomètre, exécutons notre fonction, et retournons sa durée d'exécution.</p>
<p>N'en déplaîse à mes étudiants à qui je rabâche régulièrement que les fonctions de <em>buffer</em> peuvent généralement être oubliées (sauf cas bien particuliers) : nous les utilisons ici. <em>ob_start</em> et <em>ob_end_clean</em> sont en effet employées ici afin de ne rien afficher. En effet, si un <em>echo</em> a lieu dans la fonction testée, inutile de nous polluer l'affichage. ;)</p>
<p>A présent, nous avons une durée instantanée d'exécution de fonction. Cependant, celle-ci peut-être complètement erronée. Imaginez que votre Windows Vista décide d'indexer vos fichiers durant votre benchmark. Moins de ressources seront disponibles pour Wamp, et donc le résultat serait faussé. Pour pallier à cela, nous allons procéder à plusieurs fois le même test. C'est simplement de la statistique : plus la population est grande, plus représentatif sera le résultat.</p>
<pre class="brush: php;">public function GetAverageExecutionLength($function, $arguments, $iteration)
{
	$total = 0;

	for( $i = 0 ; $i &lt; $iteration ; $i++ )	$total += $this-&gt;GetExecutionLength($function, $arguments);

	// Average time in milliseconds.
	return $total / $iteration;
}</pre>
<p>Enfin, développons une fonction nous permettant de comparer facilement deux fonctions entre elles.</p>
<pre class="brush: php;">public function GetOptimizationRate($function1, $function2, $arguments, $iteration)
{
	$average1 = $this-&gt;GetAverageExecutionLength($function1, $arguments, $iteration);
	$average2 = $this-&gt;GetAverageExecutionLength($function2, $arguments, $iteration);

	return ( ($average1 - $average2) / min($average1, $average2) ) * 100;
}

public function EchoOptimizationRate($function1, $function2, $arguments, $iteration)
{
	echo $function1.' is '.$this-&gt;GetOptimizationRate($function1,$function2, $arguments, $iteration).' % faster than '.$function2.'.';
}</pre>
<p>La formule du <em>return</em> de la première méthode indique simplement la performance relative (positive ou négative) des deux fonctions, sous forme de pourcentage. Quant à la seconde, cela nous évite d'inverser le nom des deux fonctions, et donc de commettre des contre-sens parfois problématiques.</p>
<p>Essayons donc notre toute nouvelle fonction, en reprenant un résultat déjà connu : les <a href="http://www.jonathan-petitcolas.com/optimisation-php-casting-de-variables-floatvar-float-et-settype/">performances relatives de floatval et du casting direct</a>. Créeons donc le code requis, et effectuons le test.</p>
<pre class="brush: php;">function A($i){ floatval($i); }
function B($i){ (float)$i; }

$c = new Chronometer();
$c-&gt;EchoOptimizationRate('A', 'B', array(3.14), 10000000);</pre>
<p>Plus vous augmenterez le paramètre d'itération, plus le résultat sera proche de la réalité, et plus vous devrez attendre avant de voir le très précieux taux s'afficher. A ce propos, vous pouvez toujours enlever la limite des 30 secondes d'exécution par défaut en écrivant la ligne :</p>
<pre class="brush: php;">set_time_limit(0);</pre>
<p>Avec l'exemple ci-dessus, j'obtiens :</p>
<blockquote><p>A is -11.892284371309 % faster than B.</p></blockquote>
<p>Ce qui confirme (à 2 % près) le résultat déterminé dans le billet de comparaison de ces fonctions.</p>
<p>Pour télécharger cette classe, ainsi que le petit test ci-dessus : <a href='http://www.jonathan-petitcolas.com/wp-content/uploads/2009/01/chronometre.php'>Classe Chronometre</a>.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;t=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Jonathan+Petitcolas+%3A+Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F+-+http://tinyurl.com/8ymbcz&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-netvibes">
			<a href="http://www.netvibes.com/share?title=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F&amp;url=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/" rel="nofollow" class="external" title="Submit this to Netvibes">Submit this to Netvibes</a>
		</li>
		<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;title=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F&amp;summary=Comment%20benchmarker%20diff%C3%A9rents%20scripts%20PHP%2C%20afin%20de%20r%C3%A9cup%C3%A9rer%20un%20script%20aux%20performances%20optimis%C3%A9es%20%3F%20En%20partie%20gr%C3%A2ce%20%C3%A0%20une%20classe%20Chronometer%20que%20je%20vous%20propose%20de%20construire%20ensemble%2C%20pas%20%C3%A0%20pas%2C%20dans%20cet%20article.&amp;source=Blog de Jonathan Petitcolas" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;title=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F&amp;srcUrl=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;srcTitle=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F&amp;snippet=Comment%20benchmarker%20diff%C3%A9rents%20scripts%20PHP%2C%20afin%20de%20r%C3%A9cup%C3%A9rer%20un%20script%20aux%20performances%20optimis%C3%A9es%20%3F%20En%20partie%20gr%C3%A2ce%20%C3%A0%20une%20classe%20Chronometer%20que%20je%20vous%20propose%20de%20construire%20ensemble%2C%20pas%20%C3%A0%20pas%2C%20dans%20cet%20article." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;title=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/&amp;title=Class+Chronometer%2C+ou+comment+benchmarker+vos+scripts+PHP+%3F" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.jonathan-petitcolas.com/class-chronometer-ou-comment-benchmarker-vos-scripts-php/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
