<?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>Gregwar &#187; PHP</title>
	<atom:link href="http://www.gregwar.com/category/php/feed" rel="self" type="application/rss+xml" />
	<link>http://www.gregwar.com</link>
	<description>Web &#38; technologies</description>
	<lastBuildDate>Wed, 28 Dec 2011 19:24:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Manipulation d&#8217;images sous Symfony2</title>
		<link>http://www.gregwar.com/php/manipulation-dimages-sous-symfony2-208</link>
		<comments>http://www.gregwar.com/php/manipulation-dimages-sous-symfony2-208#comments</comments>
		<pubDate>Mon, 08 Aug 2011 21:11:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[gd]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[manipulation]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.gregwar.com/?p=208</guid>
		<description><![CDATA[Dans un article précédent, je montrais une bibliothèque permettant de manipuler des images d&#8217;une manière un peu particulière, mais à mon sens intéréssant. Ici, nous allons parler de la façon dont cette bibliothèque peut s&#8217;intégrer à Symfony2.
Je travaille actuellement sous Symfony2 et j&#8217;ai été amené à manipuler des images dans une application que je développe. [...]]]></description>
			<content:encoded><![CDATA[<p>Dans un <a href="http://www.gregwar.com/programmation/manipulez-vos-images-avec-php-198">article précédent</a>, je montrais une <a href="https://github.com/Gregwar/Image">bibliothèque</a> permettant de manipuler des images d&#8217;une manière un peu particulière, mais à mon sens intéréssant. Ici, nous allons parler de la façon dont cette bibliothèque peut s&#8217;intégrer à Symfony2.</p>
<p>Je travaille actuellement sous Symfony2 et j&#8217;ai été amené à manipuler des images dans une application que je développe. Ayant déjà sous la main ma propre classe de gestion d&#8217;images, j&#8217;ai décidé de l&#8217;intégrer au framework à l&#8217;aide d&#8217;un Bundle. Comme vous pourrez le remarquer si vous jetez un oeil au <a href="https://github.com/Gregwar/ImageBundle">projet git correspondant</a>, l&#8217;intégration de la classe dans un bundle Symfony2 ne nécéssite pas beaucoup de code supplémentaire.</p>
<h2>Installation</h2>
<p>Commencez par placer le dépôt git dans vos dépendances et clonez-le. Ajoutez alors l&#8217;espace de nom Gregwar à votre <em>app/autoloader.php</em> :</p>
<pre class="brush: php">&#039;Gregwar&#039; =&gt; __DIR__.&#039;/../vendor/gregwar-image/bundle/&#039;,</pre>
<p>Une fois fait, ajouter le bundle à votre <em>app/AppKernel.php </em>:</p>
<pre class="brush: php">...
public function registerBundles()
{
$bundles = array(
...
new Gregwar\ImageBundle\GregwarImageBundle(),
...
);
...</pre>
<p>Il ne vous reste plus qu&#8217;à ajouter à votre fichier de configuration (ex: <em>app/config/config.yml</em>) :</p>
<pre class="brush: bash">gregwar_image: ~</pre>
<p>Puis, créez le dossier web/cache et donnez les permissions à apache d&#8217;écrire dedans</p>
<pre class="brush: bash">mkdir web/cache
chmod 777 web/cache</pre>
<p>Si vous voulez utiliser un autre nom, précisez le dans la configuration:</p>
<pre class="brush: bash">gregwar_image:
   cache_dir: mes_fichies_caches</pre>
<h2>Services fournis</h2>
<p>Ce Bundle Symfony2 vous fournit principalement deux choses:</p>
<ol>
<li>Un service <em>image.handling</em> permettant d&#8217;utiliser la classe <em>Gregwar\Image</em> avec l&#8217;injection de dépendance;</li>
<li>Un helper twig, qui vous permet d&#8217;utiliser les fonctionnalités de <em>Gregwar\Image </em>directement dans vos templates</li>
</ol>
<p>Je ne m&#8217;attarderais pas sur le premier point, vous l&#8217;aurez vite compris, vous pouvez écrire des lignes de la forme:</p>
<pre class="brush: php">$this-&gt;get(&#039;image.handling&#039;)-&gt;open(&#039;linux.jpg&#039;)
    -&gt;grayscale()
    -&gt;rotate(12)
    -&gt;save(&#039;out.jpg&#039;)</pre>
<p>Dans vos contrôleurs ou dans n&#8217;importe quel classe ayant accès aux services, ce qui peut s&#8217;avérer pratique !</p>
<p>La partie intéréssante repose sur l&#8217;helper Twig, qui peut être très utile en tirant profit du dossier de cache. Le bundle enregistre la fonction twig<em> image()</em> qui fournit la même API qu&#8217;avec la classe <em>Gregwar\Image</em>. Un exemple:</p>
<pre class="brush: html">&lt;!-- template.html.twig --&gt;
&lt;img src=&quot;{{ image(&#039;linux.png&#039;).resize(&#039;30%&#039;).rotate(-12).jpeg }}&quot; alt=&quot;&quot; /&gt;</pre>
<p>Le résultat sera alors l&#8217;adresse du fichier de cache hashé. Petit bonus: cet helper fait lui-même appel à l&#8217;helper <em>asset()</em> pour le chemin du fichier de cache.</p>
<p>Vous pouvez également profiter de l&#8217;API de la classe image:</p>
<pre class="brush: html">linux.png a une largeur de {{ image(&#039;linux.png&#039;).width }} px</pre>
<p><a href="https://github.com/Gregwar/ImageBundle">Dépôt Gregwar/ImageBundle sur Github</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregwar.com/php/manipulation-dimages-sous-symfony2-208/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manipulez vos images avec PHP</title>
		<link>http://www.gregwar.com/programmation/manipulez-vos-images-avec-php-198</link>
		<comments>http://www.gregwar.com/programmation/manipulez-vos-images-avec-php-198#comments</comments>
		<pubDate>Wed, 03 Aug 2011 20:28:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmation]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[manipulation]]></category>

		<guid isPermaLink="false">http://www.slashed.fr/?p=198</guid>
		<description><![CDATA[La classe Image présenté dans un article précédent a bien évolué depuis le temps. Elle est maintenant disponible dans un dépôt github dédié et permet de manipuler des images.
Comme l&#8217;explique le README, il est possible d&#8217;effectuer des actions sur vos images facilement, en utilisant le principe de chaînage de fonctions:
&#60;?php
require_once(&#039;../lib/Gregwar/Image.php&#039;);

use Gregwar\Image;

// Redimensionnement dans une boîe [...]]]></description>
			<content:encoded><![CDATA[<p>La <a href="http://www.slashed.fr/php/maitrisez-la-taille-de-vos-images-40">classe Image</a> présenté dans un article précédent a bien évolué depuis le temps. Elle est maintenant disponible dans un <a href="https://github.com/Gregwar/Image">dépôt github</a> dédié et permet de manipuler des images.</p>
<p>Comme l&#8217;explique le README, il est possible d&#8217;effectuer des actions sur vos images facilement, en utilisant le principe de chaînage de fonctions:</p>
<pre class="brush: php">&lt;?php
require_once(&#039;../lib/Gregwar/Image.php&#039;);

use Gregwar\Image;

// Redimensionnement dans une boîe de 100x100 et passage en négatif
Image::open(&#039;img/test.png&#039;)
    -&gt;resize(100, 100)
    -&gt;negate()
    -&gt;save(&#039;out.jpg&#039;);</pre>
<p>Ou encore, par exemple:</p>
<pre class="brush: php">&lt;?php
require_once(&#039;../lib/Gregwar/Image.php&#039;);

use Gregwar\Image;

// Fusion de deux images
Image::open(&#039;img/test.png&#039;)
    -&gt;merge(Image::open(&#039;img/test2.jpg&#039;)-&gt;cropResize(100, 100))
    -&gt;save(&#039;out.jpg&#039;);
</pre>
<p>Et même, dans le cas de l&#8217;utilisation du cache:</p>
<pre class="brush: php">
&lt;img src=&quot;&lt;?php echo Image::open(&#039;img/test.png&#039;)
    -&gt;resize(&#039;26%&#039;)
    -&gt;sepia()
    -&gt;jpeg(); // Fichier de cache généré à la volée ?&gt;&quot; /&gt;
</pre>
<p>Ce principe, implémenté à l&#8217;aide d&#8217;un simple &laquo;&nbsp;<em>return $this;</em>&nbsp;&raquo; en fin des fonctions, permet une bonne lisibilité du code et des opérations effectuées sur un objet.</p>
<h2>L&#8217;optimisation des opérations</h2>
<p>La particularité de cette classe et que lorsque vous apellez une méthode de manipulation sur un des objets image, aucun traitement n&#8217;est réellement effectué. En fait, la méthode et ses arguments sont stockés dans un tableau d&#8217;opérations à effectuer.</p>
<p>Si vous apellez <em>save() </em>explicitement, les opérations sont réellement appliquées, les resources nécéssaires ouvertes et traitées.</p>
<p>En revanche, si vous utilisez <em>jpeg()</em>, <em>png()</em> ou <em>gif()</em>, -c&#8217;est à dire que vous souhaitez utiliser une génération à la volée avec du cache- l&#8217;objet calculera alors un hash à partir de toutes les opérations demandées, du nom du type et de la date de modification du fichier d&#8217;image source. Ce hash est alors utilisé pour chercher un fichier dans le répertoire de cache (par exemple images/cache/1/4/a/d/2/98098ad29e294f.jpg) si ce fichier existe, la fonction retournera directement son nom, autrement elle lancera la compilation des opérations.</p>
<p>De cette façon, les opérations ne seront appliquées qu&#8217;au premier chargement de la page, la dehxuième fois, le calcul du hash suffira pour trouver le fichier de cache correspondant sans même ouvrir l&#8217;image source !</p>
<h2>Dans les coulisses de la classe : la méta-programmation</h2>
<p>Contrairement à la version présentée précédemment, les opérations qu&#8217;il est possible d&#8217;effectuer se sont multipliées. Il n&#8217;était plus envisageable d&#8217;écrire manuellement une fonction publique servant à placer l&#8217;appel de fonction dans le tableau des opérations et une fonction permettant de réellement effectuer l&#8217;opération. Il a fallu ruser pour éviter d&#8217;écrire du code extremement répetitif, et voici ce que ça donne:</p>
<pre class="brush: php">public function __call($func, $args)
{
    $reflection = new \ReflectionClass(get_class($this));
    $methodName = &#039;_&#039;.$func;

    if ($reflection-&gt;hasMethod($methodName)) {
        $method = $reflection-&gt;getMethod($methodName);

        if ($method-&gt;getNumberOfRequiredParameters() &gt; count($args))
            throw new \InvalidArgumentException(&#039;Not enough arguments given for &#039;.$func);

        $this-&gt;addOperation($methodName, $args);
        return $this;
    }   

    throw new \BadFunctionCallException(&#039;Invalid method: &#039;.$func);
}</pre>
<p>Cette technique fait appel à la fonction magique __call() et la la reflection. Le principe est simple: lorsqu&#8217;une fonction n&#8217;existe pas, __call() est apellée avec en argument le nom de la fonction et ses arguments. L&#8217;implémentation de __call vérifie alors que la méthode _$methode existe (le même nom, préfixé d&#8217;un _), si elle existe, elle vérifie que le nombre d&#8217;argument est bon et l&#8217;ajoute au tableau des opérations.</p>
<p>De ce fait, l&#8217;implémentation de negate() tient simplement en une ligne:</p>
<pre class="brush: php">public function _negate()
{
    imagefilter($this-&gt;gd, IMG_FILTER_NEGATE);
}</pre>
<p>Ces lignes suffisent pour faire marcher l&#8217;appel à <em>-&gt;negate()</em> et son ajout au tableau d&#8217;opération.</p>
<p>Quand au rendu des effets, il tient en seulement trois lignes, à l&#8217;aide d&#8217;une boucle itérant sur les opérations et de l&#8217;utilisation de call_user_func_array, qui permet d&#8217;apeller une méthode au nom variable:</p>
<pre class="brush: php">foreach ($this-&gt;operations as $operation) {
    call_user_func_array(array($this, $operation[0]), $operation[1]);
}</pre>
<h2>Contribuez</h2>
<p>Si cette classe vous intéresse, n&#8217;hésitez pas à contribuer !</p>
<p>Rendez-vous sur <a href="https://github.com/Gregwar/Image">https://github.com/Gregwar/Image</a> pour forker le projet, n&#8217;hésitez également pas à proposez vos améliorations en faisant des pull requests ou en ouvrant des issues.</p>
<p>Le code est sous license MIT.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregwar.com/programmation/manipulez-vos-images-avec-php-198/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Maitrisez la taille de vos images</title>
		<link>http://www.gregwar.com/php/maitrisez-la-taille-de-vos-images-40</link>
		<comments>http://www.gregwar.com/php/maitrisez-la-taille-de-vos-images-40#comments</comments>
		<pubDate>Mon, 25 Jan 2010 21:54:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[gd]]></category>
		<category><![CDATA[image]]></category>

		<guid isPermaLink="false">http://www.slashed.fr/?p=40</guid>
		<description><![CDATA[Voici une solution générique au problème souvent rencontré de la gestion de la taille des images. En effet, et comme vous le savez, redimensionner un objet &#60;img&#62; a tendance à faire charger à l&#8217;utilisateur une image beaucoup trop grosse pour ce qu&#8217;il en verra, de plus les navigateurs n&#8217;ont pas toujours de modules d&#8217;anti-aliasing. La [...]]]></description>
			<content:encoded><![CDATA[<p>Voici une solution générique au problème souvent rencontré de la gestion de la taille des images. En effet, et comme vous le savez, redimensionner un objet &lt;img&gt; a tendance à faire charger à l&#8217;utilisateur une image beaucoup trop grosse pour ce qu&#8217;il en verra, de plus les navigateurs n&#8217;ont pas toujours de modules d&#8217;anti-aliasing. La solution bien connue est de générer, coté serveur, des images de la bonne dimension (qu&#8217;il s&#8217;agisse de miniature ou pas).</p>
<p>J&#8217;ai écrit cette classe pour essayer de me débarasser de ce problème ennuyeux, voici comment elle fonctionne.</p>
<h2>Chargement d&#8217;une image</h2>
<p>Tout d&#8217;abord, il faut instancier l&#8217;image, puis lui dire quel fichier charger</p>
<pre class="brush: php">$i = new Image;
$i-&gt;fromFile(&quot;image.jpg&quot;);
</pre>
<p>Le paramètre peut aussi être passé directement dans le constructeur, afin de gagner de la place:</p>
<pre class="brush: php">$i = new Image(&quot;image.jpg&quot;);
</pre>
<h2>Appliquer une redimension</h2>
<p>Il existe ensuite plusieurs façon de redimensionner l&#8217;image, voici des exemples pour mieux comprendre.</p>
<div id="attachment_41" class="wp-caption aligncenter" style="width: 210px"><a href="http://www.slashed.fr/wp-content/uploads/2010/01/logo.jpg"><img class="size-full wp-image-41" title="logo" src="http://www.slashed.fr/wp-content/uploads/2010/01/logo.jpg" alt="" width="200" height="92" /></a><p class="wp-caption-text">Image d&#39;origine, 200x92</p></div>
<div id="attachment_43" class="wp-caption aligncenter" style="width: 310px"><span style="text-decoration: underline;"><a href="http://www.slashed.fr/wp-content/uploads/2010/01/logo_resize_300.jpg"><img class="size-full wp-image-43" title="logo_resize_300" src="http://www.slashed.fr/wp-content/uploads/2010/01/logo_resize_300.jpg" alt="" width="300" height="300" /></a></span><p class="wp-caption-text">$i-&gt;;resize(300,200), réduit éventuellement l&#39;image mais ne l&#39;agrandit jamais (pratique pour les miniatures)</p></div>
<div id="attachment_45" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.slashed.fr/wp-content/uploads/2010/01/logo_scaleResize_300.jpg"><img class="size-full wp-image-45" title="logo_scaleResize_300" src="http://www.slashed.fr/wp-content/uploads/2010/01/logo_scaleResize_300.jpg" alt="" width="300" height="300" /></a><p class="wp-caption-text">$i-&gt;scaleResize(300,200), redimensionne l&#39;image en gardant le ratio de maniere a la faire tenir dans la place attribuée</p></div>
<div id="attachment_46" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.slashed.fr/wp-content/uploads/2010/01/logo_forceResize_300.jpg"><img class="size-full wp-image-46" title="logo_forceResize_300" src="http://www.slashed.fr/wp-content/uploads/2010/01/logo_forceResize_300.jpg" alt="" width="300" height="300" /></a><p class="wp-caption-text">$i-&gt;forceResize(300,200), force l&#39;image a faire exactement la taille donnée, sans que le ratio ne compte (peut déformer)</p></div>
<div id="attachment_47" class="wp-caption aligncenter" style="width: 270px"><a href="http://www.slashed.fr/wp-content/uploads/2010/01/logo_forceResize_120.jpg"><img class="size-full wp-image-47" title="logo_forceResize_120" src="http://www.slashed.fr/wp-content/uploads/2010/01/logo_forceResize_120.jpg" alt="" width="260" height="120" /></a><p class="wp-caption-text">$i-&gt;forceResize(null, 120), force l&#39;image a faire 120 de hauteur, le ratio sera gardé</p></div>
<div id="attachment_51" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.slashed.fr/wp-content/uploads/2010/01/logo_cropResize_150_100.jpg"><img class="size-full wp-image-51" title="logo_cropResize_150_100" src="http://www.slashed.fr/wp-content/uploads/2010/01/logo_cropResize_150_100.jpg" alt="" width="150" height="69" /></a><p class="wp-caption-text">$i-&gt;cropResize(150,100), fonctionne comme resize mais coupe l&#39;espace blanc autour de l&#39;image (revient à limiter la largeur et la hauteur)</p></div>
<h2>Chaîne d&#8217;opération</h2>
<p>Notons que tout l&#8217;interêt du code que je présente ici est que les opérations ne sont pas appliquées. En effet apres une ouverture (<em>fromFile</em>) et une redimension (<em>resize&#8230;</em>) la classe n&#8217;a strictement rien fait d&#8217;autre que d&#8217;enregistrer tout ce qui lui est demandé. Il est alors possible de la forcer à effectuer les opérations et à sauvegarder l&#8217;image avec la fonction <em>save()</em> (voir plus bas). Mais l&#8217;option la plus interessante est de lui demander d&#8217;utiliser son système de cache de manière à tout gérer automatiquement.</p>
<p>En appellant la méthode <em>cacheFile()</em>, la classe commencera à calculer un hash de tout ce qui lui est demandé (les opérations, le fichier d&#8217;origine, le format demandé etc.) et générera alors un nom de fichier de cache. Si ce fichier existe, elle ne fera strictement rien d&#8217;autre que de retourner le nom de ce fichier. Si il n&#8217;existe pas, elle appellera <em>save</em><em>()</em>, la fonction permettant de générer l&#8217;image en la sortant dans le fichier de cache.</p>
<p>Les fonctions <em>jpeg(), gif() et png()</em> sont des raccourcis de <em>cacheFile()</em>.</p>
<h2>Exemples et raccourcis</h2>
<p>Voici un exemple d&#8217;execution détaillé:</p>
<pre class="brush: php">//Créé l&#039;instance
$i = new Image;
//Charge l&#039;image &quot;image.jpg&quot;
$i-&gt;fromFile(&quot;image.jpg&quot;);
//Utilise une redimension non-agrandissante dans une boite 300x200
$i-&gt;resize(300, 200);
//Applique les modifications ou alors récupere le cache correspondant
// $file contiendra le nom du fichier cache obtenu
$file = $i-&gt;jpeg();
</pre>
<p>Et la version raccourcie, grace à la définition de la fonction <em>Image()</em> et des <em>return $this;</em> Imaginez que vous écriviez une gallerie photo dans laquelle vous souhaitez mettre des miniatures en 120&#215;120:</p>
<pre class="brush: html">&lt;img src=&quot;&lt;? echo Image($file)-&gt;resize(120,120)-&gt;jpeg();  ?&gt;&quot; alt=&quot;&quot; /&gt;
</pre>
<p>L&#8217;interêt est de mêler étroitement la simplicité d&#8217;écriture et les performances. Lorsque le fichier de cache existe déja, l&#8217;utilisation de la classe Image ne nécessite que le calcul d&#8217;un hash et quelques vérifications. Une fois le dossier de cache correctement configuré, cette ligne suffira a maitriser le rendu des images.</p>
<h2>Autre utilisation, rendu dans un fichier</h2>
<p>Nous voudrons parfois pouvoir utiliser ce système non pas à l&#8217;affichage, mais à un instant précis du code. Pour cela vous pouvez utiliser la fonction <em>save</em><em>($fichier, $format=&nbsp;&raquo;jpg&nbsp;&raquo;, $qualite=80)</em>.</p>
<pre class="brush: php">//Ouverture de l&#039;image
$i = new Image($file_name);
//Utilise une redimension non-agrandissante dans une boite 120x120
$i-&gt;resize(120, 120);
//Sauvegarde le résultat dans le répertoire des miniatures (thumb)
$i-&gt;save($thumb_dir.$file_name, &quot;jpg&quot;);
</pre>
<p>Pour conclure voici les sources de la classe en question:<br />
<a href="http://www.slashed.fr/source/Image/Image.class.phps" target="_blank">Voir le code source de la classe Image</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregwar.com/php/maitrisez-la-taille-de-vos-images-40/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Fonctionnalités obscures de PHP</title>
		<link>http://www.gregwar.com/php/fonctionnalites-obscures-ph-25</link>
		<comments>http://www.gregwar.com/php/fonctionnalites-obscures-ph-25#comments</comments>
		<pubDate>Thu, 21 Jan 2010 18:45:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[iterable]]></category>
		<category><![CDATA[object]]></category>

		<guid isPermaLink="false">http://www.slashed.fr/?p=25</guid>
		<description><![CDATA[Un petit article pour parler des fonctionalités &#171;&#160;obscures&#160;&#187; de PHP. J&#8217;ai trouvé en effet mal documenté certains features qui me semblent intéréssant du coté des interfaces. Je vous laisse regarder la doc si vous n&#8217;avez pas envie de lire l&#8217;article en cliquant ici.
Des pseudos-tableaux
Il est en effet possible d&#8217;utiliser la syntaxe suivante (utiliser des objets [...]]]></description>
			<content:encoded><![CDATA[<p>Un petit article pour parler des fonctionalités &laquo;&nbsp;obscures&nbsp;&raquo; de PHP. J&#8217;ai trouvé en effet mal documenté certains features qui me semblent intéréssant du coté des interfaces. Je vous laisse regarder la doc si vous n&#8217;avez pas envie de lire l&#8217;article en <a href="http://fr2.php.net/manual/en/reserved.interfaces.php" target="_blank">cliquant ici</a>.</p>
<h2>Des pseudos-tableaux</h2>
<p>Il est en effet possible d&#8217;utiliser la syntaxe suivante (utiliser des objets comme des arrays):</p>
<pre class="brush: php">$m = new Machin;
$m[&quot;test&quot;] = 12</pre>
<p>Ca peut parraitre bizarre, mais c&#8217;est parfois pratique. Voici une petite description de l&#8217;utilisation de ce feature:</p>
<pre class="brush: php">class Machin implements ArrayAccess {
	//Est-ce que isset($obj[$var] ?
	public function offsetExists($var) {
		return true;
	}
	//Quelle est la valeur de $obj[$var] ?
	public function offsetGet($var) {
		return 42;
	}
	//Définition de la valeur $obj[$var]
		public function offsetSet($var, $val) {
		echo &quot;$var = $val!\n&quot;;
	}
	//Appel à unset($var[$obj])
	public function offsetUnset($var) {
		echo &quot;removing $var\n&quot;;
	}
}
$m = new Machin;
if (isset($m[&quot;toto&quot;])) { //true
	echo $m[&quot;toto&quot;].&quot;\n&quot;;   //42
	$m[&quot;truc&quot;] = &quot;bidule&quot;;  //truc = bidule!
	unset($m[&quot;blork&quot;]);     //removing blork
}</pre>
<p>Il est par exemple plus facile de créer un système de session customizées, enfin, laissez votre imagination tourner je pense que vous aurez bien plus d&#8217;idées que moi, sachant que chaque acces au tableau provoque un appel de fonction et peut donc être dynamique (pourquoi pas requêter un SGBD). Il est aussi possible de &laquo;&nbsp;mapper&nbsp;&raquo; un serveur memcache par exemple, créer une classe qui permettra d&#8217;utiliser le serveur de cache comme un simple tableau.</p>
<h2>Des objets itérables</h2>
<p>Vous qui utilisez des templates php à tour de bras vous devez apprécier fortement l&#8217;instruction <em>foreach</em>. Je vous laisse donc découvrir ce que vous pouvez faire en implémentant <em>Iterator</em>:</p>
<ul>
<li>function <em>rewind() </em>: retourne à la premiere position de l&#8217;itération</li>
<li>function <em>current()</em> : retourne l&#8217;élément courant</li>
<li>function <em>key()</em> : retourne la clé courante</li>
<li>function <em>next()</em> : passe à l&#8217;élément suivant</li>
<li>function <em>valide()</em> : retourne vrai si l&#8217;élément est valide (permet d&#8217;arrêter l&#8217;itération)</li>
</ul>
<p>Il est alors possible de faire:</p>
<pre class="brush: php">$trucs = new Trucs;
foreach ($trucs as $t) {
	//Faire quelque chose avec $t
}</pre>
<p>Ce qui peut s&#8217;avérer pratique lorsque la sémantique de votre objet est justement d&#8217;être un containers. Pour plus de détails je vous laisse consulter la <a href="http://fr2.php.net/manual/en/class.iterator.php" target="_blank">documentation</a>.</p>
<h2>Appels de méthodes enchaînés</h2>
<p>Ce n&#8217;est pas vraiment quelque chose d&#8217;obscur ou de caché mais plus une astuce. Lorsque vous souhaitez appeller plusieurs fonctions sur le même objet, et que ces fonctions ne retournent rien, rien ne coute d&#8217;ajouter un <em>return $this;</em> à la fin de la fonction en question, ce qui vous permet d&#8217;enchainer les appels sur la  même ligne. Un petit exemple:</p>
<pre class="brush: php">class Query {
	private $sql;
	public function __construct() {
		$this-&gt;sql = &quot;SELECT * FROM &quot;;
	}
	public function from($table) {
		$this-&gt;sql.= &quot;`$table` &quot;;
		return $this;
	}
	public function where($where) {
		$this-&gt;sql.= &quot;WHERE $where &quot;;
		return $this;
	}
	public function exec() {
		echo &quot;Requete: &quot;.$this-&gt;sql.&quot;\n&quot;;
	}
}

$q = new Query;
$q-&gt;from(&quot;users&quot;)-&gt;where(&quot;id=12&quot;)-&gt;exec();
//Requete: SELECT * FROM `users` WHERE id=12</pre>
<p>L&#8217;exemple est très caricatural, mais on voit vite les avantages d&#8217;un tels procedé. Cette syntaxe est largement utilsiée par certaines libs comme <a href="http://www.doctrine-project.org/" target="_blank">Doctrine</a>.</p>
<h2>Les fonctions magiques</h2>
<p>Chaque classes définit ses propres méthodes, mais peut aussi définir des méthodes dynamiquement. Lorsqu&#8217;une méthode n&#8217;existe pas, php appelle la fonction <em>__call()</em> si elle existe. un petit exemple:</p>
<pre class="brush: php">class User {
	public function __call($func, $params) {
		if (substr($func, 0, 2) == &quot;by&quot;) {
			$name = trim(strtolower(substr($func, 2)));
			$param = $params[0];
			echo &quot;SELECT * FROM users WHERE `$name`=\&quot;&quot;.$params[0].&quot;\&quot;&quot;;
		}
	}
}
$u = new User;
$u-&gt;byName(&quot;toto&quot;);
//SELECT * FROM users WHERE `name`=&quot;toto&quot;</pre>
<p>Encore très simplifié, mais je pense que le concept transparait bien, les fonctions peuvent être parfois plus parlantes que des noms d&#8217;arguments.</p>
<p>A noter qu&#8217;il existe d&#8217;autres fonctions magiques, comme celles permettant d&#8217;acceder à des pseudos-propriétés (<em>$u-&gt;name</em> par exemple) de manière dynamique (avec un appel de fonction). Là aussi, <a href="http://fr.php.net/manual/en/language.oop5.overloading.php" target="_blank">jetez un oeil au manuel</a>.</p>
<h2>Le mécanisme de réflexion</h2>
<p>Un autre aspect sur lequele je ne vais pas m&#8217;éterniser, le <a href="http://fr2.php.net/manual/en/book.reflection.php" target="_blank">mécanisme de réflexion</a>. Comme tous les langages de haut niveau, PHP peut s&#8217;analyser lui même, il est ainsi possible de savoir dynamiquement si une fonction existe, si une classe implémente telle ou telle interface, dans quel fichier elle est définie ou encore le noms et les valeurs des propriétés statiques.</p>
<p>Voila je m&#8217;arrête ici, j&#8217;éspère vous avoir donné quelques idées pour vos projets. La souplesse du langage permet de faire beaucoup de choses assez sympas qui rendent le code (celui qui utilise vos classes bizarres!) plus lisible et facile à maintenir, donc à vos claviers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregwar.com/php/fonctionnalites-obscures-ph-25/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

