<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.aide-de-camp.org/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xml:base="http://fabien.potencier.org/">
  <title>Fabien Potencier</title>
  <link href="http://fabien.potencier.org/" />
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>

      <link rel="self" href="http://feeds.aide-de-camp.org/aidedecamp" type="application/atom+xml" /><entry>
  <title>Sourceforge Community Choice Awards: symfony is a Finalist!</title>
  <link href="http://fabien.potencier.org/article/30/sourceforge-community-choice-awards-symfony-is-a-finalist" />
  <id>article-30</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-06-22T21:40:00+02:00</updated>
  <content type="html">
    &lt;div style="float: right; padding: 10px"&gt;
  &lt;a href="http://sourceforge.net/community/cca09/vote/?f=392"&gt;
    &lt;img src="http://www.symfony-project.org/images/symfony_vote_2009_white.jpg" border="0"/&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Thanks its dedicated community, &lt;a href="http://www.symfony-project.org/"&gt;symfony&lt;/a&gt; has been chosen as a finalist for the 2009 Sourceforge
Community Choice Awards in no less than three categories!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Best Project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Best Tool or Utility for Developers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Best Project for the Enterprise&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some other PHP projets are also finalists: phpMyAdmin, FLOW3, Joomla, TYPO3, and vtiger CRM.&lt;/p&gt;

&lt;p&gt;If you like symfony, or if you just like PHP, or if you just want to be kind with us, please, consider voting for symfony: http://sourceforge.net/community/cca09/vote/?f=392.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Pimple, the small dependency injection container for PHP 5.3</title>
  <link href="http://fabien.potencier.org/article/29/pimple-the-small-dependency-injection-container-for-php-5-3" />
  <id>article-29</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-06-16T07:50:00+02:00</updated>
  <content type="html">
    &lt;p&gt;Some people emailed me about a blog
&lt;a href="http://fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures"&gt;post&lt;/a&gt;
I wrote some time ago about a dependency injection container done in PHP 5.3.
I have published on &lt;a href="http://github.com/fabpot/twittee"&gt;Github&lt;/a&gt; the small
version of it (&lt;a href="http://twittee.org/"&gt;Twittee&lt;/a&gt;), but not the "working" version.&lt;/p&gt;

&lt;p&gt;Today, I took the time to publish it on
&lt;a href="http://github.com/fabpot/Pimple"&gt;Github&lt;/a&gt;. Pimple is a small dependency
injection container, with all the features you need for a usage in real
projects.&lt;/p&gt;

&lt;p&gt;Feel free to use it, fork it, and enhance it for your next PHP 5.3 project.&lt;/p&gt;

&lt;p&gt;And don't forget to give PHP 5.3 a try as the PHP core team has just
&lt;a href="http://www.php.net/archive/2009.php#id2009-06-12-1"&gt;published&lt;/a&gt; the third
release candidate, and they hope to release the final version by the end of
June.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Tweeting from PHP</title>
  <link href="http://fabien.potencier.org/article/20/tweeting-from-php" />
  <id>article-20</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-06-14T22:33:00+02:00</updated>
  <content type="html">
    &lt;p&gt;Twitter is everywhere nowadays. Odds are eventually you will want to tweet
from PHP. No need to use one of the numerous PHP Twitter libraries, as
tweeting is as simple as using the PHP built-in &lt;code&gt;file_get_contents()&lt;/code&gt;
function:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;function&lt;/span&gt; tweet&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$message&lt;/span&gt;, &lt;span class="re0"&gt;$username&lt;/span&gt;, &lt;span class="re0"&gt;$password&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="re0"&gt;$context&lt;/span&gt; = &lt;a href="http://www.php.net/stream_context_create"&gt;&lt;span class="kw3"&gt;stream_context_create&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
    &lt;span class="st0"&gt;'http'&lt;/span&gt; =&amp;gt; &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
      &lt;span class="st0"&gt;'method'&lt;/span&gt;  =&amp;gt; &lt;span class="st0"&gt;'POST'&lt;/span&gt;,
      &lt;span class="st0"&gt;'header'&lt;/span&gt;  =&amp;gt; &lt;a href="http://www.php.net/sprintf"&gt;&lt;span class="kw3"&gt;sprintf&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;Authorization: Basic %s&lt;span class="es0"&gt;\r&lt;/span&gt;&lt;span class="es0"&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, &lt;a href="http://www.php.net/base64_encode"&gt;&lt;span class="kw3"&gt;base64_encode&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$username&lt;/span&gt;.&lt;span class="st0"&gt;':'&lt;/span&gt;.&lt;span class="re0"&gt;$password&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.
                   &lt;span class="st0"&gt;&amp;quot;Content-type: application/x-www-form-urlencoded&lt;span class="es0"&gt;\r&lt;/span&gt;&lt;span class="es0"&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;,
      &lt;span class="st0"&gt;'content'&lt;/span&gt; =&amp;gt; http_build_query&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'status'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$message&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,
      &lt;span class="st0"&gt;'timeout'&lt;/span&gt; =&amp;gt; &lt;span class="nu0"&gt;5&lt;/span&gt;,
    &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,
  &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="re0"&gt;$ret&lt;/span&gt; = &lt;a href="http://www.php.net/file_get_contents"&gt;&lt;span class="kw3"&gt;file_get_contents&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'http://twitter.com/statuses/update.xml'&lt;/span&gt;, &lt;span class="kw2"&gt;false&lt;/span&gt;, &lt;span class="re0"&gt;$context&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;false&lt;/span&gt; !== &lt;span class="re0"&gt;$ret&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Pretty easy, no? Using the &lt;code&gt;tweet()&lt;/code&gt; function is of course a piece of cake:&lt;/p&gt;

&lt;pre class="php"&gt;tweet&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'From PHP, yeah...'&lt;/span&gt;, &lt;span class="st0"&gt;'fabpot'&lt;/span&gt;, &lt;span class="st0"&gt;'Pa$$'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;As an added bonus, the function returns &lt;code&gt;true&lt;/code&gt; if everything went fine, or
&lt;code&gt;false&lt;/code&gt; otherwise.&lt;/p&gt;

&lt;p&gt;As we talk about Twitter, you can &lt;a href="http://www.twitter.com/fabpot"&gt;follow me&lt;/a&gt;.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Quick SSH Tip</title>
  <link href="http://fabien.potencier.org/article/19/quick-ssh-tip" />
  <id>article-19</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-06-09T19:40:00+02:00</updated>
  <content type="html">
    &lt;p&gt;If you need to regularly connect to a lot of different servers like I do, you
probably use SSH to connect to them, and you also probably use your personal
SSH identity file to ease the connection.&lt;/p&gt;

&lt;p&gt;Some time ago, I re-discover a neat trick to simplify the connection by using
the &lt;code&gt;.ssh/config&lt;/code&gt; file. I don't know why I forgot about it, but as it seems
that a lot of people around me do not know about this file either, here is a
small post on how it can be used to your advantage.&lt;/p&gt;

&lt;p&gt;Let's say you have a host at &lt;code&gt;1.2.3.4&lt;/code&gt; you need to connect to and the username
you need to use is &lt;code&gt;fabien&lt;/code&gt;. Each time you want to connect to it, you need to
type something like the following:&lt;/p&gt;

&lt;pre class="command-line"&gt;&lt;code&gt;$ ssh fabien@1.2.3.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simple enough, even if you need to remember the remote user you need to use
for each server. However, if you need to specify a specific key, it becomes
more verbose:&lt;/p&gt;

&lt;pre class="command-line"&gt;&lt;code&gt;$ ssh -i /Users/fabien/keys/myserver.key fabien@1.2.3.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's difficult to remember, quite tedious to write and error prone. Instead,
I want to be able to just type:&lt;/p&gt;

&lt;pre class="command-line"&gt;&lt;code&gt;$ ssh myserver
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's quite easy. Create a &lt;code&gt;.ssh/config&lt;/code&gt; file under your home directory and put
something like this inside:&lt;/p&gt;

&lt;pre&gt;Host myserver
  HostName 1.2.3.4
  User root
  IdentityFile /Users/fabien/keys/myserver.key
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;That's all there is to it. Now, connecting to the server is as easy as typing:&lt;/p&gt;

&lt;pre class="command-line"&gt;&lt;code&gt;$ ssh myserver
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it works everywhere SSH is involved. For instance, when you use &lt;code&gt;scp&lt;/code&gt; to
copy a file:&lt;/p&gt;

&lt;pre class="command-line"&gt;&lt;code&gt;$ scp localfile.txt myserver:/tmp/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It is also a great way to not give sensitive information in configuration
files. For instance, in a symfony project, the &lt;code&gt;properties.ini&lt;/code&gt; file can
contain the information to connect to the production servers used for
deployment. Instead of having to hardcode the real host name, the login and
the password like this:&lt;/p&gt;

&lt;pre class="ini"&gt;&lt;span class="re0"&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;production&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;/span&gt;
&lt;span class="re1"&gt;host&lt;/span&gt;=&lt;span class="re2"&gt;www.myserver.com&lt;/span&gt;
&lt;span class="re1"&gt;port&lt;/span&gt;=&lt;span class="re2"&gt;&lt;span class="nu0"&gt;22&lt;/span&gt;&lt;/span&gt;
&lt;span class="re1"&gt;user&lt;/span&gt;=&lt;span class="re2"&gt;someusername&lt;/span&gt;
&lt;span class="re1"&gt;pass&lt;/span&gt;=&lt;span class="re2"&gt;somepassword&lt;/span&gt;
&lt;span class="re1"&gt;dir&lt;/span&gt;=&lt;span class="re2"&gt;/var/www/mysite/&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;You can simply reference the name you gave in the &lt;code&gt;config&lt;/code&gt; file and keep the
details secret on your local machine:&lt;/p&gt;

&lt;pre class="ini"&gt;&lt;span class="re0"&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;production&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;/span&gt;
&lt;span class="re1"&gt;host&lt;/span&gt;=&lt;span class="re2"&gt;myserver&lt;/span&gt;
&lt;span class="re1"&gt;port&lt;/span&gt;=&lt;span class="re2"&gt;&lt;span class="nu0"&gt;22&lt;/span&gt;&lt;/span&gt;
&lt;span class="re1"&gt;dir&lt;/span&gt;=&lt;span class="re2"&gt;/var/www/mysite/&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Unix is really powerful thanks to little things like this one. By the way, if
you want to know more about the Unix history, you can
&lt;a href="http://www.computerworld.com/action/article.do?command=printArticleBasic&amp;amp;taxonomyName=Operating+Systems&amp;amp;articleId=9133570&amp;amp;taxonomyId=89"&gt;read&lt;/a&gt;
the really interesting "Unix turns 40: The past, present and future of a revolutionary OS"
article published on ComputerWorld.com earlier this month.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>What for PHP6?</title>
  <link href="http://fabien.potencier.org/article/18/what-for-php6" />
  <id>article-18</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-06-07T21:10:00+02:00</updated>
  <content type="html">
    &lt;p&gt;PHP 5.3 is just around the corner with a lot of great new features. However,
even if I'm really excited about this new release, I won't make yet another
PHP 5.3 feature list; I will rather look at the future of PHP. PHP core
developers met at php|tek and discussed the future of PHP. And it is really
great to see that they plan lots of wonderful features; let's set aside the
Unicode stuff.&lt;/p&gt;

&lt;p&gt;They published some &lt;a href="http://wiki.php.net/summits/pdmnotesmay09"&gt;notes&lt;/a&gt; from
the meeting, and here is my personal list for things I find really
interesting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code&gt;__cast()&lt;/code&gt; magic method that will be called for all casts. If the
&lt;code&gt;__toString()&lt;/code&gt; method is there it will get used for string types first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider making a "callable" type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make &lt;code&gt;ArrayObject&lt;/code&gt; and &lt;code&gt;ArrayAccess&lt;/code&gt; accepted everywhere regular arrays
are.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add traits support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add type hinted return values, scalar type hints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make function call chaining possible (&lt;code&gt;f()()&lt;/code&gt; if &lt;code&gt;f()&lt;/code&gt; returns a function),
and array dereferencing (&lt;code&gt;f()[0]&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C#-style properties with getters/setters:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; Foo
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
   &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="re0"&gt;$bar&lt;/span&gt;
       getter &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;bar&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
       setter &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;bar&lt;/span&gt; = &lt;a href="http://www.php.net/strtolower"&gt;&lt;span class="kw3"&gt;strtolower&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$value&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
   ;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
  </content>
</entry>
      <entry>
  <title>On PHP 5.3, Lambda Functions, and Closures</title>
  <link href="http://fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures" />
  <id>article-17</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-04-16T14:00:00+02:00</updated>
  <content type="html">
    &lt;p&gt;PHP 5.3 will have a lot of exciting new features. One of the most important one
for me is the introduction of lambda functions and closures support. I won't
talk too much about what lambda functions or closures are, as you can find
many good blog posts describing them in great details. To sum up, a lambda
function is an anonymous PHP function that can be stored in a variable and
passed as an argument to other functions or methods. A closure is a lambda
function that is aware of its surrounding context.&lt;/p&gt;

&lt;p&gt;The first obvious use for lambda functions and closures is in conjunction with
the &lt;code&gt;array_map()&lt;/code&gt;, &lt;code&gt;array_reduce()&lt;/code&gt;, and &lt;code&gt;array_filter()&lt;/code&gt; native PHP
functions:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$input&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="nu0"&gt;2&lt;/span&gt;, &lt;span class="nu0"&gt;3&lt;/span&gt;, &lt;span class="nu0"&gt;4&lt;/span&gt;, &lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$output&lt;/span&gt; = &lt;a href="http://www.php.net/array_filter"&gt;&lt;span class="kw3"&gt;array_filter&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$input&lt;/span&gt;, &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$v&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$v&lt;/span&gt; &amp;gt; &lt;span class="nu0"&gt;2&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The above example filters the input array by removing all values greater than
2:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$output&lt;/span&gt; == &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;2&lt;/span&gt; =&amp;gt; &lt;span class="nu0"&gt;3&lt;/span&gt;, &lt;span class="nu0"&gt;3&lt;/span&gt; =&amp;gt; &lt;span class="nu0"&gt;4&lt;/span&gt;, &lt;span class="nu0"&gt;4&lt;/span&gt; =&amp;gt; &lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;function ($v) { return $v &amp;gt; 2; }&lt;/code&gt; is the lambda function definition and it
can be stored in a PHP variable to be reusable:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$max_comparator&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$v&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$v&lt;/span&gt; &amp;gt; &lt;span class="nu0"&gt;2&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$input&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="nu0"&gt;2&lt;/span&gt;, &lt;span class="nu0"&gt;3&lt;/span&gt;, &lt;span class="nu0"&gt;4&lt;/span&gt;, &lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$output&lt;/span&gt; = &lt;a href="http://www.php.net/array_filter"&gt;&lt;span class="kw3"&gt;array_filter&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$input&lt;/span&gt;, &lt;span class="re0"&gt;$max_comparator&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;But what if I want to change the maximum number allowed in the filtered array?
I can either create another lambda function or use a closure:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$max_comparator&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$max&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$v&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; use &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$max&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$v&lt;/span&gt; &amp;gt; &lt;span class="re0"&gt;$max&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$input&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;, &lt;span class="nu0"&gt;2&lt;/span&gt;, &lt;span class="nu0"&gt;3&lt;/span&gt;, &lt;span class="nu0"&gt;4&lt;/span&gt;, &lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$output&lt;/span&gt; = &lt;a href="http://www.php.net/array_filter"&gt;&lt;span class="kw3"&gt;array_filter&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$input&lt;/span&gt;, &lt;span class="re0"&gt;$max_comparator&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;2&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Now, the &lt;code&gt;$max_comparator&lt;/code&gt; function takes the maximum allowed number and
returns a function that is different according to this maximum. Even for such
a contrived example, I hope you see the great power it gives you!&lt;/p&gt;

&lt;p&gt;Closures also opens up a lot of great possibilities, like the implementation
of the cryptic
&lt;a href="http://php100.wordpress.com/2009/04/13/php-y-combinator/"&gt;Y-combinator&lt;/a&gt;, as
demonstrated by Stanislav Malyshev in one of his recent blog post:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;function&lt;/span&gt; Y&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$F&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="re0"&gt;$func&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$func&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; use&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$F&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$F&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$x&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; use&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
      &lt;span class="re0"&gt;$ff&lt;/span&gt; = &lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$f&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
      &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$ff&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$x&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Today, I want to talk about yet great another example on how to use lambda
functions and closures. You will see that it can simplify your code a lot when
used appropriately.&lt;/p&gt;

&lt;p&gt;If you have read my blog recently, you know that I am quite obsessed with
dependency injection these days. This post will show you how to implement a
very simple but still full-featured dependency injection container, thanks to
the new features of PHP 5.3.&lt;/p&gt;

&lt;p&gt;A dependency injection container must be able to manage two different kind of
data: objects and parameters. And objects must be created on-demand the first
time they are accessed from the container.&lt;/p&gt;

&lt;p&gt;Using a simple class that implements the magic &lt;code&gt;__get()&lt;/code&gt; and &lt;code&gt;__set()&lt;/code&gt;
methods, we can easily manage both the objects and the parameters:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; DIContainer
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  protected &lt;span class="re0"&gt;$values&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw2"&gt;function&lt;/span&gt; __set&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;, &lt;span class="re0"&gt;$value&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="re0"&gt;$value&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="kw2"&gt;function&lt;/span&gt; __get&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/is_callable"&gt;&lt;span class="kw3"&gt;is_callable&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; ? &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; : &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Using the container is quite simple:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$container&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; DIContainer&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="co1"&gt;// define the parameters&lt;/span&gt;
&lt;span class="re0"&gt;$container&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;cookie_name&lt;/span&gt; = &lt;span class="st0"&gt;'SESSION_ID'&lt;/span&gt;;
&lt;span class="re0"&gt;$container&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;storage_class&lt;/span&gt; = &lt;span class="st0"&gt;'SessionStorage'&lt;/span&gt;;
&amp;nbsp;
&lt;span class="co1"&gt;// defined the objects&lt;/span&gt;
&lt;span class="re0"&gt;$container&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;storage&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;new&lt;/span&gt; &lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;storage_class&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;cookie_name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&lt;span class="re0"&gt;$container&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;user&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;new&lt;/span&gt; User&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;storage&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="co1"&gt;// get the user object&lt;/span&gt;
&lt;span class="re0"&gt;$user&lt;/span&gt; = &lt;span class="re0"&gt;$container&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;user&lt;/span&gt;;
&amp;nbsp;
&lt;span class="co1"&gt;// the above call is roughly equivalent to the following code:&lt;/span&gt;
&lt;span class="co1"&gt;// $storage = new SessionStorage('SESSION_ID');&lt;/span&gt;
&lt;span class="co1"&gt;// $user = new User($storage);&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  The examples I use in this article are the same as the one I have used in my
  series on &lt;a href="http://fabien.potencier.org/article/11/what-is-dependency-injection"&gt;dependency injection&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The definition of an object is done by defining a lambda function that returns
an instance of the object.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;__get()&lt;/code&gt; method checks if the value associated with a key is a PHP
callable (and lambda functions are callables) to make the difference between
an object definition and a parameter.&lt;/p&gt;

&lt;p&gt;Also notice how we call the lambda:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The trick here is to pass the container as an argument of the lambda function
so that it can use the container to access parameters and other objects
managed by the container.&lt;/p&gt;

&lt;p&gt;We can make the container a bit better by adding error support:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; DIContainer
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  protected &lt;span class="re0"&gt;$values&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw2"&gt;function&lt;/span&gt; __set&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;, &lt;span class="re0"&gt;$value&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="re0"&gt;$value&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="kw2"&gt;function&lt;/span&gt; __get&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
      throw &lt;span class="kw2"&gt;new&lt;/span&gt; InvalidArgumentException&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/sprintf"&gt;&lt;span class="kw3"&gt;sprintf&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'Value &amp;quot;%s&amp;quot; is not defined.'&lt;/span&gt;, &lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/is_callable"&gt;&lt;span class="kw3"&gt;is_callable&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; ? &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; : &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;values&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Defining objects with lambda functions is great because the developer can do
whatever he wants to actually create and configure instances. But we still
need to implement one important feature of any dependency injection container:
shared instances. This can be done manually like this:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$container&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;user&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/static"&gt;&lt;span class="kw3"&gt;static&lt;/span&gt;&lt;/a&gt; &lt;span class="re0"&gt;$object&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/is_null"&gt;&lt;span class="kw3"&gt;is_null&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$object&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="re0"&gt;$object&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; User&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;storage&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$object&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;By declaring a static variable in the lambda function, the first time it is
called, the object is created and returned. For all subsequent calls, the same
instance will always be returned.&lt;/p&gt;

&lt;p&gt;It works as expected, but this is quite repetitive, tedious, and error prone.
For all instances that must be unique, we need to add this boilerplate code.
Instead, I want to support shared instances as a native feature of the
container itself. Thanks to closures, that's quite easy to accomplish:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; DIContainer
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="co1"&gt;// ...&lt;/span&gt;
&amp;nbsp;
  &lt;span class="kw2"&gt;function&lt;/span&gt; asShared&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$callable&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; use &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$callable&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
      &lt;a href="http://www.php.net/static"&gt;&lt;span class="kw3"&gt;static&lt;/span&gt;&lt;/a&gt; &lt;span class="re0"&gt;$object&lt;/span&gt;;
&amp;nbsp;
      &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/is_null"&gt;&lt;span class="kw3"&gt;is_null&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$object&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
      &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
        &lt;span class="re0"&gt;$object&lt;/span&gt; = &lt;span class="re0"&gt;$callable&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
      &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
      &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$object&lt;/span&gt;;
    &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;asShared()&lt;/code&gt; method wraps the given lambda function to add the needed
logic we have seen before. Declaring an object as unique for a given container
is now dead simple:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;user&lt;/span&gt; = &lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;asShared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;new&lt;/span&gt; User&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$c&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;storage&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;In less than 30 lines of PHP, we have coded a full-featured dependency
injection container. Quite impressive!&lt;/p&gt;

&lt;p&gt;If we remove the need for shared instance, and if we define parameters and
objects as lambdas, we can even compact the code so that it fits in a tweet:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; Container &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
 protected &lt;span class="re0"&gt;$s&lt;/span&gt;=&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
 &lt;span class="kw2"&gt;function&lt;/span&gt; __set&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$k&lt;/span&gt;, &lt;span class="re0"&gt;$c&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;s&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$k&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;=&lt;span class="re0"&gt;$c&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
 &lt;span class="kw2"&gt;function&lt;/span&gt; __get&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$k&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;s&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="re0"&gt;$k&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;I have called this tweet container &lt;em&gt;twittee&lt;/em&gt;, and it has its own
&lt;a href="http://twittee.org/"&gt;dedicated website&lt;/a&gt; and
&lt;a href="http://github.com/fabpot/twittee/tree/master"&gt;github repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;PHP 5.3 is really a great step forward for the PHP language.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Symfony Service Container: The Need for Speed</title>
  <link href="http://fabien.potencier.org/article/16/symfony-service-container-the-need-for-speed" />
  <id>article-16</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-04-02T07:50:00+02:00</updated>
  <content type="html">
    &lt;blockquote class="note"&gt;&lt;p&gt;
  This article is part of a series on Dependency Injection in general and on a
  lightweight implementation of a Container in PHP in particular:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/11/what-is-dependency-injection"&gt;Part 1: What is Dependency Injection? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container"&gt;Part 2: Do you need a Dependency Injection Container? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container"&gt;Part 3: Introduction to the Symfony Service Container&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services"&gt;Part 4: Symfony Service Container: Using a Builder to create Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/15/symfony-service-container-using-xml-or-yaml-to-describe-services"&gt;Part 5: Symfony Service Container: Using XML or YAML to describe Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/16/symfony-service-container-the-need-for-speed"&gt;Part 6: The Need for Speed&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;During the first five articles of this series on Dependency Injection, we have
progressively introduced the main concepts behind this simple and useful
design pattern. We have also talked about the implementation of a lightweight
PHP container that will be used for Symfony 2.&lt;/p&gt;

&lt;p&gt;But with the introduction of the XML and YAML configuration files, you might
have became a bit sceptic about the performance of the container itself. Even
if services are lazy loading, reading a bunch of XML or YAML files on each
request and creating objects by using introspection is probably not very
efficient in PHP. And because the container is almost always the corner stone
of any application using it, its speed does matter a lot.&lt;/p&gt;

&lt;p&gt;On the one hand, using XML or YAML to describe services and their
configuration is very powerful and flexible:&lt;/p&gt;

&lt;pre class="php"&gt;&amp;lt;container xmlns=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&amp;gt;
  &amp;lt;parameters&amp;gt;
    &amp;lt;parameter &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;mailer.username&amp;quot;&lt;/span&gt;&amp;gt;foo&amp;lt;/parameter&amp;gt;
    &amp;lt;parameter &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;mailer.password&amp;quot;&lt;/span&gt;&amp;gt;bar&amp;lt;/parameter&amp;gt;
    &amp;lt;parameter &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;mailer.class&amp;quot;&lt;/span&gt;&amp;gt;Zend_Mail&amp;lt;/parameter&amp;gt;
  &amp;lt;/parameters&amp;gt;
  &amp;lt;services&amp;gt;
    &amp;lt;service id=&lt;span class="st0"&gt;&amp;quot;mail.transport&amp;quot;&lt;/span&gt; &lt;span class="kw2"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;Zend_Mail_Transport_Smtp&amp;quot;&lt;/span&gt; shared=&lt;span class="st0"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;argument&amp;gt;smtp.gmail.com&amp;lt;/argument&amp;gt;
      &amp;lt;argument type=&lt;span class="st0"&gt;&amp;quot;collection&amp;quot;&lt;/span&gt;&amp;gt;
        &amp;lt;argument &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;auth&amp;quot;&lt;/span&gt;&amp;gt;login&amp;lt;/argument&amp;gt;
        &amp;lt;argument &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&amp;gt;%mailer.username%&amp;lt;/argument&amp;gt;
        &amp;lt;argument &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&amp;gt;%mailer.password%&amp;lt;/argument&amp;gt;
        &amp;lt;argument &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;ssl&amp;quot;&lt;/span&gt;&amp;gt;ssl&amp;lt;/argument&amp;gt;
        &amp;lt;argument &lt;a href="http://www.php.net/key"&gt;&lt;span class="kw3"&gt;key&lt;/span&gt;&lt;/a&gt;=&lt;span class="st0"&gt;&amp;quot;port&amp;quot;&lt;/span&gt;&amp;gt;true&amp;lt;/argument&amp;gt;
      &amp;lt;/argument&amp;gt;
    &amp;lt;/service&amp;gt;
    &amp;lt;service id=&lt;span class="st0"&gt;&amp;quot;mailer&amp;quot;&lt;/span&gt; &lt;span class="kw2"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;%mailer.class%&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;call method=&lt;span class="st0"&gt;&amp;quot;setDefaultTransport&amp;quot;&lt;/span&gt;&amp;gt;
        &amp;lt;argument type=&lt;span class="st0"&gt;&amp;quot;service&amp;quot;&lt;/span&gt; id=&lt;span class="st0"&gt;&amp;quot;mail.transport&amp;quot;&lt;/span&gt; /&amp;gt;
      &amp;lt;/call&amp;gt;
    &amp;lt;/service&amp;gt;
  &amp;lt;/services&amp;gt;
&amp;lt;/container&amp;gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;But, on the other hand, defining the service
container as a plain PHP class gives you the full speed, as seen during the
&lt;a href="http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container"&gt;second article&lt;/a&gt;
of this series:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; Container &lt;span class="kw2"&gt;extends&lt;/span&gt; sfServiceContainer
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/static"&gt;&lt;span class="kw3"&gt;static&lt;/span&gt;&lt;/a&gt; protected &lt;span class="re0"&gt;$shared&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getMailTransportService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;new&lt;/span&gt; Zend_Mail_Transport_Smtp&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'smtp.gmail.com'&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
      &lt;span class="st0"&gt;'auth'&lt;/span&gt;     =&amp;gt; &lt;span class="st0"&gt;'login'&lt;/span&gt;,
      &lt;span class="st0"&gt;'username'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.username'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;,
      &lt;span class="st0"&gt;'password'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.password'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;,
      &lt;span class="st0"&gt;'ssl'&lt;/span&gt;      =&amp;gt; &lt;span class="st0"&gt;'ssl'&lt;/span&gt;,
      &lt;span class="st0"&gt;'port'&lt;/span&gt;     =&amp;gt; &lt;span class="nu0"&gt;465&lt;/span&gt;,
    &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getMailerService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
      &lt;span class="kw1"&gt;return&lt;/span&gt; self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
    &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    &lt;span class="re0"&gt;$class&lt;/span&gt; = &lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; &lt;span class="re0"&gt;$class&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="re0"&gt;$mailer&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setDefaultTransport&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getMailTransportService&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="kw1"&gt;return&lt;/span&gt; self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="re0"&gt;$mailer&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The above code does the bare minimum to provide flexibility thanks to the
configuration variables, and still be very fast.&lt;/p&gt;

&lt;p&gt;How can you have the best of both world? That's quite simply. The Symfony
Dependency Injection component provides yet another built-in dumper: a &lt;strong&gt;PHP
dumper&lt;/strong&gt;. This dumper can convert any service container to plain PHP code.
That's right, it is able to generate the code you could have written by hand
in the first place.&lt;/p&gt;

&lt;p&gt;Let's use again our &lt;code&gt;Zend_Mail&lt;/code&gt; example and for brevity's sake, let's use the
XML definition file created in the previous article:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$loader&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerLoaderFileXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$loader&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;load&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.xml'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$dumper&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerDumperPhp&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$code&lt;/span&gt; = &lt;span class="re0"&gt;$dumper&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;dump&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'class'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'Container'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
file_put_contents&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.php'&lt;/span&gt;, &lt;span class="re0"&gt;$code&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;As for any other dumper, the &lt;code&gt;sfServiceContainerDumperPhp&lt;/code&gt; class takes a
container as its constructor first argument. The &lt;code&gt;dump()&lt;/code&gt; method takes an
array of options, and one of them is the name of the class to generate.&lt;/p&gt;

&lt;p&gt;Here is the generated code:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; Container &lt;span class="kw2"&gt;extends&lt;/span&gt; sfServiceContainer
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  protected &lt;span class="re0"&gt;$shared&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; __construct&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    parent::__construct&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getDefaultParameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getMailTransportService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="re0"&gt;$instance&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; Zend_Mail_Transport_Smtp&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'smtp.gmail.com'&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
      &lt;span class="st0"&gt;'auth'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'login'&lt;/span&gt;,
      &lt;span class="st0"&gt;'username'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getParameter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.username'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,
      &lt;span class="st0"&gt;'password'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getParameter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.password'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,
      &lt;span class="st0"&gt;'ssl'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'ssl'&lt;/span&gt;,
      &lt;span class="st0"&gt;'port'&lt;/span&gt; =&amp;gt; &lt;span class="nu0"&gt;465&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$instance&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getMailerService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="re0"&gt;$class&lt;/span&gt; = &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getParameter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="re0"&gt;$instance&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; &lt;span class="re0"&gt;$class&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="re0"&gt;$instance&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setDefaultTransport&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getMailTransportService&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="re0"&gt;$instance&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getDefaultParameters&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
      &lt;span class="st0"&gt;'mailer.username'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'foo'&lt;/span&gt;,
      &lt;span class="st0"&gt;'mailer.password'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'bar'&lt;/span&gt;,
      &lt;span class="st0"&gt;'mailer.class'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'Zend_Mail'&lt;/span&gt;,
    &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;If you have a closer look at the code generated by the dumper, you will notice
that the code is very similar to the one we wrote by hand.&lt;/p&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  The generated code does not use the shortcut notation to access
  parameters and services to be as fast as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By using the &lt;code&gt;sfServiceContainerDumperPhp&lt;/code&gt; dumper, you can have the best of
both world: the flexibility of the XML or YAML format to describe and
configure your services, and the speed of an optimized and auto-generated PHP
file.&lt;/p&gt;

&lt;p&gt;Of course, as projects have almost always different settings for different
environments, you can of course generate different container classes, based on
the environment or on a debugging setting. Here is a small snippet of PHP code
that illustrates how to build the container dynamically for the very first
request, and use a cached one for all other requests when not in debugging
mode:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$name&lt;/span&gt; = &lt;span class="st0"&gt;'Project'&lt;/span&gt;.&lt;a href="http://www.php.net/md5"&gt;&lt;span class="kw3"&gt;md5&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$appDir&lt;/span&gt;.&lt;span class="re0"&gt;$isDebug&lt;/span&gt;.&lt;span class="re0"&gt;$environment&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="st0"&gt;'ServiceContainer'&lt;/span&gt;;
&lt;span class="re0"&gt;$file&lt;/span&gt; = sys_get_temp_dir&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="st0"&gt;'/'&lt;/span&gt;.&lt;span class="re0"&gt;$name&lt;/span&gt;.&lt;span class="st0"&gt;'.php'&lt;/span&gt;;
&amp;nbsp;
&lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!&lt;span class="re0"&gt;$isDebug&lt;/span&gt; &amp;amp;&amp;amp; &lt;a href="http://www.php.net/file_exists"&gt;&lt;span class="kw3"&gt;file_exists&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$file&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="kw1"&gt;require_once&lt;/span&gt; &lt;span class="re0"&gt;$file&lt;/span&gt;;
  &lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; &lt;span class="re0"&gt;$name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="kw1"&gt;else&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="co1"&gt;// build the service container dynamically&lt;/span&gt;
  &lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="re0"&gt;$loader&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerLoaderFileXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="re0"&gt;$loader&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;load&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.xml'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!&lt;span class="re0"&gt;$isDebug&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="re0"&gt;$dumper&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerDumperPhp&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    file_put_contents&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$file&lt;/span&gt;, &lt;span class="re0"&gt;$dumper&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;dump&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'class'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;That wraps up our tour of the Symfony 2 Dependency Injection Container.&lt;/p&gt;

&lt;p&gt;Before closing this series, I want to show you yet another great feature of
the dumpers. Dumpers can do a lot of different things, and to demonstrate the
decoupling of the implementation of the component, I have implemented a
Graphviz dumper. What for? To help you visualize your services and their
dependencies.&lt;/p&gt;

&lt;p&gt;First, let's see how to use it on our example container:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$dumper&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerDumperGraphviz&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
file_put_contents&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.dot'&lt;/span&gt;, &lt;span class="re0"&gt;$dumper&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;dump&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The Graphviz dumper generates a &lt;code&gt;dot&lt;/code&gt; representation of your container:&lt;/p&gt;

&lt;pre class="php"&gt;digraph sc &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  ratio=&lt;span class="st0"&gt;&amp;quot;compress&amp;quot;&lt;/span&gt;
  node &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;fontsize=&lt;span class="st0"&gt;&amp;quot;11&amp;quot;&lt;/span&gt; fontname=&lt;span class="st0"&gt;&amp;quot;Myriad&amp;quot;&lt;/span&gt; shape=&lt;span class="st0"&gt;&amp;quot;record&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
  edge &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;fontsize=&lt;span class="st0"&gt;&amp;quot;9&amp;quot;&lt;/span&gt; fontname=&lt;span class="st0"&gt;&amp;quot;Myriad&amp;quot;&lt;/span&gt; color=&lt;span class="st0"&gt;&amp;quot;grey&amp;quot;&lt;/span&gt; arrowhead=&lt;span class="st0"&gt;&amp;quot;open&amp;quot;&lt;/span&gt; arrowsize=&lt;span class="st0"&gt;&amp;quot;0.5&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
  node_service_container &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;label=&lt;span class="st0"&gt;&amp;quot;service_container&lt;span class="es0"&gt;\n&lt;/span&gt;sfServiceContainerBuilder&lt;span class="es0"&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, shape=record, fillcolor=&lt;span class="st0"&gt;&amp;quot;#9999ff&amp;quot;&lt;/span&gt;, style=&lt;span class="st0"&gt;&amp;quot;filled&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
  node_mail_transport &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;label=&lt;span class="st0"&gt;&amp;quot;mail.transport&lt;span class="es0"&gt;\n&lt;/span&gt;Zend_Mail_Transport_Smtp&lt;span class="es0"&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, shape=record, fillcolor=&lt;span class="st0"&gt;&amp;quot;#eeeeee&amp;quot;&lt;/span&gt;, style=&lt;span class="st0"&gt;&amp;quot;dotted&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
  node_mailer &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;label=&lt;span class="st0"&gt;&amp;quot;mailer&lt;span class="es0"&gt;\n&lt;/span&gt;Zend_Mail&lt;span class="es0"&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, shape=record, fillcolor=&lt;span class="st0"&gt;&amp;quot;#eeeeee&amp;quot;&lt;/span&gt;, style=&lt;span class="st0"&gt;&amp;quot;filled&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
  node_mailer -&amp;gt; &lt;span class="me1"&gt;node_mail_transport&lt;/span&gt; &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;label=&lt;span class="st0"&gt;&amp;quot;setDefaultTransport()&amp;quot;&lt;/span&gt; style=&lt;span class="st0"&gt;&amp;quot;dashed&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;This representation can be converted to an image by using the
&lt;a href="http://graphviz.org/"&gt;&lt;code&gt;dot&lt;/code&gt; program&lt;/a&gt;:&lt;/p&gt;

&lt;pre class="command-line"&gt;&lt;code&gt;$ dot -Tpng /somewhere/container.dot &amp;gt; /somewhere/container.png
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src="http://fabien.potencier.org/media/articles/di/zend-mail.png" alt="Zend_Mail container PNG representation" /&gt;&lt;/p&gt;

&lt;p&gt;For this simple example, the visualization has no real added value, but as
soon as you start having more than a few services, it can be quite useful...
and beautiful.&lt;/p&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  The Graphviz dumper &lt;code&gt;dump()&lt;/code&gt; method takes a lot of different options
  to tweak the output of the graph. Have a look at the source code to
  discover the default values for each of them:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;code&gt;graph&lt;/code&gt;: The default options for the whole graph&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;node&lt;/code&gt;: The default options for nodes&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;edge&lt;/code&gt;: The default options for edges&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;node.instance&lt;/code&gt;: The default options for services that are defined
  directly by object instances&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;node.definition&lt;/code&gt;: The default options for services that are
  defined via service definition instances&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;node.missing&lt;/code&gt;: The default options for missing services&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a teaser for the next Symfony component that will be released later this
month, here is the graph for an hypothetic CMS using the Symfony 2 new
Templating Framework:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://fabien.potencier.org/media/articles/di/template.png" alt="Symfony 2 Templating Framework" /&gt;&lt;/p&gt;

&lt;p&gt;That's all for this series on Dependency Injection. I hope you have learned
something reading these articles. I also hope you will try the Symfony 2
Service Container component soon and give me feedback about your usage. Also,
if you create "recipes" for some existing Open-Source libraries, consider
sharing them with the community. You can also send them to me and I will host
them along side the container component to ease reusing.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Symfony Service Container: Using XML or YAML to describe Services</title>
  <link href="http://fabien.potencier.org/article/15/symfony-service-container-using-xml-or-yaml-to-describe-services" />
  <id>article-15</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-04-01T09:00:00+02:00</updated>
  <content type="html">
    &lt;blockquote class="note"&gt;&lt;p&gt;
  This article is part of a series on Dependency Injection in general and on a
  lightweight implementation of a Container in PHP in particular:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/11/what-is-dependency-injection"&gt;Part 1: What is Dependency Injection? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container"&gt;Part 2: Do you need a Dependency Injection Container? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container"&gt;Part 3: Introduction to the Symfony Service Container&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services"&gt;Part 4: Symfony Service Container: Using a Builder to create Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/15/symfony-service-container-using-xml-or-yaml-to-describe-services"&gt;Part 5: Symfony Service Container: Using XML or YAML to describe Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/16/symfony-service-container-the-need-for-speed"&gt;Part 6: The Need for Speed&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the &lt;a href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services"&gt;last article&lt;/a&gt;
on Dependency Injection, you learned how to describe services with PHP code by
using the &lt;code&gt;sfServiceContainerBuilder&lt;/code&gt; class. Today, with the help of
service loaders and dumpers, you will learn how to use XML or YAML to describe
your services.&lt;/p&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  The Subversion repository has been updated with the code needed
  for today's tutorial. If you got the code from yesterday's repository,
  ou can just update it (&lt;code&gt;svn up&lt;/code&gt;). If not, the repository is available at
  &lt;code&gt;http://svn.symfony-project.com/components/dependency_injection/trunk/&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Symfony Dependency Injection component provides helper classes that load
services using &lt;strong&gt;"loader objects"&lt;/strong&gt;. By default, the component comes with two
of them: &lt;code&gt;sfServiceContainerLoaderFileXml&lt;/code&gt; to load XML files, and
&lt;code&gt;sfServiceContainerLoaderFileYaml&lt;/code&gt; to load YAML files.&lt;/p&gt;

&lt;p&gt;But before diving into the XML and YAML notations, let's first have a look at
another part of the Symfony Dependency Injection component: the &lt;strong&gt;"dumper
objects"&lt;/strong&gt;. A service dumper takes a container object and convert it to
another format. And of course, the component comes bundled with dumpers for
the XML and YAML formats.&lt;/p&gt;

&lt;p&gt;To introduce the XML format, let's convert yesterday's container service
definitions to a &lt;code&gt;container.xml&lt;/code&gt; file by using the
&lt;code&gt;sfServiceContainerDumperXml&lt;/code&gt; dumper class.&lt;/p&gt;

&lt;p&gt;Remember the code we used to define the &lt;code&gt;Zend_Mail&lt;/code&gt; service?&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;require_once&lt;/span&gt; &lt;span class="st0"&gt;'/PATH/TO/sfServiceContainerAutoloader.php'&lt;/span&gt;;
sfServiceContainerAutoloader::&lt;span class="me2"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mail.transport'&lt;/span&gt;, &lt;span class="st0"&gt;'Zend_Mail_Transport_Smtp'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'smtp.gmail.com'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
    &lt;span class="st0"&gt;'auth'&lt;/span&gt;     =&amp;gt; &lt;span class="st0"&gt;'login'&lt;/span&gt;,
    &lt;span class="st0"&gt;'username'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'%mailer.username%'&lt;/span&gt;,
    &lt;span class="st0"&gt;'password'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'%mailer.password%'&lt;/span&gt;,
    &lt;span class="st0"&gt;'ssl'&lt;/span&gt;      =&amp;gt; &lt;span class="st0"&gt;'ssl'&lt;/span&gt;,
    &lt;span class="st0"&gt;'port'&lt;/span&gt;     =&amp;gt; &lt;span class="nu0"&gt;465&lt;/span&gt;,
  &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;setShared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;false&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;, &lt;span class="st0"&gt;'%mailer.class%'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addMethodCall&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'setDefaultTransport'&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceReference&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mail.transport'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;To convert this container to an XML representation, use the following code:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$dumper&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerDumperXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
file_put_contents&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.xml'&lt;/span&gt;, &lt;span class="re0"&gt;$dumper&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;dump&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;A dumper class constructor takes a service container builder object as its
first argument and the &lt;code&gt;dump()&lt;/code&gt; method introspects the container services and
converts them to another representation. If everything went fine, the
&lt;code&gt;container.xml&lt;/code&gt; file should look like the following XML snippet:&lt;/p&gt;

&lt;pre class="xml"&gt;&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;?xml&lt;/span&gt; &lt;span class="re0"&gt;version&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mailer.username&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;foo&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameter&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mailer.password&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;bar&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameter&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mailer.class&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Zend_Mail&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameter&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;services&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="re0"&gt;id&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mail.transport&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;Zend_Mail_Transport_Smtp&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;shared&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;smtp.gmail.com&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;type&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;collection&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;auth&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;login&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;%mailer.username%&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;%mailer.password%&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;ssl&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;ssl&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;port&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;465&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/service&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="re0"&gt;id&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mailer&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;%mailer.class%&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;call&lt;/span&gt; &lt;span class="re0"&gt;method&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;setDefaultTransport&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;type&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;service&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;id&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mail.transport&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/call&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/service&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/services&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="tip"&gt;&lt;p&gt;
  The XML format supports anonymous services. An anonymous service is a
  service that does not need a name and is defined directly in its use
  context.  It can be very convenient when you need a service that won't
  be used outside of another one scope:&lt;/p&gt;

&lt;pre class="xml"&gt;&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="re0"&gt;id&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;mailer&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;%mailer.class%&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;call&lt;/span&gt; &lt;span class="re0"&gt;method&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;setDefaultTransport&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;type&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;service&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="re0"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;Zend_Mail_Transport_Smtp&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;smtp.gmail.com&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;type&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;collection&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;auth&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;login&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;%mailer.username%&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;%mailer.password%&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;ssl&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;ssl&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;port&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;465&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/service&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/argument&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/call&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/service&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Loading back the container is dead simple thanks to the XML service loader
class:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;require_once&lt;/span&gt; &lt;span class="st0"&gt;'/PATH/TO/sfServiceContainerAutoloader.php'&lt;/span&gt;;
sfServiceContainerAutoloader::&lt;span class="me2"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$loader&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerLoaderFileXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$loader&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;load&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.xml'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;As for dumpers, a loader takes a service container builder as its constructor
first argument, and the &lt;code&gt;load()&lt;/code&gt; method reads the file and registers the
services into the container. The container is then useable as usual.&lt;/p&gt;

&lt;p&gt;If you change the dumper code to use the &lt;code&gt;sfServiceContainerDumperYaml&lt;/code&gt; class
instead, you will have a YAML representation of your services:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;require_once&lt;/span&gt; &lt;span class="st0"&gt;'/PATH/TO/sfYaml.php'&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$dumper&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerDumperYaml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
file_put_contents&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.yml'&lt;/span&gt;, &lt;span class="re0"&gt;$dumper&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;dump&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  This will only work if you first load the sfYAML component
  (&lt;code&gt;http://svn.symfony-project.com/components/yaml/trunk/&lt;/code&gt;) as it is
  required for the service container loader and dumper.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The previous container is represented like follows in YAML:&lt;/p&gt;

&lt;pre&gt;parameters:
  mailer.username: foo
  mailer.password: bar
  mailer.class:    Zend_Mail
&amp;nbsp;
services:
  mail.transport:
    class:     Zend_Mail_Transport_Smtp
    arguments: [smtp.gmail.com, { auth: login, username: %mailer.username%, password: %mailer.password%, ssl: ssl, port: 465 }]
    shared:    false
  mailer:
    class: %mailer.class%
    calls:
      - [setDefaultTransport, [@mail.transport]]
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="sidebar"&gt;&lt;p class="title"&gt;What's the best Format for your Service Definitions?&lt;/p&gt;
  
  &lt;p&gt;Using the XML format gives you several advantages over the YAML one:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;p&gt;When a XML file is loaded, it is automatically validated with the
  built-in &lt;code&gt;services.xsd&lt;/code&gt; file;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;The XML can be auto-completed in IDEs;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;The XML format is faster than the YAML one;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;The XML format as no external dependencies (the YAML format relies
  on the sfYAML component).&lt;/p&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can of course mix and match the loaders and the dumpers to convert any
format to any other one:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="co1"&gt;// Convert an XML container service definitions file to a YAML one&lt;/span&gt;
&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$loader&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerLoaderFileXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$loader&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;load&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.xml'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$dumper&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerDumperYaml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
file_put_contents&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.yml'&lt;/span&gt;, &lt;span class="re0"&gt;$dumper&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;dump&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="tip"&gt;&lt;p&gt;
  To keep this article short, I won't list all possibilities of the YAML
  or XML format. But you can easily learn them by converting an existing
  container and look at the output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using YAML or XML files for configuring your services allows you to create
your services with a GUI (yet to be done...). But it also opens a lot more
interesting possibilities.&lt;/p&gt;

&lt;p&gt;One of the most important one is the ability to import other "resources". A
resource can be any other configuration file:&lt;/p&gt;

&lt;pre class="xml"&gt;&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="re0"&gt;resource&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;default.xml&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- These parameters override the one defined in default.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;services&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- These service definitions override the one defined in default.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/services&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;imports&lt;/code&gt; section lists resources that need to be included before the
other sections are evaluated. By default, it looks for files with a path
relative to the current file, but you can also pass an array of paths to look
in as the second argument of the loader:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$loader&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerLoaderFileXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/another/path'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$loader&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;load&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/container.xml'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;You can even embed a YAML definition file in an XML one by defining the
&lt;code&gt;class&lt;/code&gt; that is able to load the resource:&lt;/p&gt;

&lt;pre class="xml"&gt;&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="re0"&gt;resource&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;default.yml&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;sfServiceContainerLoaderFileYaml&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;And of course, the same goes for the YAML format:&lt;/p&gt;

&lt;pre&gt;imports:
  - { resource: default.xml, class: sfServiceContainerLoaderFileXml }
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;import&lt;/code&gt; facility gives you a flexible way to organize your service
definition files. It is also a great way to share and reuse definition files.
Let's talk about the web session example we introduced in the first article.
When you use web sessions in a test environment, the session storage object
probably need to be mocked; on the contrary, and if you have several
load-balanced web servers, the production environment need to store its
sessions in a database like MySQL. One way to have a different configuration
based on the environment is to create several different configuration files
and import them as needed:&lt;/p&gt;

&lt;pre class="xml"&gt;&lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- in /framework/config/default/session.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;session.class&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;sfSessionStorage&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameter&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- service definitions go here --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
&lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- in /project/config/session_test.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="re0"&gt;resource&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;session.xml&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;session.class&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;sfSessionTestStorage&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameter&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
&lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- in /project/config/session_prod.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="re0"&gt;resource&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;session.xml&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="re0"&gt;key&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;session.class&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;sfMySQLSessionStorage&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameter&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/parameters&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Using the right configuration is trivial:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$loader&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerLoaderFileXml&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
  &lt;span class="st0"&gt;'/framework/config/default/'&lt;/span&gt;,
  &lt;span class="st0"&gt;'/project/config/'&lt;/span&gt;,
&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="re0"&gt;$loader&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;load&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'/somewhere/session_'&lt;/span&gt;.&lt;span class="re0"&gt;$environment&lt;/span&gt;.&lt;span class="st0"&gt;'.xml'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;I can hear people crying about using XML to define the configuration, as XML
is probably not the most readable configuration format on earth. Coming from a
Symfony background, you could have written all the files in the YAML format.
But you can also decouple the service definitions from their configuration. As
you can import files form other ones, you can define services in a
&lt;code&gt;services.xml&lt;/code&gt; file, and store the related configuration in a &lt;code&gt;parameters.xml&lt;/code&gt;
one. You can also define parameters in a YAML file (&lt;code&gt;parameters.yml&lt;/code&gt;).
Eventually, there is a last built-in INI loader that is able to read
parameters from a standard INI file:&lt;/p&gt;

&lt;pre class="xml"&gt;&lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- in /project/config/session_test.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;container&lt;/span&gt; &lt;span class="re0"&gt;xmlns&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;http://symfony-project.org/2.0/container&amp;quot;&lt;/span&gt;&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="re0"&gt;resource&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;config.ini&amp;quot;&lt;/span&gt; &lt;span class="re0"&gt;class&lt;/span&gt;=&lt;span class="st0"&gt;&amp;quot;sfServiceContainerLoaderFileIni&amp;quot;&lt;/span&gt; &lt;span class="re2"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/imports&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="sc3"&gt;&lt;span class="re1"&gt;&amp;lt;/container&lt;span class="re2"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
&lt;span class="sc3"&gt;&lt;span class="coMULTI"&gt;&amp;lt;!-- /project/config/config.ini --&amp;gt;&lt;/span&gt;&lt;/span&gt;
[parameters]
session.class = sfSessionTestStorage
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  It is not possible to define services in an INI file; only parameters
  can be defined and parsed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These examples barely scratches the surface of the container loaders and
dumpers features, but I hope this article has been a good overview of the
power of the XML and YAML formats over the PHP one. And for those who are
sceptic about the performance of a container that needs to load several files
to be configured, I think you will be blown away by the next article. As this
will be the last installment of this series on Dependency Injection, I will
also talk about a nice way to visualize your service dependencies.&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Symfony Service Container: Using a Builder to create Services</title>
  <link href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services" />
  <id>article-14</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-03-31T08:20:00+02:00</updated>
  <content type="html">
    &lt;blockquote class="note"&gt;&lt;p&gt;
  This article is part of a series on Dependency Injection in general and on a
  lightweight implementation of a Container in PHP in particular:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/11/what-is-dependency-injection"&gt;Part 1: What is Dependency Injection? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container"&gt;Part 2: Do you need a Dependency Injection Container? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container"&gt;Part 3: Introduction to the Symfony Service Container&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services"&gt;Part 4: Symfony Service Container: Using a Builder to create Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/15/symfony-service-container-using-xml-or-yaml-to-describe-services"&gt;Part 5: Symfony Service Container: Using XML or YAML to describe Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/16/symfony-service-container-the-need-for-speed"&gt;Part 6: The Need for Speed&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;a href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container"&gt;previous article&lt;/a&gt;
on Dependency Injection, you learned how to use the &lt;code&gt;sfServiceContainer&lt;/code&gt; class
to provide a more appealing interface to your service containers. In this
article, we will go one step further and learn how to leverage the
&lt;code&gt;sfServiceContainerBuilder&lt;/code&gt; class to describe services and their configuration
in pure PHP code.&lt;/p&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  The Subversion repository has been updated with the code needed for this tutorial. If you have
  checkout the code yesterday, you can simple update it. If not, the repository is available at &lt;code&gt;http://svn.symfony-project.com/components/dependency_injection/trunk/&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;sfServiceContainerBuilder&lt;/code&gt; class extends the basic &lt;code&gt;sfServiceContainer&lt;/code&gt;
class and allows the developer to describe services with a simple PHP
interface.&lt;/p&gt;

&lt;blockquote class="sidebar"&gt;&lt;p class="title"&gt;The Service Container Interface&lt;/p&gt;
  
  &lt;p&gt;All service container classes share the same interface, defined in
  &lt;code&gt;sfServiceContainerInterface&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;interface&lt;/span&gt; sfServiceContainerInterface
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; setParameters&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt; &lt;span class="re0"&gt;$parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; addParameters&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt; &lt;span class="re0"&gt;$parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; getParameters&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; getParameter&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; setParameter&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$name&lt;/span&gt;, &lt;span class="re0"&gt;$value&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; hasParameter&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; setService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;, &lt;span class="re0"&gt;$service&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; getService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$id&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; hasService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The description of the services are done by registering service definitions.
Each service definition describes a service: from the class to use to the
arguments to pass to the constructor, and a bunch of other configuration
properties (see the &lt;code&gt;sfServiceDefinition&lt;/code&gt; sidebar below).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Zend_Mail&lt;/code&gt; example can easily be rewritten by removing all the hardcoded
code and building it dynamically with the builder class instead:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;require_once&lt;/span&gt; &lt;span class="st0"&gt;'PATH/TO/sf/lib/sfServiceContainerAutoloader.php'&lt;/span&gt;;
sfServiceContainerAutoloader::&lt;span class="me2"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mail.transport'&lt;/span&gt;, &lt;span class="st0"&gt;'Zend_Mail_Transport_Smtp'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'smtp.gmail.com'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
    &lt;span class="st0"&gt;'auth'&lt;/span&gt;     =&amp;gt; &lt;span class="st0"&gt;'login'&lt;/span&gt;,
    &lt;span class="st0"&gt;'username'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'%mailer.username%'&lt;/span&gt;,
    &lt;span class="st0"&gt;'password'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'%mailer.password%'&lt;/span&gt;,
    &lt;span class="st0"&gt;'ssl'&lt;/span&gt;      =&amp;gt; &lt;span class="st0"&gt;'ssl'&lt;/span&gt;,
    &lt;span class="st0"&gt;'port'&lt;/span&gt;     =&amp;gt; &lt;span class="nu0"&gt;465&lt;/span&gt;,
  &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;setShared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;false&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;, &lt;span class="st0"&gt;'%mailer.class%'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addMethodCall&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'setDefaultTransport'&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceReference&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mail.transport'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The creation of a service is done by calling the &lt;code&gt;register()&lt;/code&gt; method, which
takes the service name and the class name, and returns a &lt;code&gt;sfServiceDefinition&lt;/code&gt;
instance.&lt;/p&gt;

&lt;blockquote class="tip"&gt;&lt;p&gt;
  A service definition is internally represented by an object of
  class &lt;code&gt;sfServiceDefinition&lt;/code&gt;. It is also possible to create one by
  hand and registering it directly by using the service container
  &lt;code&gt;setServiceDefinition()&lt;/code&gt; method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The definition object implements a fluid interface and provides
methods that configure the service. In the above example, we have used the
following ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;addArgument()&lt;/code&gt;: Adds an argument to pass to the service constructor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;setShared()&lt;/code&gt;: Whether the service must be unique for a container or not
(&lt;code&gt;true&lt;/code&gt; by default).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;addMethodCall()&lt;/code&gt;: A method to call after the service has been created.
The second argument is an array of arguments to pass to the method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Referencing a service is now done with a &lt;code&gt;sfServiceReference&lt;/code&gt; instance. This
special object is dynamically replaced with the actual service when the
referencing service is created.&lt;/p&gt;

&lt;p&gt;During the registration phase, no service is actually created, it is just
about the description of the services. The services are only created when you
actually want to work with them. It means you can register the services in any
order without taking care of the dependencies between them. It also means you
can override an existing service definition by re-registering a service with
the same name. That's yet another simple way to override a service for testing
purpose.&lt;/p&gt;

&lt;blockquote class="sidebar"&gt;&lt;p class="title"&gt;The &lt;code&gt;sfServiceDefinition&lt;/code&gt; Class&lt;/p&gt;
  
  &lt;p&gt;A service has several properties that changes the way it is created and
  configured:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setConstructor()&lt;/code&gt;: Sets the static method to use when the service
  is created, instead of the standard &lt;code&gt;new&lt;/code&gt; construct (useful for
  factories).&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setClass()&lt;/code&gt;: Sets the service class.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setArguments()&lt;/code&gt;: Sets the arguments to pass to the constructor (the
  order is of course significant).&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;addArgument()&lt;/code&gt;: Adds an argument for the constructor.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setMethodCalls()&lt;/code&gt;: Sets the service methods to call after
  service creation. These methods are called in the same order as the
  registration.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;addMethodCall()&lt;/code&gt;: Adds a service method call to call after service
  creation. You can add a call to the same method several times if
  needed.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setFile()&lt;/code&gt;: Sets a file to include before creating a service
  (useful if the service class if not autoloaded).&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setShared()&lt;/code&gt;: Whether the service must be unique for a container or
  not (&lt;code&gt;true&lt;/code&gt; by default).&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;code&gt;setConfigurator()&lt;/code&gt;: Sets a PHP callable to call after the service
  has been configured.&lt;/p&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;As the &lt;code&gt;sfServiceContainerBuilder&lt;/code&gt; class implements the standard
&lt;code&gt;sfServiceContainerInterface&lt;/code&gt; interface, using the service container does not
need to be changed:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;addParameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
  &lt;span class="st0"&gt;'mailer.username'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'foo'&lt;/span&gt;,
  &lt;span class="st0"&gt;'mailer.password'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'bar'&lt;/span&gt;,
  &lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;    =&amp;gt; &lt;span class="st0"&gt;'Zend_Mail'&lt;/span&gt;,
&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;mailer&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;sfServiceContainerBuilder&lt;/code&gt; is able to describe any object instantiation
and configuration. We have demonstrated it with the &lt;code&gt;Zend_Mail&lt;/code&gt; class, and
here is another example using the &lt;code&gt;sfUser&lt;/code&gt; class from Symfony:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceContainerBuilder&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
  &lt;span class="st0"&gt;'storage.class'&lt;/span&gt;        =&amp;gt; &lt;span class="st0"&gt;'sfMySQLSessionStorage'&lt;/span&gt;,
  &lt;span class="st0"&gt;'storage.options'&lt;/span&gt;      =&amp;gt; &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'database'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'session'&lt;/span&gt;, &lt;span class="st0"&gt;'db_table'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'session'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,
  &lt;span class="st0"&gt;'user.class'&lt;/span&gt;           =&amp;gt; &lt;span class="st0"&gt;'sfUser'&lt;/span&gt;,
  &lt;span class="st0"&gt;'user.default_culture'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'en'&lt;/span&gt;,
&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'dispatcher'&lt;/span&gt;, &lt;span class="st0"&gt;'sfEventDispatcher'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'storage'&lt;/span&gt;, &lt;span class="st0"&gt;'%storage.class%'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'%storage.options%'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'user'&lt;/span&gt;, &lt;span class="st0"&gt;'%user.class%'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceReference&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'dispatcher'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;new&lt;/span&gt; sfServiceReference&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'storage'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
  &lt;span class="me1"&gt;addArgument&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'default_culture'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'%user.default_culture%'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;-&amp;gt;
;
&amp;nbsp;
&lt;span class="re0"&gt;$user&lt;/span&gt; = &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;user&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  In the Symfony example, even if the storage object takes an
  array of options as an argument, we passed a string placeholder
  (&lt;code&gt;addArgument('%storage.options%')&lt;/code&gt;). The container is smarter enough
  to actually pass an array, the value of the placeholder.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's all for today. Using PHP code to describe the services is quite simple
and powerful. It gives you a tool to create your container without duplicating
too much code and to abstract objects instantiation and configuration. In the
next article, we will see how services can also be described with XML or YAML
files. Stay tuned!&lt;/p&gt;
  </content>
</entry>
      <entry>
  <title>Introduction to the Symfony Service Container</title>
  <link href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container" />
  <id>article-13</id>
  <author>
    <name>Fabien Potencier</name>
    <author_email>fabien.potencier@sensio.com</author_email>
  </author>
  <updated>2009-03-30T12:30:00+02:00</updated>
  <content type="html">
    &lt;blockquote class="note"&gt;&lt;p&gt;
  This article is part of a series on Dependency Injection in general and on a
  lightweight implementation of a Container in PHP in particular:&lt;/p&gt;
  
  &lt;ul&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/11/what-is-dependency-injection"&gt;Part 1: What is Dependency Injection? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container"&gt;Part 2: Do you need a Dependency Injection Container? &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container"&gt;Part 3: Introduction to the Symfony Service Container&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/14/symfony-service-container-using-a-builder-to-create-services"&gt;Part 4: Symfony Service Container: Using a Builder to create Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/15/symfony-service-container-using-xml-or-yaml-to-describe-services"&gt;Part 5: Symfony Service Container: Using XML or YAML to describe Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fabien.potencier.org/article/16/symfony-service-container-the-need-for-speed"&gt;Part 6: The Need for Speed&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Until now in this series on Dependency Injection, we have talked about general
concepts. The first two introductory articles were important to better
understand the implementation we will talk about in this article and in the
following ones. It is now time to dive into the Symfony 2 service container
implementation.&lt;/p&gt;

&lt;p&gt;The Dependency Injection Container in Symfony is managed by a class named
&lt;code&gt;sfServiceContainer&lt;/code&gt;. It is a very lightweight class that implements the basic
features we talked about in the last article.&lt;/p&gt;

&lt;blockquote class="note"&gt;&lt;p&gt;
  The Symfony Service Container is available as a standalone
  component in the symfony official Subversion repository:
  &lt;code&gt;http://svn.symfony-project.com/components/dependency_injection/trunk/&lt;/code&gt;. Keep in
  mind that this component is still under heavy development, which means
  that things can change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Symfony speak, &lt;em&gt;a service is any object managed by the container&lt;/em&gt;. In the
&lt;code&gt;Zend_Mail&lt;/code&gt; example from the last article, we had two of them: the &lt;code&gt;mailer&lt;/code&gt;
service and the &lt;code&gt;mail_transport&lt;/code&gt; service:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; Container
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/static"&gt;&lt;span class="kw3"&gt;static&lt;/span&gt;&lt;/a&gt; protected &lt;span class="re0"&gt;$shared&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  protected &lt;span class="re0"&gt;$parameters&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; __construct&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt; &lt;span class="re0"&gt;$parameters&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;parameters&lt;/span&gt; = &lt;span class="re0"&gt;$parameters&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; getMailTransport&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;new&lt;/span&gt; Zend_Mail_Transport_Smtp&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'smtp.gmail.com'&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
      &lt;span class="st0"&gt;'auth'&lt;/span&gt;     =&amp;gt; &lt;span class="st0"&gt;'login'&lt;/span&gt;,
      &lt;span class="st0"&gt;'username'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.username'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;,
      &lt;span class="st0"&gt;'password'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.password'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;,
      &lt;span class="st0"&gt;'ssl'&lt;/span&gt;      =&amp;gt; &lt;span class="st0"&gt;'ssl'&lt;/span&gt;,
      &lt;span class="st0"&gt;'port'&lt;/span&gt;     =&amp;gt; &lt;span class="nu0"&gt;465&lt;/span&gt;,
    &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  &lt;span class="kw2"&gt;public&lt;/span&gt; &lt;span class="kw2"&gt;function&lt;/span&gt; getMailer&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
      &lt;span class="kw1"&gt;return&lt;/span&gt; self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
    &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    &lt;span class="re0"&gt;$class&lt;/span&gt; = &lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; &lt;span class="re0"&gt;$class&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="re0"&gt;$mailer&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setDefaultTransport&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getMailTransport&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="kw1"&gt;return&lt;/span&gt; self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="re0"&gt;$mailer&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;If we make the &lt;code&gt;Container&lt;/code&gt; class extend the &lt;code&gt;sfServiceContainer&lt;/code&gt; Symfony
class, we can simplify the code a bit:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw2"&gt;class&lt;/span&gt; Container &lt;span class="kw2"&gt;extends&lt;/span&gt; sfServiceContainer
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/static"&gt;&lt;span class="kw3"&gt;static&lt;/span&gt;&lt;/a&gt; protected &lt;span class="re0"&gt;$shared&lt;/span&gt; = &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getMailTransportService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;new&lt;/span&gt; Zend_Mail_Transport_Smtp&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'smtp.gmail.com'&lt;/span&gt;, &lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
      &lt;span class="st0"&gt;'auth'&lt;/span&gt;     =&amp;gt; &lt;span class="st0"&gt;'login'&lt;/span&gt;,
      &lt;span class="st0"&gt;'username'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.username'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;,
      &lt;span class="st0"&gt;'password'&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.password'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;,
      &lt;span class="st0"&gt;'ssl'&lt;/span&gt;      =&amp;gt; &lt;span class="st0"&gt;'ssl'&lt;/span&gt;,
      &lt;span class="st0"&gt;'port'&lt;/span&gt;     =&amp;gt; &lt;span class="nu0"&gt;465&lt;/span&gt;,
    &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  protected &lt;span class="kw2"&gt;function&lt;/span&gt; getMailerService&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
  &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
    &lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
    &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
      &lt;span class="kw1"&gt;return&lt;/span&gt; self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
    &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    &lt;span class="re0"&gt;$class&lt;/span&gt; = &lt;span class="re0"&gt;$this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; &lt;span class="re0"&gt;$class&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
    &lt;span class="re0"&gt;$mailer&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setDefaultTransport&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$this&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getMailTransportService&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
    &lt;span class="kw1"&gt;return&lt;/span&gt; self::&lt;span class="re0"&gt;$shared&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="re0"&gt;$mailer&lt;/span&gt;;
  &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;That's not much, but it will give us a more powerful and clean interface. Here
is the main changes we made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The method names have been suffixed with &lt;code&gt;Service&lt;/code&gt;. By convention, a
service is to be defined by a method prefixed by &lt;code&gt;get&lt;/code&gt; and suffixed by
&lt;code&gt;Service&lt;/code&gt;. Each service has a unique identifier, which is the underscored
version of the method name without the prefix and suffix. By defining a
&lt;code&gt;getMailTransportService()&lt;/code&gt; method, we have defined a service named
&lt;code&gt;mail_transport&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The methods are now protected. We will see in a minute how to retrieve
services from the container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The container can be used as an array to get parameter values
(&lt;code&gt;$this['mailer.class']&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote class="tip"&gt;&lt;p&gt;
  A service identifier must be unique and must be made of letters,
  numbers, underscores, and dots.  Dots are useful to define
  "namespaces" within your container (for instance &lt;code&gt;mail.mailer&lt;/code&gt; and
  &lt;code&gt;mail.transport&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see how to use the new container class:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;require_once&lt;/span&gt; &lt;span class="st0"&gt;'PATH/TO/sf/lib/sfServiceContainerAutoloader.php'&lt;/span&gt;;
sfServiceContainerAutoloader::&lt;span class="me2"&gt;register&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt; = &lt;span class="kw2"&gt;new&lt;/span&gt; Container&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span class="kw3"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;
  &lt;span class="st0"&gt;'mailer.username'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'foo'&lt;/span&gt;,
  &lt;span class="st0"&gt;'mailer.password'&lt;/span&gt; =&amp;gt; &lt;span class="st0"&gt;'bar'&lt;/span&gt;,
  &lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;    =&amp;gt; &lt;span class="st0"&gt;'Zend_Mail'&lt;/span&gt;,
&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;mailer&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;

&lt;p&gt;Now, because the &lt;code&gt;Container&lt;/code&gt; class extends the &lt;code&gt;sfServiceContainer&lt;/code&gt; class, we
can enjoy a cleaner interface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Services are accessible via a uniform interface:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;hasService&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getService&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setService&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer'&lt;/span&gt;, &lt;span class="re0"&gt;$mailer&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a shortcut, services are also accessible by using the class property
notation:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;mailer&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="re0"&gt;$mailer&lt;/span&gt; = &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;mailer&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;mailer&lt;/span&gt; = &lt;span class="re0"&gt;$mailer&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters are accessible via a uniform interface:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;hasParameter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer_class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setParameter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer_class'&lt;/span&gt;, &lt;span class="st0"&gt;'Zend_Mail'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;a href="http://www.php.net/echo"&gt;&lt;span class="kw3"&gt;echo&lt;/span&gt;&lt;/a&gt; &lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;getParameter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'mailer_class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="co1"&gt;// Override all parameters of the container&lt;/span&gt;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;setParameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;
&lt;span class="co1"&gt;// Adds parameters&lt;/span&gt;
&lt;span class="re0"&gt;$sc&lt;/span&gt;-&amp;gt;&lt;span class="me1"&gt;addParameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$parameters&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a shortcut, parameters are also accessible by using the container like
an array:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;if&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!&lt;a href="http://www.php.net/isset"&gt;&lt;span class="kw3"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = &lt;span class="st0"&gt;'Zend_Mail'&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;span class="re0"&gt;$mailerClass&lt;/span&gt; = &lt;span class="re0"&gt;$sc&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="st0"&gt;'mailer.class'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can also iterate over all services of a container:&lt;/p&gt;

&lt;pre class="php"&gt;&lt;span class="kw1"&gt;foreach&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$sc&lt;/span&gt; &lt;span class="kw1"&gt;as&lt;/span&gt; &lt;span class="re0"&gt;$id&lt;/span&gt; =&amp;gt; &lt;span class="re0"&gt;$service&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;
&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;
  &lt;a href="http://www.php.net/echo"&gt;&lt;span class="kw3"&gt;echo&lt;/span&gt;&lt;/a&gt; &lt;a href="http://www.php.net/sprintf"&gt;&lt;span class="kw3"&gt;sprintf&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;Service %s is an instance of %s.&lt;span class="es0"&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;, &lt;span class="re0"&gt;$id&lt;/span&gt;, &lt;a href="http://www.php.net/get_class"&gt;&lt;span class="kw3"&gt;get_class&lt;/span&gt;&lt;/a&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;$service&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the &lt;code&gt;sfServiceContainer&lt;/code&gt; class is very useful when you have a very small
number of services to manage; even if you still need to do a lot of groundwork
yourself, and duplicate a lot of code. But, if the number of services to be
managed starts to grow beyond a few of them, we need a better way to describe
the services.&lt;/p&gt;

&lt;p&gt;That's why, most of the time, you don't use the &lt;code&gt;sfServiceContainer&lt;/code&gt; class
directly. It was nonetheless important to take some time to describe it as it
is the corner stone of the Symfony dependency injection container
implementation.&lt;/p&gt;

&lt;p&gt;In the next article, we will have a look at the &lt;code&gt;sfServiceContainerBuilder&lt;/code&gt;
class, which eases the service definition process.&lt;/p&gt;
  </content>
</entry>
  </feed>
