<?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>Not My Idea &#187; Injection de dépendances</title>
	<atom:link href="http://www.notmyidea.org/article/tag/injection-de-dependances/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.notmyidea.org</link>
	<description>Carnets Web d&#039;Alexis Métaireau</description>
	<lastBuildDate>Tue, 20 Jul 2010 10:07:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Injection de dépendances &#8211; Utilisation du SpiralDi Container</title>
		<link>http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/</link>
		<comments>http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 09:05:38 +0000</pubDate>
		<dc:creator>Alexis Metaireau</dc:creator>
				<category><![CDATA[Architecture logicielle]]></category>
		<category><![CDATA[php-fr]]></category>
		<category><![CDATA[Injection de dépendances]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[spiral]]></category>

		<guid isPermaLink="false">http://www.notmyidea.org/?p=189</guid>
		<description><![CDATA[Cet article est également disponible en version anglaise. Un grand merci à Frédéric Sureau pour son travail de traduction.
Suite à mon précédent article, j&#8217;ai continué à travailler sur l&#8217;injecteur de dépendances de Spiral, que je viens de publier dans une version standalone. 
Voici un tour d&#8217;horizon des fonctionnalités apportées par SpiralDi, ainsi que quelques exemples [...]]]></description>
			<content:encoded><![CDATA[<p class="info">Cet article est également <a href="http://www.notmyidea.org/article/en-introduction-to-spiral-dependency-injection-container-in-php">disponible en version anglaise</a>. Un grand merci à Frédéric Sureau pour son travail de traduction.</p>
<p>Suite à mon <a href="http://www.notmyidea.org/article/dependency-injection-singleton-design-pattern-ioc-dendencies-dependences/">précédent article</a>, j&#8217;ai continué à travailler sur l&#8217;injecteur de dépendances de <a href="http://bitbucket.org/ametaireau/spiral/wiki/Home">Spiral</a>, que je viens de publier dans une <a href="http://bitbucket.org/ametaireau/spiraldi/">version <em>standalone</em></a>. </p>
<p>Voici un tour d&#8217;horizon des fonctionnalités apportées par SpiralDi, ainsi que quelques exemples d&#8217;utilisation.<br />
<span id="more-189"></span></p>
<h2>Table des matières</h2>
<div class="toc">
<ol>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-tour-dhorizon">Tour d&#8217;horizon</a></li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-principes">Principes</a>
<ol>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-portee-des-services-scopes">Portée des services (Scopes)</a></li>
</ol>
</li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-utilisation-avancee">Utilisation &laquo;&nbsp;avancée&raquo;&nbsp;</a>
<ol>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-utilisation-des-references-et-des-methodfactory">Utilisation des Références et des <em>MethodFactory</em></a></li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-heritage-et-surcharge-de-services">Héritage et surcharge de services</a></li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-container-aware">Container Aware</a></li>
</ol>
</li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-factories">Factories</a></li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-telechargez-le">Téléchargez le ! </a>
<ol>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-via-le-depot-mercurial">Via le dépôt mercurial</a></li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-via-les-archives">Via les archives</a></li>
</ol>
</li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-et-ailleurs">Et ailleurs ?</a></li>
<li><a href="http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/#toc-lectures-interessantes">Lectures intéressantes</a></li>
</ol>
</div>
<h2 id="toc-tour-dhorizon">Tour d&#8217;horizon</h2>
<p>SpiralDi arrive avec son lot de nouveautés, pour certaines inspirées de l&#8217;excellent framework Java Spring. Il est désormais possible, en vrac, de:</p>
<ul>
<li>Utiliser des <em>factories</em> pour renseigner les valeurs des parametres (pratique pour la configuration)</li>
<li>Utiliser un système d&#8217;héritage, pour alléger les fichiers de configuration</li>
<li>Utiliser des <em>Factories</em> pour résoudre les services</li>
<li>Injecter directement le conteneur à certains services, dits <em>ContainerAware</em></li>
</ul>
<p>Mais peut être que ça ne vous parles pas trop, nous y reviendrons tout à l&#8217;heure.</p>
<h2 id="toc-principes">Principes</h2>
<p>Si vous n&#8217;êtes pas à l&#8217;aise avec le principe d&#8217;inversion de contrôle, je vous conseille d&#8217;aller lire mon <a href="http://www.notmyidea.org/article/dependency-injection-singleton-design-pattern-ioc-dendencies-dependences/">introduction sur l&#8217;injection de dépendances</a>.</p>
<p>L&#8217;utilisation d&#8217;un conteneur léger se fait toujours en deux étapes:</p>
<ul>
<li>La description et le renseignement du <em>schéma</em> de services qui pourront être utilisés par la suite</li>
<li>la demande de résolution de ces derniers, via le <em>conteneur</em></li>
</ul>
<p>SpiralDi fournit plusieurs manières de décrire le <em>Schema</em>. La plus appropriée est surement l&#8217;XML, mais il est également possible de passer via du PHP si cela vous semble plus pratique. Nous prendrons ici l&#8217;exemple du XML. Voici un fichier de description assez simple, qui décrit deux services:</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;db&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Database&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;localhost&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;root&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;password&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constructor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;user&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;User&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;setDb&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;service&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;db&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/method<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Une fois le fichier écrit, il faut le transformer dans un format compréhensible par SpiralDi: le Schema.</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$builder</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SpiralDi_SchemaBuilder_Xml<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFileName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;schema.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$schema</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$builder</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">buildSchema</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Nous pouvons désormais exploiter notre Schema. La première utilité d&#8217;un Schéma est d&#8217;être utilisé pour résoudre nos objets. Nous verrons un peu plus tard qu&#8217;il peut avoir d&#8217;autres utilités. Passons donc le <em>Schema</em> au <em>Conteneur</em>:</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// construction du conteneur</span><br />
<span style="color: #000088;">$container</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SpiralDi_Container_Default<span style="color: #009900;">&#40;</span><span style="color: #000088;">$schema</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// récupération du service souhaité</span><br />
<span style="color: #000088;">$myUser</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user</span><span style="color: #339933;">;</span></div></div>
<p>Plutôt sympa non? Le conteneur s&#8217;est occupé de tout: résolution des dépendances de l&#8217;objet, et injection de ces dernières quand nécessaire.</p>
<h3 id="toc-portee-des-services-scopes">Portée des services (Scopes)</h3>
<p>Les services construits via SpiralDi ont une durée de vie contrôlée.<br />
Par défaut, plusieurs demandes au conteneur pour un même service retournerons la même instance de l&#8217;objet, il s&#8217;agit de la portée de type <em>singleton</em>.<br />
Le conteneur est configuré par défaut pour que les services qu&#8217;ils crée aient une portée de type <em>singleton</em>.</p>
<p>Il est possible d&#8217;utiliser la portée <em>prototype</em> pour qu&#8217;un nouvel objet soit créé à chaque appel du service, en utilisant la propriété</p>
<div class="codecolorer-container text notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">scope=&quot;prototype&quot;</div></div>
<p>dans le fichier XML.</p>
<h2 id="toc-utilisation-avancee">Utilisation &laquo;&nbsp;avancée&raquo;&nbsp;</h2>
<p>Vous savez désormais comment décrire &laquo;&nbsp;basiquement&raquo;&nbsp; vos services et leurs dépendances. Voyons maintenant quelques concepts un peu plus poussés.</p>
<h3 id="toc-utilisation-des-references-et-des-methodfactory">Utilisation des Références et des <em>MethodFactory</em></h3>
<p>Il peut arriver que l&#8217;on ai besoin d&#8217;injecter des paramètres de manière dynamique. Imaginez que vous ne connaissiez pas la valeur des paramètres à injecter, ceux-ci étant contenus dans un objet de configuration par exemple.</p>
<p>Nous souhaitons donc que le conteneur construise nos objets en utilisant des informations contenues dans la configuration. Le conteneur est donc capable de s&#8217;occuper de générer le code suivant à notre place:</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Config<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$service</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Db<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Pour cela, il faut utiliser le système de réferences:</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;db&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Database&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;config&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;host&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;config&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;user&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;config&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;password&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constructor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Il est également possible de spécifier la méthode à utiliser pour résoudre les arguments,</p>
<div class="codecolorer-container text notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">getParam()</div></div>
<p>par exemple, pour arriver à quelque chose de ce genre:</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Config<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$service</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Db<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;host&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;user&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; <span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;password&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Le code XML est alors le suivant:</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;config&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;host&quot;</span> <span style="color: #000066;">factoryMethod</span>=<span style="color: #ff0000;">&quot;getParam&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<h3 id="toc-heritage-et-surcharge-de-services">Héritage et surcharge de services</h3>
<p>Assez souvent, certains services à injecter se ressemblent. Il est possible d&#8217;utiliser un système d&#8217;héritage pour rendre la description des services moins rébarbative. Il ne s&#8217;agit pas d&#8217;un héritage &laquo;&nbsp;concret&raquo;&nbsp; dans nos classes, mais du principe de l&#8217;héritage. Ainsi, une description peut en étendre une autre, facilitant à la fois son écriture et sa compréhension.</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;extendedService&quot;</span> <span style="color: #000066;">extends</span>=<span style="color: #ff0000;">&quot;config&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;method2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;value&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/method<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h3 id="toc-container-aware">Container Aware</h3>
<p>Dans certains cas, il peut être utile qu&#8217;un service soit conscient de l&#8217;existence du conteneur, et qu&#8217;il puisse y accéder. Il est facile d&#8217;injecter le conteneur dans un service, en utilisant le type &laquo;&nbsp;container&raquo;&nbsp;, ou la facilité &laquo;&nbsp;containerAware&raquo;&nbsp;:</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;containerAwareService&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Service&quot;</span> <span style="color: #000066;">containerAware</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- est exactement équivalent à--&gt;</span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;containerAwareService&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Service&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;setDiContainer&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;container&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/method<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Du coté de votre classe, si celle-ci doit récupérer le conteneur, elle à simplement à implémenter l&#8217;interface <em>SpiralDi_ContainerAware</em>. Lors de sa construction, la méthode <em>setDiContainer</em> sera directement appelée. </p>
<p>A noter que dans ce cas, il n&#8217;est pas nécessaire de définir votre service comme étant &laquo;&nbsp;ContainerAware&raquo;&nbsp;, le conteneur étant capable de le découvrir tout seul. </p>
<h2 id="toc-factories">Factories</h2>
<p>Il est également possible d&#8217;utiliser des Factory depuis le DI, pour générer un comportement comme celui ci</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$service</span> <span style="color: #339933;">=</span> MyServiceFactory<span style="color: #339933;">::</span><span style="color: #004000;">createService</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Le code XML correspondant est le suivant:</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;serviceFactory&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;factory&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;MyServiceFactory&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;createService&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Cela peut s&#8217;avérer pratique pour récupérer vos anciennes implémentations du pattern Singleton entres autres&#8230;</p>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;singleton&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;factory&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Mysingleton&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;getInstance&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h2 id="toc-telechargez-le">Téléchargez le ! </h2>
<p>Convaincu ? Pour récupérer la dernière version de SpiralDi, vous avez le choix entre plusieurs solutions:</p>
<h3 id="toc-via-le-depot-mercurial">Via le dépôt mercurial</h3>
<div class="codecolorer-container bash notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">hg clone https:<span style="color: #000000; font-weight: bold;">//</span>ametaireau<span style="color: #000000; font-weight: bold;">@</span>bitbucket.org<span style="color: #000000; font-weight: bold;">/</span>ametaireau<span style="color: #000000; font-weight: bold;">/</span>spiraldi<span style="color: #000000; font-weight: bold;">/</span></div></div>
<h3 id="toc-via-les-archives">Via les archives</h3>
<p>Le code est disponible en <a href="http://bitbucket.org/ametaireau/spiraldi/get/tip.zip">zip</a>, <a href="http://bitbucket.org/ametaireau/spiraldi/get/tip.gz">gz</a> ou <a href="http://bitbucket.org/ametaireau/spiraldi/get/tip.bz2">bz2</a></p>
<p>Vous pouvez aussi aller <a href="http://bitbucket.org/ametaireau/spiraldi/">jeter directement un oeil au dépot</a>.<br />
Et voila! Vous avez de quoi vous amuser ! Pour toute demande de fonctionnalité, rapport de bug etc, <a href="http://bitbucket.org/ametaireau/spiraldi/issues/new/">n&#8217;hésitez surtout pas</a>!</p>
<h2 id="toc-et-ailleurs">Et ailleurs ?</h2>
<p>SpiralDi n&#8217;est bien évidemment pas le seul Conteneur Léger écrit en PHP. Depuis peu, ces derniers commencent d&#8217;ailleurs à fleurir sur la toile. Les frameworks Symfony et Flow3<sup>1</sup> leur font d&#8217;ailleurs la part belle, et c&#8217;est tant mieux! Quelques alternatives possibles au conteneur de Spiral donc:</p>
<ul>
<li><a href="http://svn.symfony-project.com/components/dependency_injection/">Le service container de symfony</a></li>
<li><a href="http://github.com/beberlei/yadif/tree/master">Yadim</a></li>
<li><a href="http://flow3.typo3.org/documentation/reference/object/">Flow3 Objects</a></li>
<li><a href="http://www.beberlei.de/sphicy/">Sphicy</a></li>
</ul>
<h2 id="toc-lectures-interessantes">Lectures intéressantes</h2>
<p>Si vous souhaitez aller plus loin, voici quelques lectures intéressantes sur le sujet de l&#8217;injection de dépendances:</p>
<ul>
<li><a href="http://www.martinfowler.com/articles/injection.html">L&#8217;article de Martin Fowler sur l&#8217;injection de dépendances</a></li>
<li>La série d&#8217;articles de Fabien potencier (<a href="http://fabien.potencier.org/article/11/what-is-dependency-injection">1</a>,<a href="http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container">2</a>,<a href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container">3</a>,<a href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services">4</a>,<a href="http://github.com/fabpot/Pimple/tree/master">5</a>)</li>
<li>Celle de Padraic Brady (<a href="http://blog.astrumfutura.com/archives/394-The-Case-For-Dependency-Injection-Part-1.html">1</a>,<a href="http://blog.astrumfutura.com/archives/395-The-Case-For-Dependency-Injection-Part-2.html">2</a>) </li>
<li><a href="http://www.dotnetguru.org/articles/dossiers/ioc/ioc.htm">Les conteneurs légers du futur</a>, par Sami Jabber</li>
</ul>
<ol class="footnotes"><li id="footnote_0_189" class="footnote">Il est tout nouveau, tout beau, en PHP 5.3, utilise l&#8217;AOP, la persistance <em>Domain Model</em> &#8230; et l&#8217;injection de dépendances! A suivre de très près: <a href="http://flow3.typo3.org/">Flow3 </a></li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.notmyidea.org/article/fr-introduction-to-spiral-dependency-injection-container-in-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introduction à l&#8217;injection de dépendances: le cas du singleton.</title>
		<link>http://www.notmyidea.org/article/dependency-injection-singleton-design-pattern-ioc-dendencies-dependences/</link>
		<comments>http://www.notmyidea.org/article/dependency-injection-singleton-design-pattern-ioc-dendencies-dependences/#comments</comments>
		<pubDate>Mon, 25 May 2009 14:36:58 +0000</pubDate>
		<dc:creator>Alexis Metaireau</dc:creator>
				<category><![CDATA[Architecture logicielle]]></category>
		<category><![CDATA[Injection de dépendances]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[singleton]]></category>
		<category><![CDATA[spiral]]></category>

		<guid isPermaLink="false">http://www.notmyidea.org/?p=67</guid>
		<description><![CDATA[L&#8217;architecture logicielle est un des aspects du développement qui m&#8217;intéresse particulièrement. Ça fait d&#8217;ailleurs un bout de temps que l&#8217;idée d&#8217;un article à propos des dépendances (de l&#8217;injection de dépendances) et du cas du singleton me trotte dans la tête, alors, le voici:
Avant tout, il faut bien comprendre que sans contexte il n&#8217;existe pas de [...]]]></description>
			<content:encoded><![CDATA[<p>L&#8217;architecture logicielle est un des aspects du développement qui m&#8217;intéresse particulièrement. Ça fait d&#8217;ailleurs un bout de temps que l&#8217;idée d&#8217;un article à propos des dépendances (de l&#8217;injection de dépendances) et du cas du singleton me trotte dans la tête, alors, le voici:</p>
<p>Avant tout, il faut bien comprendre que sans contexte il n&#8217;existe pas de manière plus censée qu&#8217;une autre pour construire une application. Il existe par contre un ensemble de bonnes pratiques qu&#8217;il est bon de connaitre et d&#8217;appliquer, dans la plus large mesure possible. Ces pratiques sont souvent mal connues, et nombre d&#8217;entre elles sont appliquées à la va vite.</p>
<p>Nous allons tenter d&#8217;expliquer ici pourquoi et comment l&#8217;implémentation la plus rependue du singleton favorise la création de dépendances, et comment nous pouvons y remédier, grâce à l&#8217;injection de dépendances.<br />
<span id="more-67"></span></p>
<h3 id="toc-le-singleton">Le singleton</h3>
<div id="attachment_140" class="wp-caption alignright" style="width: 160px"><img class="size-thumbnail wp-image-140" title="singleton" src="http://www.notmyidea.org/wp-content/uploads/2009/05/singleton-150x150.jpg" alt="Le singleton, à l'origine de dépendances" width="150" height="150" /><p class="wp-caption-text">Le singleton, à l&#39;origine de dépendances</p></div>
<p>Le Singleton est un patron de conception (souvent le premier patron de conception qui nous est présenté) qui doit être appliqué avec précaution. Son utilisation est souvent mal comprise et celui ci peut être considéré à tort comme une solution &laquo;&nbsp;miracle&raquo;&nbsp; pour accéder facilement à un objet, comme on le ferait d&#8217;une variable globale. On dit d&#8217;ailleurs aussi qu&#8217;il s&#8217;agit de l&#8217;<em>antipattern</em> singleton, à raison. Pourquoi ?</p>
<p>Très rapidement, un singleton est une classe dont il existe un nombre défini d&#8217;instances. Typiquement, le singleton est utilisé afin de réduire le nombre possible d&#8217;instances d&#8217;une classe à une seule. Cela peut être très utile, et est utilisé dans de nombreux cas à bon escient (je pense par exemple à l&#8217;accès à une base de données).</p>
<p>Un des défauts majeur de ce motif, est l&#8217;implémentation la plus souvent présentée, qui va de paire avec l&#8217;usage de méthodes statiques pour récupérer une instance de la classe. Pour mieux comprendre, voici l&#8217;implémentation type, en PHP (le motif est sensiblement le même dans de nombreux langages):</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> DbConnection_MySql <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$_instance</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> __construct <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> getInstance <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span> instanceof <span style="color: #000000; font-weight: bold;">self</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> connect<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// do some stuff</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Ici, pour récupérer l&#8217;instance de la classe, il est nécessaire de faire appel à la méthode statique <em>getInstance </em>de la classe <em>DbConnection_Mysql</em>.</p>
<p>Il est alors nécessaire, dans la classe utilisatrice du singleton (imaginons qu&#8217;il s&#8217;agisse d&#8217;une classe User), de <em>hardcoder</em> le nom de la classe DbConnection_Mysql, la classe A devenant alors <span style="text-decoration: underline;">dépendante</span> de cette implémentation particulière du singleton.</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> User<span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// dépendance avec la classe DbConnection</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$dbc</span> <span style="color: #339933;">=</span> DbConnection_MySql<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Avec cette implémentation, il est impossible de changer la classe en charge de la connexion à la base de données sans modifier le code. Imaginons que nous souhaitons utiliser la classe <em>DbConnection_Oracle</em> par exemple, nous sommes bloqués. Il s&#8217;agit d&#8217;une problème de conception, et peut faire perdre un temps important lors du développement.</p>
<h3 id="toc-inversion-de-controle-injection-de-dependances">Inversion de contrôle / Injection de dépendances</h3>
<p>Comme nous venons de le voir, le singleton, ou plutôt, cette implémentation du singleton, introduit et favorise les dépendances entre nos classes.</p>
<p>Une des solutions possible est d&#8217;inverser le flux de contrôle de notre application: au lieu que ce soit la classe <em>User</em> qui appelle directement <em>DbConnection_Mysql</em>, celui ci peut être crée en amont, pour être ensuite injecté dans la classe qui souhaite l&#8217;utiliser. De cette manière,  Ce principe à un nom, il s&#8217;agit de <span style="text-decoration: underline;">l&#8217;injection de dépendances</span>.</p>
<h4 id="toc-theorie">Théorie</h4>
<p><em>Alice</em> a besoin d&#8217;une Glace pour la <em>manger()</em>.<br />
<em>Alice</em> aime les <em>GlaceALaFraise</em>&#8230; Si on donne de l&#8217;argent à <em>Alice</em> elle achète systématiquement une <em>GlaceALaFraise</em>. <em>Alice</em> est bloquée au seul parfum &laquo;&nbsp;fraise des bois&raquo;&nbsp; aussi savoureux soit-il.</p>
<p>Pour lui faire découvrir de nouvelles saveurs sa <em>Maman</em> décide de ne plus laisser <em>Alice</em> choisir sa <em>Glace</em> elle-même, mais se charge de choisir pour elle une <em>GlaceAuPaté</em>. </p>
<p>Quels que soit les goûts d&#8217;<em>Alice</em>, une <em>GlaceAuPaté</em> reste une <em>Glace</em>, et donc <em>Alice</em> est tout à fait à même de la <em>manger()</em><sup>1</sup>.</p>
<p>Le concept exposé ici est connu comme le <em><a href="http://en.wikipedia.org/wiki/Hollywood_principle">principe d&#8217;Holywood</a></em>: &laquo;&nbsp;Ne vous appelez pas vous même, nous vous appellerons&raquo;&nbsp;.</p>
<p>Ce qu&#8217;il faut retenir, c&#8217;est qu&#8217;<em>Alice</em> peut, si elle le souhaite, <em>manger()</em> tout type de <em>Glace</em>, même si au départ <em>Alice</em> n&#8217;à besoin de <em>manger()</em> q&#8217;une <em>GlaceALaFraise</em>. Nous favorisons ici la réutilisations du code: nous pouvons réutiliser Alice facilement et substituer sa <em>Glace</em> par une autre facilement.</p>
<h4 id="toc-application-a-notre-exemple">Application à notre exemple</h4>
<p>Reprenons l&#8217;exemple des utilisateurs et de l&#8217;utilisation de la DbConnection pour y appliquer ce principe d&#8217;inversion de contrôle. Notre code ressemblerait alors à quelque chose dans cet esprit:</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$dbc</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DbConnection_Default<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClassA_Default<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDbConnection</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$dbc</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Avec les deux interfaces/implémentations suivantes pour DbConnection et User:</p>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:420px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Interfaces</span><br />
<span style="color: #000000; font-weight: bold;">interface</span> DbConnection <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$password</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">function</span> connect<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">interface</span> User<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">function</span> setDbConnection<span style="color: #009900;">&#40;</span>DbConnection<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Implementations</span><br />
<span style="color: #000000; font-weight: bold;">class</span> DbConnection_Mysql implements DbConnection<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$password</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// store parameters into the object</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> connect<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// connect to the database</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> User_Default implements User<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setDbConnection<span style="color: #009900;">&#40;</span>DbConnection <span style="color: #000088;">$dbc</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// store $dbc into the object</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Ici, il subsiste des dépendances dans le code. Il s&#8217;agit de dépendances vis à vis de contrats (interfaces) et non d&#8217;implémentations données (classes), puisque j&#8217;ai choisi d&#8217;utiliser le paradigme de <a href="http://fr.wikipedia.org/wiki/Programmation_par_contrat">programmation par contrats</a>.</p>
<p>Nous avons parlé de singleton et de création de dépendances, mais l&#8217;injection de dépendances est applicable à tout type de classes, et devrait d&#8217;ailleurs être utilisé dans la plupart des projet d&#8217;importante envergure.</p>
<h3 id="toc-utilisation-dun-conteneur">Utilisation d&#8217;un conteneur</h3>
<div id="attachment_170" class="wp-caption alignright" style="width: 197px"><img src="http://www.notmyidea.org/wp-content/uploads/2009/05/exemple.png" alt="schéma des dépendances entre nos classes" title="exemple" width="187" height="155" class="size-full wp-image-170 alignleft" /><p class="wp-caption-text">schéma des dépendances entre nos classes</p></div>
<p>Pour aller un peu plus loin, il peut être utile et efficace de déléguer la tâche de création des objets à un conteneur. Il s&#8217;agit d&#8217;une classe, en charge de la création de tous les objets, ce dernier pouvant résoudre les dépendances nécessaires à la création de l&#8217;objet souhaité.</p>
<p>Nous avons donc le schéma de dépendances décrit à gauche. Une fois ces informations fournies au conteneur (via un fichier de configuration), nous pouvons facilement récupérer l&#8217;object <em>User_Default</em> en le demandant à notre conteneur:</p>
<div class="codecolorer-container text notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$container-&gt;user</div></div>
<p>. Ce dernier se charge alors de créer l&#8217;ensemble des dépendances de cet objet (un objet de la classe DbConnection_Mysql ici). Plutôt sympa, non ?</p>
<p>Pour faire en sorte que la classe d&#8217;accès aux données soit un singleton, c&#8217;est le schéma qu&#8217;il faut alors modifier (via le fichier de configuration ici.)</p>
<p>Ici, j&#8217;ai essentiellement parlé de dépendances entre classes. Cependant, de la même manière, il est possible de contrôler tous les arguments passés à nos objets, qu&#8217;il s&#8217;agisse de tableaux, de chaines de caractère ou autres.</p>
<h3 id="toc-moi-aussi-jen-veux-spiral-di-container">Moi aussi j&#8217;en veux ! Spiral Di Container</h3>
<p>Pour mon usage personnel, j&#8217;ai développé un injecteur de dépendances flexible, permettant d&#8217;appliquer ce modèle à mes futurs développements. Il existe déjà des projets similaires, mais ces derniers font un usage trop abusif &#8211; à mon gout &#8211; du mécanisme de réflexion, perdant alors grandement en performance.</p>
<p>Voyons comment nous pouvons utiliser le conteneur dans notre cas. Cela revient à créer le schéma de dépendances. Cela est possible pour le moment par 2 biais: via XML ou directement via php.</p>
<h4 id="toc-directement-via-php">Directement via php</h4>
<div class="codecolorer-container php notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$fluent</span><br />
<span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerService</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'User_Default'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">-&gt;</span><span style="color: #004000;">call</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'setDbConnection'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">withServices</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'dbc'</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerService</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'dbc'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'DbConnection_Mysql'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">-&gt;</span><span style="color: #004000;">construct</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">with</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'root'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span></div></div>
<h4 id="toc-via-un-fichier-xml">Via un fichier XML</h4>
<div class="codecolorer-container xml notmyidea" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;user&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;User_Default&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;setDbConnection&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;dbc&quot;</span> <span style="color: #000066;">service</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/method<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;dbc&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;DbConnection_Mysql&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;method</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;__construct&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;localhost&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;root&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;argument</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/method<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/container<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Il est à noter que le fichier XML à été directement généré via le <em>Dumper</em> Xml, en utilisant le schema.</p>
<p>Si vous êtes interessé pour regarder plus en détail le fonctionnement de ce conteneur, les sources sont d&#8217;ores et déjà disponibles via le framework de travail spiral, disponible via <a href="http://bitbucket.org/ametaireau/spiral-php52/src/di/">son dépot mercurial</a>.</p>
<p>L&#8217;injecteur de dépendances est présent dans la partie /core/Di de l&#8217;architecture. Une version standalone devrait bientôt voir le jour.</p>
<p>Si cet article vous à plu, je publierais prochainement une série d&#8217;article expliquant en détail comment utiliser un conteneur de dépendances, en m&#8217;appuyant sur des exemples concrets que j&#8217;ai pu rencontrer.</p>
<p>Ah, et j&#8217;oubliais, un grand merci aux relecteurs pour votre aide précieuse ! (Fred, David, Florent, Joel, Nico &#8230;)</p>
<ol class="footnotes"><li id="footnote_0_67" class="footnote">Merci Frédéric pour ton super exemple !</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.notmyidea.org/article/dependency-injection-singleton-design-pattern-ioc-dendencies-dependences/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
