<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Richard Miller]]></title><description><![CDATA[It's mainly all Symfony2 stuff and dependency injection related rants]]></description><link>https://richardmiller.co.uk/</link><image><url>https://richardmiller.co.uk/favicon.png</url><title>Richard Miller</title><link>https://richardmiller.co.uk/</link></image><generator>Ghost 3.40</generator><lastBuildDate>Mon, 14 Dec 2020 17:36:28 GMT</lastBuildDate><atom:link href="https://richardmiller.co.uk/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Value Objects and Immutability]]></title><description><![CDATA[Immutability is often given as a core aspect of value objects. There is good reason for this but it is not immutability that make an object a value object. ]]></description><link>https://richardmiller.co.uk/2014/11/21/value-objects-and-immutability/</link><guid isPermaLink="false">5e3825edde21b10018bb82a2</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Fri, 21 Nov 2014 08:56:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Following on from my <a href="https://richardmiller.co.uk/2014/11/06/value-objects/">previous post on value objects</a>,<br>
immutability is often given as a core aspect of value objects. There is good reason for this, but it is not immutability that make an object a value object. It is equality based on value not identity that is essential.</p>
<p>That said, immutability makes sense for the domain concept in most cases. Going back to the Takeaway example from my previous post and the Distance value object used for the radius of the DeliveryArea. If the delivery area was expanded then it would be to a new distance, the distance itself would not change. If the radius was 5km and it was increased to 8km then it is a different distance, 5km is still 5km, it's just that the radius is now 8km.</p>
<p>In fact, since we are thinking like that, the DeliveryArea itself is a different delivery area if we change the distance. So it makes sense to set the delivery area property of the Takeaway to a new DeliveryArea rather than mutate the existing DeliveryArea.</p>
<p>So how do we implement this? The objects are immutable as they stand anyway. They are constructed with values and there is no way of mutating these from outside. Where we need something more that this though is if, rather than just changing the distance, we wanted to be able to add to it. For example, if we have a distance of 5km and we want to add 1 km to this. We could do this externally to the value object by getting its current value adding the new value to this and then creating a new one. We could simplify this though by getting telling the object what you want to add to it and it returning a new object with the total:</p>
<pre><code class="language-php">class Distance  
{
    private $quantity;
    private $unit;

    public function __construct($quantity, $unit)
    {
        $this-&gt;quantity = $quantity;
        $this-&gt;unit = $unit;        
    }

    public function equals(Distance $toCompare)
    {
        return $this-&gt;quantity == $toCompare-&gt;quantity
           &amp;&amp; $this-&gt;unit == $toCompare-&gt;unit;
    }
    
    public function add(Distance $toAdd)
    {
    	if ($this-&gt;unit != $toAdd-&gt;unit) {
        	throw new \RuntimeException(
            	'Cannot add distances with different units'
            );
        }
        
        return new Distance(
	        $this-&gt;quantity + $toAdd-&gt;quantity,
            $this-&gt;unit
        );
    }
}
</code></pre>
<p>There may be times though when an object is immutable in terms of the domain but technical constraints mean that it is not actual immutable. This is can occur when construction needs to be done through setter methods in order to allow integration with something else, such as a framework's way of constructing objects from a form. Whilst we want to stay decoupled from frameworks as much as possible, value objects can still be something that are used at the boundaries between the model and the framework. In this case it may make sense to make it mutable to avoid jumping through hoops. It can still then be treated as immutable within the domain model.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Value Objects]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Since <a href="https://twitter.com/phpvalueobjects">PHP Value Objects</a> is now a thing, I thought I’d write about them as well. You may also want to read <a href="http://kacper.gunia.me/blog/ddd-building-blocks-in-php-value-object">http://kacper.gunia.me/blog/ddd-building-blocks-in-php-value-object</a> and <a href="http://kacper.gunia.me/blog/validating-value-objects">http://kacper.gunia.me/blog/validating-value-objects</a>.</p>
<p>So Value Objects are objects that are considered equal based on their values and</p>]]></description><link>https://richardmiller.co.uk/2014/11/06/value-objects/</link><guid isPermaLink="false">5e3825edde21b10018bb82a1</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Thu, 06 Nov 2014 09:06:14 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Since <a href="https://twitter.com/phpvalueobjects">PHP Value Objects</a> is now a thing, I thought I’d write about them as well. You may also want to read <a href="http://kacper.gunia.me/blog/ddd-building-blocks-in-php-value-object">http://kacper.gunia.me/blog/ddd-building-blocks-in-php-value-object</a> and <a href="http://kacper.gunia.me/blog/validating-value-objects">http://kacper.gunia.me/blog/validating-value-objects</a>.</p>
<p>So Value Objects are objects that are considered equal based on their values and not on identity. For the sake of having an example, let’s say that our domain is ordering takeaway food for delivery. So within this we have the concept of a Takeaway as a place we can order food from. Since that is what we call them here even if they only deliver food, for, er, reasons.</p>
<p>Typically we would model this with an entity and not a value object. This does indeed fit well since equality between two takeaways is not determined by value. For now, let's assume the only property they have are their names. If we have two takeaways with the same name they are not the same takeaway:</p>
<pre><code class="language-language-php">new Takeaway('Thai Tantic') != new Takeaway('Thai Tantic');
</code></pre>
<p>A takeaway that changes its name can still be the same takeaway:</p>
<pre><code class="language-language-php">$takeaway = new Takeaway('Wok around the clock');
$takeaway-&gt;changeName('Wok this way');
</code></pre>
<p>So if we are deciding whether they are equal we have some identity beyond just values such as its name.</p>
<p>If we consider just the name itself though then two names are the same if they are the same value. This is clearly true with strings:</p>
<pre><code class="language-language-php">'Lord of the Fries' == 'Lord of the Fries';
'Man Fryday' != 'The Codfather';
</code></pre>
<p>If we created an object to encapsulate the name then this needs not have identity but can just be consider equal if the value is the same:</p>
<pre><code class="language-language-php">new TakeawayName('Just Falafs') 
    == new TakeawayName('Just Falafs');
new TakeawayName('Abra Kebabra')
    != new TakeawayName('Jason Donnervan');
</code></pre>
<p>So if we want to model the Takeaway's name as an object then a value object is a good fit. Some value objects, such as the TakeawayName are about single values but trying to focus on the benefits of making that an object are perhaps a little misleading. Instead let's look at where we might want a value object to have more than one property.</p>
<p>So what other properties might our Takeaway entity have if it just stores them as primitive values? One important domain concept is the area that they will deliver to. For now let’s say assume a simplistic concept of this where it is determined by the location and a distance from that location. This will then form a circle which they will deliver within. The distance can be provided in kilometers or miles as well so we will need to know which it is. So we have the following:</p>
<pre><code class="language-language-php">class Takeaway
{
    //...
    private $long;
    private $lat;
    private $distanceQuantity;
    private $distanceUnits;    
}
</code></pre>
<p>So let’s consider the distance. This is made up of two values, the unit of measurement and the amount of that measurement. The amount alone e.g. 6 is not a distance. The unit of distance e.g. km is not a distance. 6 km is a distance.</p>
<p>Both need to be equal for a distance to be considered equal:</p>
<ul>
<li>5 km = 5 km</li>
<li>5km != 5cm</li>
<li>5Km != 8km</li>
</ul>
<p>So using primitives as two separate fields in the Takeaway entity is not fulling capturing the connection between these values. It is possible to change just the unit or just the quantity which does not seem like the correct behaviour. Instead we can extract an object that represents a distance, then we can change the whole distance object instead.</p>
<pre><code class="language-language-php">class Distance
{
    private $quantity;
    private $unit;
    
    public function __construct($quantity, $unit)
    {
        $this-&gt;quantity = $quantity;
        $this-&gt;unit = $unit;        
    }
    
    public function equals(Distance $toCompare)
    {
        return $this-&gt;quantity == $toCompare-&gt;quantity
           &amp;&amp; $this-&gt;unit == $toCompare-&gt;unit;
    }
}
</code></pre>
<pre><code class="language-language-php">class Takeaway
{
    //...
    private $long;
    private $lat;
    /**
     * @var Distance
     */
    private $distance;
}
</code></pre>
<p>Likewise lat and long as separate properties don’t seem right, what we are really interested in is the location they determine. So let’s make that an object as well and make the reason we are interested in these values more explicit in our model.</p>
<pre><code class="language-language-php">class Location
{
    private $long;
    private $lat;
    
    public function __construct($long, $lat)
    {
        $this-&gt;long = $long;
        $this-&gt;lat = $lat;        
    }
    
    public function equals(Location $toCompare)
    {
        return $this-&gt;long == $toCompare-&gt;long
           &amp;&amp; $this-&gt;lat == $toCompare-&gt;lat;
    }
}
</code></pre>
<pre><code class="language-language-php">class Takeaway
{
    //...
    /**
     * @var Location
     */    
    private $location;

    /**
     * @var Distance
     */
    private $distance;
}
</code></pre>
<p>So value objects need not wrap a single primitive value. As well as this, value objects do not need to just contain primitives. What we are really interested in here is the area the company are willing to deliver to. The distance and location do not capture and make explicit this concept in out code. So let’s extract an object that represents the area covered. This can be made up of the location and distance value objects and not have any primitive values itself.</p>
<pre><code class="language-language-php">class DeliveryArea
{
    private $location;
    private $radius;
    
    public function __construct(Location $location, Distance $radius)
    {
        $this-&gt;location = $location;
        $this-&gt;radius = $radius;
    }
    
    public function equals(DeliveryArea $toCompare)
    {
        return $this-&gt;location-&gt;equals($toCompare-&gt;location) &amp;&amp; $this-&gt;radius-&gt;equals($toCompare-&gt;radius);
    }
}
</code></pre>
<pre><code class="language-language-php">class Takeaway
{
    //...
    /**
     * @var DeliveryArea
     */    
    private $areaCovered;
}
</code></pre>
<p>Going back to the start again, these are value objects because there equality is determined by values and not by identity. The area covered still has no identity, we can swap it with another object with the same values without any issues. None of this says anything about behviour though; being a value object does not mean having no behaviour and just values.</p>
<p>So if we have a location and we want to find out if the company will deliver to it then we can ask the company object:</p>
<pre><code class="language-language-php">class Takeaway
{
    //...
    /**
     * @var DeliveryArea
     */    
    private $areaCovered;
    
    public function deliversTo(Location $location)
    {
    	//determine if location falls within the area covered.
    }
}
</code></pre>
<p>This method could calculate whether the location falls in the area itself but it would be simpler to just ask the Area object if the location falls in it:</p>
<pre><code class="language-language-php">class Takeaway
{
    //...
    /**
     * @var DeliveryArea
     */    
    private $areaCovered;
    
    public function deliversTo(Location $location)
    {
    	return $this-&gt;areaCovered-&gt;includes($location);
    }
}
</code></pre>
<p>Not only can the value object have behaviour but it attracts it. It is better for the DeliveryArea to decide whether the Location is included or not than have the Takeaway reach into the DeliveryArea to get its values and make the decision. This breaks encapsulation and by making it a method on the DeliveryArea it can be called from elsewhere. Putting the logic involved in checking in the Takeaway ties it to the wrong object.</p>
<p>So our company object now just has an AreaCovered object and a method that delegates to it for deciding if a location is within it. One thing that stands out here is that the company no longer knows anything about what that Area is or what the location is. When we started they were tied to lat, long, and a radius. Should alternative ways of identifying locations and areas - e.g. a list of postcodes that is covered then nothing needs changing in the company object to support this. Different implementations of the Location and AreaCovered objects could be used for this. We could extract interfaces for Location and AreaCovered and have different implementations without changing the Takeaway entity at all.</p>
<p>This encapsulation of data and polymorphism are the benefits of OO. If we just had the company object with primitives and that had the logic of deciding is a location was covered then supporting different area and location types would be much more difficult. We have introduced more objects, where each one is in itself very simple.</p>
<p>As well as this, the company object’s level of abstraction is higher now. We can see that it has an area that is covered and that we can find out whether a location falls in it. For many purposes this may be all we need to know when reading the code. We need not concern ourselves with the detail of how these things are implemented. Without this level of abstraction we would see that a company has a latitude, a longitude, a distance amount and a distance unit and some logic around these value. This tells us too much about the detail and not enough about the purpose and this will only get worse if we want to support more ways of representing these things.</p>
<p>So value objects are useful for encapsulating data and exposing related behavior. Well, yes, but that’s not specific to value objects that <strong>is</strong> Object Orientation.</p>
<p>So what about immutability and validation? Well they are not unimportant but they are not what value objects are primarily about. Objects are about encapsulation and polymorphism. Value objects are the subset of objects where equality is determined by value and not identity.</p>
<p>More on those things soon anyway.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[The new Symfony Best Practices]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Yesterday the initial preview of the new <a href="http://symfony.com/doc/current/best_practices/index.html">Symfony Best Practices</a> was made available. A document like this is something that the Symfony community has needed. It is a much appreciated effort by those involved in producing this. The <a href="http://symfony.com/doc/current/index.html">existing documentation</a> is great but in order to introduce individual concepts it</p>]]></description><link>https://richardmiller.co.uk/2014/10/14/the-new-symfony-best-practices/</link><guid isPermaLink="false">5e3825edde21b10018bb829f</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Tue, 14 Oct 2014 10:15:28 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Yesterday the initial preview of the new <a href="http://symfony.com/doc/current/best_practices/index.html">Symfony Best Practices</a> was made available. A document like this is something that the Symfony community has needed. It is a much appreciated effort by those involved in producing this. The <a href="http://symfony.com/doc/current/index.html">existing documentation</a> is great but in order to introduce individual concepts it is necessary to simplify things whether it is the concept being introduced or others to avoid being sidetracked and bogged down in details other than the one at hand.</p>
<p>Symfony is a powerful, flexible framework which favours configuration over convention in general. There are conventions which can be followed in some cases but configured different if you have a particular need to. This means that it can be confusing for those moving from first starting out learning the framework into building applications with it. Faced with a lot of decisions which options should they choose?</p>
<p>The new best practices document does a good job of providing this next step. I have seen a lot of Symfony applications that would have been vastly improved had this guide been followed by those developing it. It has however not been entirely well received by the community with many questioning whether things in it are really best practices.</p>
<p>It was developed not by the community as a whole but by a fairly small group before being released. This in itself has made it difficult for some to accept but it was probably necessary if anything was ever going to be complete given the disagreements about content that would have made developing it openly a torturous process. Those involved in writing it are very well placed to have an in depth knowledge of the framework and a wealth of experience in creating applications with it. The repository for the document is to be opened up soon anyway so this will not be the case as it evolves.</p>
<p>I think there are some changes to it that could have and could continue to avoid some of the controversy and to better explain the purpose of the document. There are plenty of articles on why “best practices” is not a good name for documents like this. I won’t regurgitate them here but it being misleading that they are the one true way to do things and therefore anything else is inferior is a concern. Another is that best implies that there is little room for improvement. Whilst there are disclaimers included early on to say that these are optional and personal opinion a change of name would make this clearer.</p>
<p>The document opens by talking about how Symfony is suitable for a whole range of applications sizes and complexities up to enterprise software. I think this is true but that much of what follows makes a lot of assumptions about the nature of the application being built and only applies in those circumstances. Yes, a lot of applications built with Symfony will be relatively simple, database backed, CRUD applications. However there are many applications that this does not describe. A not inconsiderable number of people are using Symfony to build APIs, perhaps with a separate website frontend using a client side framework to communicate to this API. In that case many of the practices are not relevant or counter productive. Likewise many people do work on applications that communicate with other systems via HTTP clients, message queues and other means. These are not merely fringe cases and dealing with the complexity of multiple and potentially changing data sources is a real day to day issue for many not just an academic concern.</p>
<p>Making it clear that these are guidelines for building a certain type of application and not suitable in all cases would be good improvement in my opinion. Even better would be to provide some guidelines for working on applications outside of this relatively narrow remit. It is when moving past that point that a lot of questions about what approach to take arise in my experience.</p>
<p>In terms of specific content, there is some I disagree with but that is neither here nor there really. I do find that there is currently some confusion in it as to what the priority is. There are always factors pulling in different directions when building an application. Which of these are important depends on the individual application and the context it is being developed in.</p>
<p>Convenience and speed of development are important but can be odds with performance. Making full use of the short cuts and conventions that the framework provides doesn’t always fit well with making sure that it can be understood and maintained by some that lacks that in depth framework specific knowledge. The best practices seem a little muddled on this, param converters are good because they save time and boilerplate code but the @Template annotation is bad because some prior knowledge is needed and there is a performance issue. I don’t see there being much of a difference in the amount of prior knowledge required in each case. The performance issue of @Template may be a concern but depending on the project this may be less of a concern than the amount of developer time it saves.</p>
<p>Rather than single a single one as being the best, it may be better to say which is better for performance, for convenience or for clarity, when these pull in different directions. This still gives  a clear recommendation to someone who knows which of these is more important to their application.</p>
<p>There is something I see no reason not to change to improve the perception of this document amongst the existing community and to avoid giving a bad impression to newcomers. That is the use of some unnecessarily inflammatory and opinionated language. The first thing that jumps out and no doubt was what rubbed a lot of people up the wrong way was the second paragraph:</p>
<p>“These community resources - like blog posts or presentations - have created an unofficial set of recommendations for developing Symfony applications. Unfortunately, a lot of these recommendations are in fact wrong.”</p>
<p>If this document is, as it states immediately after this, a subjective opinion then opening by dismissing a huge collective effort from the community as “in fact wrong” seems completely out of place in a document of this nature.</p>
<p>Likewise when talking about decoupling controllers then this does not seem like a calm and measured argument:</p>
<p>“And since your controllers should be thin and contain nothing more than a few lines of glue-code, spending hours trying to decouple them from your framework doesn't benefit you in the long run. The amount of time wasted isn't worth the benefit.”</p>
<p>Some people may benefit from doing this and saying that this is wasted time seems unnecessarily antagonistic attack on those with opposing views. The same advice could be presented in a much more neutral way in my opinion. There are better places for strong personal feelings about this topic to be shared.</p>
<p>So to reiterate, I think this is a much needed document and the effort that has gone into getting it to us is much appreciated. I personally think it could benefit from a change of name and some clarity about the nature of the applications it is suitable for. In some places it could be a bit less prescriptive and instead make recommendations based on the application’s needs and context. Longer terms further guidelines that cover some of the wider picture of different application being created with Symfony would be great. However, I do see no reason not to remove some of the more emotional and inflammatory language as soon as possible.</p>
<p>The repository is to be made public so that the community can contribute. I hope that this can be productive and further improve the excellent documentation that Symfony already  benefits from.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Some, no doubt unoriginal, thoughts on BDD]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>BDD is primarily about designing object behaviour and interaction and not about testing. It does however produce a suite of regression tests as a side effect. This has value in allowing us to refactor code knowing that it still behaves as specified.</p>
<p>One issue people have with (T|B)DD</p>]]></description><link>https://richardmiller.co.uk/2014/10/13/some-no-doubt-unoriginal-thoughts-on-bdd/</link><guid isPermaLink="false">5e3825edde21b10018bb829e</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Mon, 13 Oct 2014 18:41:29 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>BDD is primarily about designing object behaviour and interaction and not about testing. It does however produce a suite of regression tests as a side effect. This has value in allowing us to refactor code knowing that it still behaves as specified.</p>
<p>One issue people have with (T|B)DD is that it then makes it difficult to change things as you have lots of tests/specs to change. If the behaviour is changing then they should change. So is this a red herring? Well not exactly, this only holds true if you use only use them to specify the external behaviour at a boundary. For example, from the DDD world, an aggregate boundary.</p>
<p>If inside that boundary there are multiple objects and how they communicate is essentially an implementation detail then specs for these may well get in the way when refactoring the implementation within that boundary. The behaviour of the objects implementing maybe changing a lot without the external boundary changing.</p>
<p>It seems one view is that you should therefore avoid writing them in the first place and another is that this is the right thing to do and you should just maintain them and live with this. So, does this mean that you should not write these specs in the first place? Do you need to then keep updating these to change the implementation?</p>
<p>Well as Hegel would have it, there is a possible synthesis of these positions. Use specs to design the internal interactions where it helps you but don’t feel obliged to keep these as soon as they becomes a hindrance to improving that implementation later. Keep those that specify the external behaviour but discard those that are no longer helpful. The test suite is a side effect, its not something to be precious about if it gets in the way of the primary use of BDD as a design technique. Don’t throw the baby out with the bathwater though - if that side effect gets in the way don’t avoid the original primary benefit.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Configuring different services for different environments]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In my <a href="https://richardmiller.co.uk/2014/03/17/avoiding-optional-dependencies/">previous post</a> I talked about avoiding optional dependencies. The example I used was of changing an optional dependency on a logger into a mandatory one. We injected a null logger implementation when we did not need logging. In this post I am going to look at this from</p>]]></description><link>https://richardmiller.co.uk/2014/03/28/symfony2-configuring-different-services-for-different-environments/</link><guid isPermaLink="false">5e3825edde21b10018bb8298</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Fri, 28 Mar 2014 12:27:41 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In my <a href="https://richardmiller.co.uk/2014/03/17/avoiding-optional-dependencies/">previous post</a> I talked about avoiding optional dependencies. The example I used was of changing an optional dependency on a logger into a mandatory one. We injected a null logger implementation when we did not need logging. In this post I am going to look at this from the configuration point of view. In particular, how we could switch between which implementation gets injected for different environments.</p>
<p>We would not want to turn logging off for production but we may want to for an environment used for automated tests.</p>
<p>So we have the following services file:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml --&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;

    &lt;services&gt;
        &lt;!-- More services --&gt;

        &lt;service id=&quot;acme.demo.listener&quot; class=&quot;Acme\DemoBundle\EventListener\ControllerListener&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;twig.extension.acme.demo&quot; /&gt;
            &lt;argument type=&quot;service&quot; id=&quot;logger&quot; /&gt;
        &lt;/service&gt;

        &lt;service id=&quot;acme.demo.mailer&quot; class=&quot;Acme\DemoBundle\Mailer&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;logger&quot; /&gt;
        &lt;/service&gt;

    &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>For our test environment we want to use the null logger implementation from PSR instead. So we need to inject a different logger service into all the services that use it. So what can we do? We could load a different xml file for the test environment by changing the extension class.</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator;

class AcmeDemoExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader-&gt;load('services.xml');

        if ($this-&gt;container-&gt;getParameter('kernel.environment') == 'test') {
            $loader-&gt;load('services_test.xml');
        }
    }

    public function getAlias()
    {
        return 'acme_demo';
    }
}
</code></pre>
<p>If we load a different one instead then we will have a lot of repetition. We would be better off loading an extra one and overriding services as necessary. We could define a new logger service and redefine all the services that use it:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services_test.xml --&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;

    &lt;services&gt;
        &lt;!-- More services --&gt;

        &lt;service id=&quot;acme.demo.null_logger&quot; class=&quot;Psr\Log\NullLogger&quot; /&gt;

        &lt;service id=&quot;acme.demo.listener&quot; class=&quot;Acme\DemoBundle\EventListener\ControllerListener&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;twig.extension.acme.demo&quot; /&gt;
            &lt;argument type=&quot;service&quot; id=&quot;acme.demo.null_logger&quot; /&gt;
        &lt;/service&gt;

        &lt;service id=&quot;acme.demo.mailer&quot; class=&quot;Acme\DemoBundle\Mailer&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;acme.demo.null_logger&quot; /&gt;
        &lt;/service&gt;

    &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>This is still a lot of repeated configuration. We could redefine the logger service instead so that this is then used throughout.</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services_test.xml --&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;

    &lt;services&gt;
        
        &lt;service id=&quot;logger&quot; class=&quot;Psr\Log\NullLogger&quot; /&gt;

    &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>This is an improvement as we now just have one different service in our extra service file. It would be good to reduce the changes further still. We can do this using a service alias. Then we can just change what the alias looks like. We can create an alias that points at the normal logger service. Then we can use this in our other services:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml --&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;

    &lt;services&gt;
        &lt;!-- More services --&gt;

        &lt;service id=&quot;acme.logger&quot; alias=&quot;logger&quot;/&gt;

        &lt;service id=&quot;acme.demo.null_logger&quot; class=&quot;Psr\Log\NullLogger&quot; /&gt;

        &lt;service id=&quot;acme.demo.listener&quot; class=&quot;Acme\DemoBundle\EventListener\ControllerListener&quot;&gt;
           &lt;argument type=&quot;service&quot; id=&quot;twig.extension.acme.demo&quot; /&gt;
            &lt;argument type=&quot;service&quot; id=&quot;acme.logger&quot; /&gt;
        &lt;/service&gt;

        &lt;service id=&quot;acme.demo.mailer&quot; class=&quot;Acme\DemoBundle\Mailer&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;acme.logger&quot; /&gt;
        &lt;/service&gt;

    &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>We can now set the alias to point at the normal logger service in our main service file. We can rename the null logger service id. Now that it does not clash with the main logger service we can move it to the main services xml file. In the extra services file we now just need to point the alias at the null service.</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services_test.xml --&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;

    &lt;services&gt;
        
        &lt;service id=&quot;acme.logger&quot; alias=&quot;acme.demo.null_logger&quot; /&gt;

    &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>This does not make much difference as the null logger has no arguments. We could get rid of it altogether though. We can make the choice of service to alias to a parameter:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml --&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;

    &lt;services&gt;
        &lt;!-- More services --&gt;

        &lt;service id=&quot;acme.logger&quot; alias=&quot;%acme.logger.id%&quot;/&gt;

        &lt;service id=&quot;acme.demo.null_logger&quot; class=&quot;Psr\Log\NullLogger&quot; /&gt;

        &lt;service id=&quot;acme.demo.listener&quot; class=&quot;Acme\DemoBundle\EventListener\ControllerListener&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;twig.extension.acme.demo&quot; /&gt;
            &lt;argument type=&quot;service&quot; id=&quot;acme.logger&quot; /&gt;
        &lt;/service&gt;

        &lt;service id=&quot;acme.demo.mailer&quot; class=&quot;Acme\DemoBundle\Mailer&quot;&gt;
            &lt;argument type=&quot;service&quot; id=&quot;acme.logger&quot; /&gt;
        &lt;/service&gt;

    &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>It can now be set in the application config and the extra services file removed altogether!</p>
<pre><code class="language-language-markup">#app/config/parameters.yml in local dev installation
parameters:
    #...
    acme.logger.id: logger
</code></pre>
<p>and</p>
<pre><code class="language-language-markup">#app/config/parameters.yml on test server
parameters:
    #...
    acme.logger.id: acme.demo.null_logger
</code></pre>
<p>As well as making the reconfiguration simpler we have decoupled the choice from the environment. I have <a href="https://richardmiller.co.uk/2013/05/28/symfony2-avoiding-coupling-applications-to-the-environment/">previously written about this</a> as a more general idea. We can now change the parameter on its own. This may not be that important for our logger but allows us to switch which services we use with ease.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Avoiding Optional Dependencies]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In <a href="https://richardmiller.co.uk/2014/03/12/avoiding-setter-injection/">my previous post</a> I argued against setter injection. Optional dependencies are one of the main objections raised in the comments and elsewhere. I did mention these with a suggestion of just making them optional constructor arguments. I also mentioned that refactoring to stop it being optional was a solution.</p>]]></description><link>https://richardmiller.co.uk/2014/03/17/avoiding-optional-dependencies/</link><guid isPermaLink="false">5e3825edde21b10018bb8295</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Mon, 17 Mar 2014 12:57:06 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In <a href="https://richardmiller.co.uk/2014/03/12/avoiding-setter-injection/">my previous post</a> I argued against setter injection. Optional dependencies are one of the main objections raised in the comments and elsewhere. I did mention these with a suggestion of just making them optional constructor arguments. I also mentioned that refactoring to stop it being optional was a solution.</p>
<p>I think that this is worth exploring further. I think that the disadvantages of setter injection means it should be avoided. I do not think any advantages for dealing with optional dependencies outweigh the disadvantages. This is not an opinion shared by all though.</p>
<p>Looking at how I deal with optional dependencies made me realise that I do not just avoid setter injection. I also usually avoid having optional dependencies. Having thought this through more will now avoid using them at all.</p>
<p>So why are optional dependencies a problem? Often an optional dependency is a sign that the class has several behaviours. So it has several responsibilities and is not adhering to the Single Responsibility Principle. A class with an optional dependency does one thing always. It does another thing sometimes if the optional dependency is present.</p>
<p>We would be better extracting the optional behaviour into another class. This new class could then have a single responsibility for that behaviour. In the new class this would not be optional and we can now choose which version. We are now deciding if we want the optional behaviour only in the config not in the config and in the object.</p>
<p>Even if this is not possible then we would still do well to avoid the optional dependency. Consider logging as the optional behaviour, which was a common counterexample. So a class with optional logging may look like this:</p>
<pre><code class="language-language-php">
private $otherDependency;
private $logger;

public function __construct(OtherDependency $otherDependency, LoggerInterface $logger = null)
{
    $this-&gt;otherDependency = $otherDependency;
    $this-&gt;logger = $logger;
}

public function doSomething()
{
    //do something
    if ($this-&gt;logger) {
        $this-&gt;logger-&gt;info('something to log');
    }
}
</code></pre>
<p>There is another issue here which is that we have to wrap any use of the logger is a conditional. If we do not then we would get a fatal error when calling the non-existent logger's method. This adds complexity to the class and raises the risk of bugs. It is easy to avoid this bug with a spec or unit test. We could avoid even having to go to that effort though. Our class would be simpler if it looked like this:</p>
<pre><code class="language-language-php">
private $otherDependency;
private $logger;

public function __construct(OtherDependency $otherDependency, LoggerInterface $logger)
{
    $this-&gt;otherDependency = $otherDependency;
    $this-&gt;logger = $logger;
}

public function doSomething()
{
    //do something
    $this-&gt;logger-&gt;info('something to log');
}
</code></pre>
<p>We can have this and still achieve the desired behaviour of optional logging by using a Null object. We can pass in a null logger that implements the logger interface but which does nothing when we do not want logging. Our class does not need to be aware that this is the case, it will use anything that has the interface. In fact if you are using a PSR3 logger then there is null logger implementation in the <a href="https://packagist.org/packages/psr/log">psr/log package</a>.</p>
<p>Yes, we need an extra class but optional logging is something we will find in many classes. For the sake of a single extra class we can remove conditionals from a lot of places in our code. This reduces the number of potential bugs and makes the code more readable. Removing a lot of conditionals in exchange for creating a single class is a good refactoring of code.</p>
<p>It is no more complicated to turn logging on and off in configuration. When we do not need logging the logger service can just be the null logger. We will have turned off logging without making any other changes.</p>
<p>We now have simpler code. We can remove all the conditionals. We avoid setter injection. All without adding anything more complex to our code than a simple null implementation of the logger.</p>
<p>My thought is that optional dependencies are themselves a code smell. Setter injection is not a solution to this smell. Stopping the dependency being optional is more important than how we inject it.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Avoiding Setter Injection]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A while ago I had a twitter discussion with <a href="https://twitter.com/igorwhiletrue">Igor Wiedler</a> and <a href="https://twitter.com/matthiasnoback">Matthias Noback</a> about setter injected dependencies being mutable.</p>
<p>When using objects as services in an application then we do not want them to have state. This is because we can them call them many times without the outcome</p>]]></description><link>https://richardmiller.co.uk/2014/03/12/avoiding-setter-injection/</link><guid isPermaLink="false">5e3825edde21b10018bb8293</guid><category><![CDATA[dependency injection]]></category><category><![CDATA[php]]></category><category><![CDATA[symfony2]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Wed, 12 Mar 2014 15:03:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A while ago I had a twitter discussion with <a href="https://twitter.com/igorwhiletrue">Igor Wiedler</a> and <a href="https://twitter.com/matthiasnoback">Matthias Noback</a> about setter injected dependencies being mutable.</p>
<p>When using objects as services in an application then we do not want them to have state. This is because we can them call them many times without the outcome changing. For example, if we have a mailer service that sends emails for us we would expect it to behave the same way whenever we call it in an application. We would not want the service's behaviour to be different because we had already called it somewhere else in the request. We can make sure that we write the internals of services to not change their state in this way. Yet when we use setter injection we take control over this from the service and leave it in the hands of the code consuming the service.</p>
<p>The two main ways of injecting dependencies are constructor and setter injection. A main advantage of constructor injection is that ensures that we inject the dependency. This means that there are no surprises later if it has not been. Another advantage is that the choice of dependency is immutable. Constructing the service fixes it to that dependency (assuming we provide no other means of changing it).</p>
<p>With setter injection, we can call the setter method many times. So the choice of dependency is not immutable with setter injection. We cannot use the service knowing we will get the same results with the same arguments. Other code using the service could have changed the dependency between calls. Anywhere that uses the service can now set a different dependency which will change its behaviour.</p>
<p>For example, let's say we can set a filter on our mailer service. Since this is optional we choose to inject it with a setter method. If we do not want a filter then we do not call the method. We could not expect consistent results if other code as other could change the filter dependency.</p>
<p>We could change the setter to only allow the dependency to be set once. We will need to write extra code needed for this. The main issue it will fall down because the of the optional nature of dependencies provided by setter injection. The behaviour remaining the same throughout the service's lifetime is still not guaranteed. We could use the service before the dependency has been set and again after it has been set with different results.</p>
<p>We can avoid this by injecting the dependency through the constructor and making it an optional argument. Now the dependency is still optional but we are fixing whether it is set at the time of construction.</p>
<p>As an aside, it would be better to refactor away from having optional dependencies. Instead we could move to different classes implementing the service's interface. One without the dependency and one where it is mandatory.</p>
<p>So is there a case for using setter injection at all? One other use is as an &quot;adder&quot; method which adds dependencies to a collection. Here calling it again does not replace the dependency but adds it to the collection. We still have the potential for changing behaviour here by adding additionally dependencies later.</p>
<p>If we want to fix the collection of dependencies what can we do? Well we can fix them at construction time by passing the full collection in as a constructor argument. So, is this always possible? Symfony2 uses adder methods to add dependencies outside of the original service definition. These dependencies are usually added in a compiler pass. The compiler pass finds tagged services and adds them as dependencies to another service. It does this by adding a call to the service's adder method for each dependency in the service's definition. Here is <a href="http://symfony.com/doc/current/components/dependency_injection/tags.html">an example from the Symfony documentation</a>:</p>
<pre><code class="language-language-php">use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

class TransportCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container-&gt;hasDefinition('acme_mailer.transport_chain')) {
            return;
        }

        $definition = $container-&gt;getDefinition(
            'acme_mailer.transport_chain'
        );

        $taggedServices = $container-&gt;findTaggedServiceIds(
            'acme_mailer.transport'
        );
        foreach ($taggedServices as $id =&gt; $attributes) {
            $definition-&gt;addMethodCall(
                'addTransport',
                array(new Reference($id))
            );
        }
    }
}
</code></pre>
<p>The problem here is that it is still possible for code using the service to add more dependencies later. So can we prevent this? In the twitter conversation We discussed several options. One was to have a way of flagging that we have finished adding dependencies. The method could then throw an exception if called after the flag is set. We could do this by adding a method that sets the flag, calling it last in the service definition. Unfortunately, this feels like quite an awkward solution and relies on making sure that you add the call to the locking method.</p>
<p>Another would be to have a builder object that collects the dependencies and then set the service up with them. This requires adding an extra layer of complexity, which is not appealing. In fact, we realised that the service container already is doing this job. Just changing the way the compiler pass works would be enough. The TransportChain class's first constructor argument is now a collection of transports.  The compiler pass could now be as follows:</p>
<pre><code class="language-language-php">use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

class TransportCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container-&gt;hasDefinition('acme_mailer.transport_chain')) {
            return;
        }

        $definition = $container-&gt;getDefinition(
            'acme_mailer.transport_chain'
        );

        $transports = $definition-&gt;getArgument(0);

        $taggedServices = $container-&gt;findTaggedServiceIds(
            'acme_mailer.transport'
        );
        foreach ($taggedServices as $id =&gt; $attributes) {
            $transports[] = new Reference($id);
        }

        $definition-&gt;replaceArgument(0, $transports);
    }
}
</code></pre>
<p>Here we are getting the first argument in the service definition for the transport chain. In this case we are assuming that it is already defined as a collection. We then append the references to the tagged services to the collection keeping  any existing services. The argument in the definition is then replaced with the populated collection. We can now remove the addTransport method from the class. This prevents code using the transport chain from making further changes.</p>
<p>So it looks as though we can avoid most instances of setter injection with little difficulty. We then give ourselves the greater safety of constructor injection.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Some links]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In my <a href="https://richardmiller.co.uk/2013/06/18/symfony2-bundle-structure-bundles-as-integration-layers-for-libraries/">previous post on separating bundles from libraries</a> in <a href="http://symfony.com">Symfony2</a> applications I said I would follow this up with more details.</p>
<p>I have yet to write that post, in the meantime some links to useful information along these lines:</p>
<ul>
	<li>This is the <a href="http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/">first of a series on DDD with</a></li></ul>]]></description><link>https://richardmiller.co.uk/2013/10/08/symfony2-some-links/</link><guid isPermaLink="false">5e3825edde21b10018bb828d</guid><category><![CDATA[ddd]]></category><category><![CDATA[php]]></category><category><![CDATA[symfony2]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Tue, 08 Oct 2013 18:18:37 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In my <a href="https://richardmiller.co.uk/2013/06/18/symfony2-bundle-structure-bundles-as-integration-layers-for-libraries/">previous post on separating bundles from libraries</a> in <a href="http://symfony.com">Symfony2</a> applications I said I would follow this up with more details.</p>
<p>I have yet to write that post, in the meantime some links to useful information along these lines:</p>
<ul>
	<li>This is the <a href="http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/">first of a series on DDD with Symfony2</a> by William Durand.</li>
<pre><code>&lt;li&gt;This &lt;a href=&quot;http://www.whitewashing.de/2012/08/11/oop_business_applications__trying_to_escape_the_mess.html&quot;&gt;series of posts&lt;/a&gt; by Benjamin Eberlei as well as many other great articles on that blog.&lt;/li&gt;


&lt;li&gt;&lt;a href=&quot;http://verraes.net/#blog&quot;&gt;Mathias Verraes has a blog&lt;/a&gt; with lots of interesting posts relating to DDD in PHP.&lt;/li&gt;
</code></pre>
</ul>
<p>I spoke about this subject at SymfonyLive in London, you can <a href="https://speakerdeck.com/richardmiller/atm">find the slides here</a>.</p>
<p>A lot of the above related to using the ideas of Domain Driven Design in Symfony2. Eric Evan's original <a href="http://dddcommunity.org/book/evans_2003/">Blue Book DDD book</a> and Vaughn Vernon's <a href="http://dddcommunity.org/book/implementing-domain-driven-design-by-vaughn-vernon/">Implementing DDD book</a> are both excellent if not easy reads as they are both long with a lot of information packed in.</p>
<p>Some slide from recent conference talks: Marcello Duarte and Konstantin Kudryashov spoke about the <a href="http://www.slideshare.net/marcello.duarte/the-framework-as-an-implementation-detail">framework as an implementation detail</a> at Symfony Live in London. At the PHPNW conference this weekend Ross Tuck gave an excellent talk on a similar topic as well, <a href="http://www.slideshare.net/rosstuck/models-and-service-layers-hemoglobin-and-hobgoblins">Models and Service Layers; Hemoglobin and Hobgoblins</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Bundle structure – bundles as integration layers for libraries]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Many of the bundles that are part of the <a href="http://symfony.com">Symfony2</a> framework and the available third party bundles are effectively integration layers between a library and the framework. For example:</p>
<ul>
	<li>The <a href="https://github.com/videlalvaro/rabbitmqbundle">OldSoundRabbitMqBundle</a> integrates the <a href="https://github.com/videlalvaro/php-amqplib">php-amqplib</a> library</li>
<li>The <a href="https://github.com/FriendsOfSymfony/FOSElasticaBundle">FOSElasticaBundle</a> integrates <a href="https://github.com/ruflin/Elastica">Elastica</a> </li>
<li>The <a href="https://github.com/liip/LiipImagineBundle">LiipImagineBundle</a> integrates <a href="https://github.com/avalanche123/Imagine">Imagine</a></li>
</ul>
<p>What is in the bundle then? One</p>]]></description><link>https://richardmiller.co.uk/2013/06/18/symfony2-bundle-structure-bundles-as-integration-layers-for-libraries/</link><guid isPermaLink="false">5e3825edde21b10018bb828c</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Tue, 18 Jun 2013 05:56:28 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Many of the bundles that are part of the <a href="http://symfony.com">Symfony2</a> framework and the available third party bundles are effectively integration layers between a library and the framework. For example:</p>
<ul>
	<li>The <a href="https://github.com/videlalvaro/rabbitmqbundle">OldSoundRabbitMqBundle</a> integrates the <a href="https://github.com/videlalvaro/php-amqplib">php-amqplib</a> library</li>
<li>The <a href="https://github.com/FriendsOfSymfony/FOSElasticaBundle">FOSElasticaBundle</a> integrates <a href="https://github.com/ruflin/Elastica">Elastica</a> </li>
<li>The <a href="https://github.com/liip/LiipImagineBundle">LiipImagineBundle</a> integrates <a href="https://github.com/avalanche123/Imagine">Imagine</a></li>
</ul>
<p>What is in the bundle then? One common thing are service definitions to integrate them into a Symfony2 app instead of manually creating objects. Alongside this is exposing the configuration of these objects via the Dependency Injection Extension to allow configuration from the application's overall config files.</p>
<p>The libraries in many cases have been written using dependency injection but the definitions that wire them together are part of the bundle. In some cases the libraries are not written using dependency injection but the bundle can still contain the service definitions to integrate them into a Symfony application.</p>
<p>Service definitions are not the only thing that bundles do to integrate libraries there is also twig extensions, twig templates, some have controllers, listeners for events etc.</p>
<p>In some cases these could be further separated into a bridge and a bundle as with the framework itself.  For example, twig extensions and doctrine listeners are not Symfony2 specific and could live in a bridge with the bundle handling service definitions with tags to automatically register them in the application. This would allow other non-Symfony2 applications but which used Doctrine or Twig to make use of the templates and listeners.</p>
<p>This technique also suits code within an application, rather than having everything in a bundle it make sense to split out non-framework specific code into a library and have an associated bundle to integrate this back in. By avoiding having framework specific code you open up the possibility of reusing this library in other applications with no or another framework. Even where it is not useful in another application it will aid any future migrations of the app. This way the bundle is dependant on the app but not vice versa making it much easier to move.</p>
<p>This is not to say that no Symfony code should be used in the library, it makes sense to still use the components but avoiding code from the bundles and bridges makes sense as you are then introducing dependencies only on the components used and not on the whole framework. These can of course be specified in the bundle’s composer.json file so that it can be easily installed standalone elsewhere.</p>
<p>The obvious cases for this are where the code being extracted from the bundle into a library is infrastructure code as it is with most third party bundle/library combinations. For example, if there are particular logging requirements for the application not met by existing solutions, such as having to interact with an in-house log aggregation server. By keeping everything related to this in a separate library and bundle it is then available for use in other applications as well as making any future migrations simpler. It also makes it easier to avoid this code becoming dependant on the needs or worse the business logic of the particular application, which should not be the case for this sort of infrastructure code.</p>
<p>What about the business logic that is specific to the application though? Is there any benefit to doing the same with this? It may seem like it will not be any use outside of this application but if it is part of the business then it may well be useful in other applications even is this is not immediately apparent. Even if it is not used in a different application then any future migrations, even if just to a new major version of Symfony rather than a different framework, will be considerably easier if the business logic has no framework dependencies.</p>
<p>Another benefit is the enforced separation this gets us between the application specific logic and the business logic. Even if we never intend to and don't use the business logic outside of this application then making it work outside of the application will help us to create business logic that is decoupled from the application and easier to maintain and extend for it. We will no longer end to making decisions about business logic based on the needs of the framework.</p>
<p>Unlike the infrastructure code where it relatively easier to separate out what is not framework specific it becomes harder in the case of business logic, if we move our entities, repositories etc. out of the bundle how do we work with forms and validation etc.? This is something I will look at over my next few posts.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Avoiding coupling applications to the environment]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A quick post looking avoiding tying a <a href="http://symfony.com">Symfony2</a> application to the environment and instead varying config per environment.</p>
<p>It's tempting to access the env parameter from within an application in order to make decisions. A very crude example designed to make what is happening clear, is getting the environment within</p>]]></description><link>https://richardmiller.co.uk/2013/05/28/symfony2-avoiding-coupling-applications-to-the-environment/</link><guid isPermaLink="false">5e3825edde21b10018bb828b</guid><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Tue, 28 May 2013 07:35:37 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A quick post looking avoiding tying a <a href="http://symfony.com">Symfony2</a> application to the environment and instead varying config per environment.</p>
<p>It's tempting to access the env parameter from within an application in order to make decisions. A very crude example designed to make what is happening clear, is getting the environment within from the container in a controller and using that to decide whether to actually send an SMS alert:</p>
<pre><code class="language-language-php">if ($this-&gt;container-&gt;getParameter('kernel.environment') == 'prod') {
    $this-&gt;sendSms();
}
</code></pre>
<p>We could clean this up by moving the sending of the SMS into a service and injecting the value of the parameter into it:</p>
<pre><code class="language-language-php">namespace Acme\DemoBundle\Sms\Sender;

class Sender
{
    private $env

    public function __construct($env)
    {
        $this-&gt;env = $env;
    }
    
    public function send($number, $message)
    {
        if($this-&gt;env != 'prod') {
            return;
        }
        // ...
    }
}
</code></pre>
<p>with this service definition:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml--&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;
    &lt;services&gt;
         &lt;service id=&quot;acme.sms_sender&quot; 
                  class=&quot;Acme\DemoBundle\Sms\Sender&quot;&gt;
             &lt;argument&gt;%kernel.environment%&lt;/argument&gt;
         &lt;/service&gt;
     &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>However whilst moving the sending of the SMS out of the controller is a good idea we are still coupling the service to the environment.</p>
<h2>Why this is bad in theory</h2>
<p>The application should not be aware of what environment it is running under, it should just be configured a particular way based on its configuration files. Since we want to vary configuration between different environments there are typically different configuration for each of these environments. We choose which of these sets of configuration to load rather than telling the application which environment it is in.</p>
<h2>Why this is bad in practice</h2>
<p>This is all very well in theory but what problem's can it cause us to make the application aware of what environment it is in in practice? The first is that we can only change the configuration now in the code if we change our mind about the setting. The second is that we can no longer test the setting by changing config, we need to change the environment the application is running in altogether to see the effect, if we used a configuration value instead we could just change that for the current environment.</p>
<p>If you later need to add further environments which need the same change then you will need to add to the if statements in the code to do this. With a configuration value you can just set it for that environment if it needs a value different to the default configuration.</p>
<p>With a good parameter name it is then clear as to its purpose as well, so reconfiguring the application is straightforward without having to dig into the application code to see what the parameter is used for.</p>
<pre><code class="language-language-php">namespace Acme\DemoBundle\Sms\Sender;

class SmsSender
{
    private $sendingDisabled

    public function __construct($sendingDisabled)
    {
        $this-&gt;sendingDisabled = $sendingDisabled;
    }
    
    public function send($number, $message)
    {
        if($this-&gt;sendingDisabled) {
            return;
        }
        // ...
    }
}
</code></pre>
<p>with this service definition:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml--&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;
    &lt;services&gt;
         &lt;service id=&quot;acme.sms_sender&quot; 
                  class=&quot;Acme\DemoBundle\Sms\Sender&quot;&gt;
             &lt;argument&gt;%acme.sms.disabled%&lt;/argument&gt;
         &lt;/service&gt;
     &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>and in the config_dev.yml file:</p>
<pre><code class="language-language-markup">parameters:
    acme.sms.disabled: true
</code></pre>
<p>Rather than simply setting this as a parameter you could expose it as bundle configuration as I looked at <a href="https://richardmiller.co.uk/2013/05/22/symfony2-yet-more-on-that-twig-extension/">in my previous post</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Yet more on that Twig Extension]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://richardmiller.co.uk/2013/02/27/symfony2-more-twig-ajax-templates/">In my last post</a> I looked at the end at creating a Twig extension that would return the template to extend in order to pull the logic for the decision out of the template. The template names were just stored in class constants to keep the example simple; I mentioned</p>]]></description><link>https://richardmiller.co.uk/2013/05/22/symfony2-yet-more-on-that-twig-extension/</link><guid isPermaLink="false">5e3825edde21b10018bb8289</guid><category><![CDATA[config]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[php]]></category><category><![CDATA[symfony2]]></category><category><![CDATA[Twig]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Wed, 22 May 2013 06:30:17 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://richardmiller.co.uk/2013/02/27/symfony2-more-twig-ajax-templates/">In my last post</a> I looked at the end at creating a Twig extension that would return the template to extend in order to pull the logic for the decision out of the template. The template names were just stored in class constants to keep the example simple; I mentioned that these could be moved out into configuration. A few people asked for more details on how that would be done so here it is. This is not specific to Twig extension but it does provide us with an example to look at exposing bundle configuration.</p>
<p>So to start with the extension class looks like this:</p>
<pre><code class="language-language-php">namespace Acme\DemoBundle\Twig;

class DemoExtension extends \Twig_Extension
{
    const FULL_TEMPLATE = '::full-layout.html.twig';
    const PARTIAL_TEMPLATE = '::partial-layout.html.twig';

    public function getFunctions()
    {
        return array(
            'parent_template' =&gt; new \Twig_Function_Method($this, 'getParentTemplate'),
        );
    }

    public function getParentTemplate()
    {
        if ($this-&gt;useFullTemplate()) {
            return self::FULL_TEMPLATE;
        }
        return self::PARTIAL_TEMPLATE; 
    }

    public function useFullTemplate()
    {
         //...
    }
}
</code></pre>
<p>with this service definition:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml--&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;
    &lt;services&gt;
         &lt;service id=&quot;acme.twig.demo_extension&quot; 
                  class=&quot;Acme\DemoBundle\Twig\DemoExtension&quot;&gt;
             &lt;tag name=&quot;twig.extension&quot; /&gt;
         &lt;/service&gt;
     &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>As we only have a couple of template names we could inject them individually to the constructor:</p>
<pre><code class="language-language-php">namespace Acme\DemoBundle\Twig;

class DemoExtension extends \Twig_Extension
{
    private $fullTemplate;
    private $partialTemplate;

    public function __construct($fullTemplate, $partialTemplate)
    {
        $this-&gt;fullTemplate = $fullTemplate;
        $this-&gt;partialTemplate = $partialTemplate;
    }

    public function getFunctions()
    {
        return array(
            'parent_template' =&gt; new \Twig_Function_Method($this, 'getParentTemplate'),
        );
    }

    public function getParentTemplate()
    {
        if ($this-&gt;useFullTemplate()) {
            return $this-&gt;fullTemplate;
        }
        return $this-&gt;partialTemplate; 
    }

    public function useFullTemplate()
    {
         //...
    }
}
</code></pre>
<p>and set them as parameters in our services file:</p>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml--&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;
    &lt;parameters&gt;
        &lt;parameter key=&quot;acme.templates.full&quot;&gt;::full-layout.html.twig&lt;/parameter&gt;
        &lt;parameter key=&quot;acme.templates.partial&quot;&gt;::partial-layout.html.twig&lt;/parameter&gt;
    &lt;/parameters&gt;
    &lt;services&gt;
         &lt;service id=&quot;acme.twig.demo_extension&quot; 
                  class=&quot;Acme\DemoBundle\Twig\DemoExtension&quot;&gt;
             &lt;argument&gt;%acme.templates.full%&lt;/argument&gt;
             &lt;argument&gt;%acme.templates.partial%&lt;/argument&gt;
             &lt;tag name=&quot;twig.extension&quot; /&gt;
         &lt;/service&gt;
     &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>It may be better though to just accept an associative array of template names so that we can increase the number later without increasing the number of constructor arguments:</p>
<pre><code class="language-language-php">namespace Acme\DemoBundle\Twig;

class DemoExtension extends \Twig_Extension
{
    private $templates;

    public function __construct($templates)
    {
        $this-&gt;templates = $templates;
    }

    public function getFunctions()
    {
        return array(
            'parent_template' =&gt; new \Twig_Function_Method($this, 'getParentTemplate'),
        );
    }

    public function getParentTemplate()
    {
        if ($this-&gt;useFullTemplate()) {
            return $this-&gt;templates['full'];
        }
        return $this-&gt;templates['partial']; 
    }

    public function useFullTemplate()
    {
         //...
    }
}
</code></pre>
<pre><code class="language-language-markup">&lt;!-- src/Acme/DemoBundle/Resources/config/services.xml--&gt;
&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;
    &lt;parameters&gt;
        &lt;parameter key=&quot;acme.templates&quot; type=&quot;collection&quot;&gt;
             &lt;parameter key=&quot;full&quot;&gt;::full-layout.html.twig&lt;/parameter&gt;
             &lt;parameter key=&quot;partial&quot;&gt;::partial-layout.html.twig&lt;/parameter&gt;
        &lt;/parameter&gt;
    &lt;/parameters&gt;
    &lt;services&gt;
         &lt;service id=&quot;acme.twig.demo_extension&quot; 
                  class=&quot;Acme\DemoBundle\Twig\DemoExtension&quot;&gt;
             &lt;argument&gt;%acme.templates.full%&lt;/argument&gt;
             &lt;argument&gt;%acme.templates.partial%&lt;/argument&gt;
             &lt;tag name=&quot;twig.extension&quot; /&gt;
         &lt;/service&gt;
     &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>So far this has just used setting parameters directly, however this does not give us much opportunity to validate the configuration. Currently the parameters are set in our bundle as well. If we decide that this bundle is worth sharing between applications then we would want to be able to set the parameters outside of the bundle in the app level config. We could just leave setting these parameters directly and move to doing that in the app parameters file:</p>
<pre><code class="language-language-markup"># app/config/config.yml
parameters:
    acme.templates:
        full: &quot;::full-layout.html.twig&quot;
        partial: &quot;::partial-layout.html.twig&quot;
</code></pre>
<p>This still does not give us much control over what values get set. If we move to making them part of the config that the bundle exposes to the app level config then we can validate the values. It also makes it easier for someone else or ourselves in the future to see how to configure the bundle by looking at the allowed config.</p>
<p>We can instead make setting the template part of the bundle configuration instead of setting the parameters directly. This is the way the bundles that are part of the framework handle their configuration. The first step is to tell the bundle to expect configuration relating to the templates in the Configuration class that is in the DependencyInjection directory. This is autogenerated if you create your bundles with the generate:bundle console command:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder-&gt;root('acme');

        $rootNode
            -&gt;children()
                -&gt;arrayNode('templates')
                -&gt;useAttributeAsKey('name')
                -&gt;isRequired()
                    -&gt;requiresAtleastOneElement()
                    -&gt;prototype('scalar')-&gt;end()
                -&gt;end()
            -&gt;end()
        ;

        return $treeBuilder;
    }
}
</code></pre>
<p>Here we are saying that we want an array of templates, at the moment all we have said is that it must exist and that it must have at least one element. We will now not be able to run the application as we get an exception due to not having met these requirements.</p>
<p>We can now add them to the <code>config.yml</code> file, instead of the parameters section we add them to a section with the top level key which matches out bundle’s name which was set as the root node name in the configuration class above. For the examples this is &quot;acme&quot;:</p>
<pre><code class="language-language-markup"># app/config/config.yml
acme:
    templates:
        full: &quot;::full-layout.html.twig&quot;
        partial: &quot;::partial-layout.html.twig&quot;

</code></pre>
<p>At this point we can remove the previous setting on these values in the parameters section of the config.</p>
<p>We should now be able to load the application without an exception about the config, however the template values are not yet being set as parameters. For that we also need to take the validated config and directly set the parameters. This is done in the Extension class in the DependencyInjection folder which is again generated automatically. In that we can see the configuration being processed in the first two lines of the load method. This is where the config files such as <code>config.yml</code> and <code>config_dev.yml</code> are merged and validated against the tree in the Configuration class.</p>
<p>We can use the processed configuration array to access the values and set them as parameters:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

class WHOTranslationExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this-&gt;processConfiguration($configuration, $configs);

        $container-&gt;setParameter('acme.templates', $config['templates']);

        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader-&gt;load('services.xml');
    }
}

</code></pre>
<p>We are now back where we started and had to make a few changes to get there, so what have we actually gained? Not much so far and our Twig extension is still expecting particular keys to be set in that array, which is going to cause issues if they are missing. We can start to get the benefits of the changes by tightening up the validation settings in Configuration class.</p>
<p>We do not just want an array with some values in this case we want specific keys to be set. So to ensure that the &quot;full&quot; and &quot;partial&quot; keys have values we can change the configuration to:</p>
<pre><code class="language-language-php">//...
$rootNode
    -&gt;children()
        -&gt;arrayNode('templates')
            -&gt;isRequired()
            -&gt;children()
                -&gt;scalarNode('main')-&gt;isRequired()-&gt;end()
                -&gt;scalarNode('partial')-&gt;isRequired()-&gt;end()
            -&gt;end()
        -&gt;end()
    -&gt;end()
;
//...
</code></pre>
<p>If we usual use the same name for these templates then we could set default values and use convention to avoid the explicit configuration but still leave open the possibility of overriding these values if we need to:</p>
<pre><code class="language-language-php">//...
$rootNode
    -&gt;children()
        -&gt;arrayNode('templates')
            -&gt;addDefaultsIfNotSet()
            -&gt;children()
                -&gt;scalarNode('main')
                    -&gt;defaultValue('::full-layout.html.twig')
                -&gt;end()
                -&gt;scalarNode('partial')
                    -&gt;defaultValue('::partial-layout.html.twig')
                -&gt;end()
            -&gt;end()
        -&gt;end()
    -&gt;end()
;
//...
</code></pre>
<p>There is a console command to dump the config, showing the available key and any default values.  This is dumped as Yaml so you can copy it as a starting pint for configuring the bundle. You can run it for this demo bundle with <code>app/console config:dump-reference acme</code>.</p>
<p>We can add additional information to this from the configuration tree using the <code>info()</code> and <code>example()</code> methods. Info is printed above the key it is set for as a comment; examples are printed as an inline comment after the value. The example is less useful where we already have default values so let’s go back to version where we didn’t and enhance it with some additional information:</p>
<pre><code class="language-language-php">//...
$rootNode
    -&gt;children()
        -&gt;arrayNode('templates')-&gt;info('The names of the parent templates to use')
            -&gt;isRequired()
            -&gt;children()
                -&gt;scalarNode('main')
                    -&gt;isRequired()
                    -&gt;example('::full-layout.html.twig')
                -&gt;end()
                -&gt;scalarNode('partial')
                     -&gt;isRequired()
                     -&gt;example('::partial-layout.html.twig')
                -&gt;end()
            -&gt;end()
        -&gt;end()
    -&gt;end()
;
//...
</code></pre>
<p>Running the console command now gives us:</p>
<pre><code class="language-language-markup">Default configuration for extension with alias: &quot;acme&quot;
acme:

    # The parent templates to use
    templates:
        main:                 ~ # Required, Example: ::full-layout.html.twig
        partial:              ~ # Required, Example: ::partial-layout.html.twig
</code></pre>
<p>So we have made our bundle more robust by validating its configuration and made more information about this configuration available to future uses of it. There are a lot more options available when validating configuration as there are a lot more possible requirements around what config is needed. There is more information on the possibilities when defining configuration in the <a href="http://symfony.com/doc/current/components/config/definition.html">official documentation</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: More on Twig Ajax Templates]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This post is a few notes to follow up on some of the responses to <a href="http://richardmiller.co.uk/2013/02/18/symfony2-ajax-and-full-page-templates/">my previous post</a> on reusing inner <a href="https://richardmiller.co.uk/2013/02/27/symfony2-more-twig-ajax-templates/twig.sensiolabs.org">Twig</a> templates for full page responses and ajax responses.</p>
<p>One clarification to make, as I had not made it clear, is that is only relevant to the case where</p>]]></description><link>https://richardmiller.co.uk/2013/02/27/symfony2-more-twig-ajax-templates/</link><guid isPermaLink="false">5e3825edde21b10018bb8286</guid><category><![CDATA[php]]></category><category><![CDATA[symfony2]]></category><category><![CDATA[Twig]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Wed, 27 Feb 2013 08:33:19 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This post is a few notes to follow up on some of the responses to <a href="http://richardmiller.co.uk/2013/02/18/symfony2-ajax-and-full-page-templates/">my previous post</a> on reusing inner <a href="https://richardmiller.co.uk/2013/02/27/symfony2-more-twig-ajax-templates/twig.sensiolabs.org">Twig</a> templates for full page responses and ajax responses.</p>
<p>One clarification to make, as I had not made it clear, is that is only relevant to the case where you are sending back HTML fragments is response to Ajax requests (and where that fragment is the same as the full page response minus the common parts of the page). If your Ajax response is XML or JSON then this technique is irrelevant as you will already be using different templates. In that case you can switch template using the <a href="http://symfony.com/doc/2.0/book/routing.html#book-routing-format-param">_format route parameter</a> or you may want to look at using the <a href="https://github.com/FriendsOfSymfony/FOSRestBundle">FOSRestBundle</a>.</p>
<p><a href="https://twitter.com/th0masr">Thomas Rabaix</a> of the <a href="http://sonata-project.org/about">Sonata Project</a> pointed out that a further improvement can be made by separating out the names of the templates to be extended into configuration by using Twig globals. This means that the choice of template to extend is no longer hardcoded into the templates at all. In a <a href="http://symfony.com">Symfony2</a> app it is easy to register globals in config. Our simple intermediate template that decides whether to extend the full or ajax template would now look like this:</p>
<pre><code class="language-language-markup">{# app/Resources/views/layout.html.twig #}
{% extends app.request.xmlHttpRequest 
         ? acme.templates.full
         : acme.templates.partial %}

</code></pre>
<p>with the global parameters set in the app's main config file:</p>
<pre><code class="language-language-markup"># app/config/config.yml
twig:
    globals:
        acme:
            templates:
                full: &quot;::ajax-layout.html.twig&quot;
                partial: &quot;::full-layout.html.twig&quot;
</code></pre>
<p>I also mentioned moving any logic for deciding which template to use to a Twig extension, if it became more complex than our simple ternary operator, so that it could be tested outside of a template. This could return the template to use rather than just a boolean allowing more complex decisions to be made as well.</p>
<p>A simple version of the extension may look like this:</p>
<pre><code class="language-language-php">namespace Acme\DemoBundle\Twig;

class DemoExtension extends \Twig_Extension
{
    const FULL_TEMPLATE = '::full-layout.html.twig';
    const PARTIAL_TEMPLATE = '::partial-layout.html.twig';

    public function getFunctions()
    {
        return array(
            'parent_template' =&gt; new \Twig_Function_Method($this, 'getParentTemplate'),
        );
    }

    public function getParentTemplate()
    {
        if ($this-&gt;useFullTemplate()) {
            return self::FULL_TEMPLATE;
        }
        return self::PARTIAL_TEMPLATE; 
    }

    public function useFullTemplate()
    {
         //...
    }
}
</code></pre>
<pre><code class="language-language-markup">&lt;?xml version=&quot;1.0&quot; ?&gt;

&lt;container xmlns=&quot;http://symfony.com/schema/dic/services&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd&quot;&gt;
    &lt;services&gt;
         &lt;service id=&quot;acme.twig.demo_extension&quot; 
                  class=&quot;Acme\DemoBundle\Twig\DemoExtension&quot;&gt;
             &lt;tag name=&quot;twig.extension&quot; /&gt;
         &lt;/service&gt;
     &lt;/services&gt;
&lt;/container&gt;
</code></pre>
<p>We can now remove the intermediate template altogether and call our twig function from the inner template:</p>
<pre><code class="language-language-markup">{# src/Acme/DemoBundle/Resources/views/Product/new.html.twig #}
{% extends parent_template() %}

{% block title %}New product{% endblock %}

{% block body %}
&lt;form action=&quot;{{ path('product_new') }}&quot; method=&quot;post&quot; {{ form_enctype(form) }}&gt;
    {{ form_widget(form) }}

    &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;
{% endblock body %}

</code></pre>
<p>In this example the templates are hardcoded in as class constants to keep the example straightforward, this could be changed to have them injected in to the extension so that they can be kept in configuration instead.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Ajax and Full Page Templates]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A quick look at one way to use the same controller action and <a href="http://twig.sensiolabs.org/">Twig</a> template (or just template) for displaying a full page and also just the inner content for an Ajax request in a <a href="http://symfony.com">Symfony2</a> application. This is using the ability to set which template a twig template extends</p>]]></description><link>https://richardmiller.co.uk/2013/02/18/symfony2-ajax-and-full-page-templates/</link><guid isPermaLink="false">5e3825edde21b10018bb8281</guid><category><![CDATA[php]]></category><category><![CDATA[symfony2]]></category><category><![CDATA[Twig]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Mon, 18 Feb 2013 13:16:51 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A quick look at one way to use the same controller action and <a href="http://twig.sensiolabs.org/">Twig</a> template (or just template) for displaying a full page and also just the inner content for an Ajax request in a <a href="http://symfony.com">Symfony2</a> application. This is using the ability to set which template a twig template extends from dynamically (which is shown <a href="http://twig.sensiolabs.org/doc/recipes.html#making-a-layout-conditional">here in the Twig documentation</a>).</p>
<p>So assuming we have a current inner template that looks like this:</p>
<pre><code class="language-language-markup">{# src/Acme/DemoBundle/Resources/views/Product/new.html.twig #}
{% extends '::full-layout.html.twig' %}

{% block title %}New product{% endblock %}

{% block body %}
&lt;form action=&quot;{{ path('product_new') }}&quot; method=&quot;post&quot; {{ form_enctype(form) }}&gt;
    {{ form_widget(form) }}

    &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;
{% endblock body %}

</code></pre>
<p>This extends our main layout template that adds the rest of the page, the header, footer etc. Whenever we render it we will get the full page with all the content from the outer template as well. For an Ajax request we only want the content of the body block to be displayed, we do not want any of the outer content that is provided by the the main template and we are not interested in the title block either. We can do this by creating an alternative Ajax outer template to render just the body block that is as simple as:</p>
<pre><code class="language-language-markup">{# app/Resources/views/ajax-layout.html.twig #}
{% block body %}{% endblock body %}
</code></pre>
<p>Then in our inner template we can use the app global to find out if it is an Ajax request:</p>
<pre><code class="language-language-markup">{# src/Acme/DemoBundle/Resources/views/Product/new.html.twig #}
{% extends app.request.xmlHttpRequest 
         ? '::ajax-layout.html.twig'
         : '::full-layout.html.twig' %}

{# ... #}

</code></pre>
<p>Note: If you are using Twig outside of Symfony2 then you will need to add an alternative way of identifying whether it is an Ajax request.</p>
<p>It's a simple as that. However we can add an improvement in order to avoid having to repeat that check in multiple inner templates. By adding an intermediate template that contains just that logic and extending the inner template from it this can be kept in a single template:</p>
<pre><code class="language-language-markup">{# app/Resources/views/layout.html.twig #}
{% extends app.request.xmlHttpRequest 
         ? '::ajax-layout.html.twig'
         : '::full-layout.html.twig' %}

</code></pre>
<pre><code class="language-language-markup">{# src/Acme/DemoBundle/Resources/views/Product/new.html.twig #}
{% extends '::layout.html.twig' %}

{# ... #}

</code></pre>
<p>Another possible time you may need this sort of solution is where a template should sometimes be rendered as a main request and sometimes as a subrequest. The only real difference here is the logic in checking which template to extend. By passing a parameter when rendering a subrequest you can then check that:</p>
<pre><code class="language-language-markup">{# ... #}

{% render url(&quot;inner_route&quot;, { 'partial': true }) with {}, { 'standalone': true } %}

{# ... #}
</code></pre>
<pre><code class="language-language-markup">{# app/Resources/views/layout.html.twig #}
{% extends app.request.partial 
         ? '::full-layout.html.twig'
         : '::partial-layout.html.twig' %}

</code></pre>
<p>If you needed to combine these and other reasons for making the decision it would be worth moving the logic involved to a function using a <a href="http://symfony.com/doc/current/cookbook/templating/twig_extension.html">Twig extension</a> where it could then be tested outside of the template.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Trimming Fat from Controllers]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In this post I am going to look at some techniques for cleaning up <a href="http://symfony.com">Symfony2</a> controller actions. Some of this by using some of the extras that are part of the standard distribution and some by moving code out to be triggered by events.</p>
<p>So here is a fairly standard</p>]]></description><link>https://richardmiller.co.uk/2012/10/31/symfony2-trimming-fat-from-controllers/</link><guid isPermaLink="false">5e3825edde21b10018bb8279</guid><category><![CDATA[dependency injection]]></category><category><![CDATA[doctrine]]></category><category><![CDATA[doctrine2]]></category><category><![CDATA[php]]></category><category><![CDATA[symfony2]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Wed, 31 Oct 2012 08:39:59 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In this post I am going to look at some techniques for cleaning up <a href="http://symfony.com">Symfony2</a> controller actions. Some of this by using some of the extras that are part of the standard distribution and some by moving code out to be triggered by events.</p>
<p>So here is a fairly standard update action in a controller:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Form\ProductType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     */
    public function updateAction($id)
    {
        if (false === $this-&gt;get('security.context')-&gt;isGranted('ROLE_ADMIN')) {
            throw new AccessDeniedException();
        }

        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $product = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$product) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $request = $this-&gt;getRequest();
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $product-&gt;setLastUpdated(new \DateTime);
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $id))
            );
        }

        return new Response(
            $this-&gt;renderView(
                'AcmeDemoBundle:Product:edit.html.twig',
                array(
                    'product'      =&gt; $product,
                    'edit_form'   =&gt; $editForm-&gt;createView(),
                )
            )
        );
    }

    //...
}
</code></pre>
<p>The controller action starts by checking if the current user has the <code>ROLE_ADMIN</code> role and throws and exception if they don't. The product entity is retrieved from the database based on the passed id. A form is created and the request retrieved from the container and bound to the form. If the form is valid the entity has its last updated field updated, the entity manager is flushed and an email sent to notify of the changes. If the product changes are not valid then the edit form is redisplayed.</p>
<p>The controller action is quite lengthy now and some of the work being done, in particular the sending of the email, does not really belong in it. Let's go through some steps we can take to arrive at a much leaner controller.</p>
<p>Starting with a task common to many actions, the rendering of the template and returning a <strong>Response</strong> object with the results can be made simpler. By adding the <a href="http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/annotations/view.html">Template</a> annotation we can just return the array of parameters to be passed to the template. With the annotation in place, when you return the parameters the template will be automatically rendered and a Response with the result sent. Note that the annotation is namespaced and requires the use statement to be added:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Form\ProductType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction($id)
    {
        if (false === $this-&gt;get('security.context')-&gt;isGranted('ROLE_ADMIN')) {
            throw new AccessDeniedException();
        }

        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $product = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$product) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $request = $this-&gt;getRequest();
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $product-&gt;setLastUpdated(new \DateTime);
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $id))
            );
        }

        return array(
            'product'      =&gt; $product,
            'edit_form'   =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>A further annotation, the <strong>Secure</strong> annotation can be used to replace the permissions checking. By adding this annotation the check for the <code>ROLE_ADMIN</code> role and the exception throwing if necessary, will take place without the need for the code:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Form\ProductType;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Secure(&quot;ROLE_ADMIN&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction($id)
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $product = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$product) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $request = $this-&gt;getRequest();
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $product-&gt;setLastUpdated(new \DateTime);
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $id))
            );
        }

        return array(
            'product'      =&gt; $product,
            'edit_form'   =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>We can use Symfony2 resolving of controller action arguments to remove more code from our action. First by having the request automatically injected as a method argument. By type hinting the argument as <strong>Request</strong> the current request will be passed to the action automatically and we can remove the line requesting it from the controller:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Form\ProductType;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Secure(&quot;ROLE_ADMIN&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction(Request $request, $id)
    {
        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $product = $em-&gt;getRepository('AcmeDemoBundle:Product')-&gt;find($id);

        if (!$product) {
            throw $this-&gt;createNotFoundException('Unable to find Product entity.');
        }

        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $product-&gt;setLastUpdated(new \DateTime);
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $id))
            );
        }

        return array(
            'product'      =&gt; $product,
            'edit_form'   =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>We can do something similar for the Product by using the <a href="http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/annotations/converters.html">ParamConverter</a> annotation. So instead of the <code>$id</code> argument we have a <code>$product</code> type hinted as our Product entity. This is automatically retrieved from Doctrine or an exception thrown if it is not found, pretty much as we were doing in the code anyway, allowing us to remove the code for getting the entity from the database altogether:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Entity\Product;
use Acme\DemoBundle\Form\ProductType;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @ParamConverter
     * @Secure(&quot;ROLE_ADMIN&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction(Request $request, Product $product)
    {
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $product-&gt;setLastUpdated(new \DateTime);
            $em = $this-&gt;getDoctrine()-&gt;getManager();
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $product-&gt;getId()))
            );            
        }

        return array(
            'product'      =&gt; $product,
            'edit_form'   =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>In fact in this case, where we are not setting any options on the ParamConverter annotation, we can omit it altogether:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Entity\Product;
use Acme\DemoBundle\Form\ProductType;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Secure(&quot;ROLE_ADMIN&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction(Request $request, Product $product)
    {
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $product-&gt;setLastUpdated(new \DateTime);
            $em = $this-&gt;getDoctrine()-&gt;getManager();
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $product-&gt;getId()))
            ); 
        }

        return array(
            'product'      =&gt; $product,
            'edit_form'   =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>If you have are not using Doctrine then you can still get similar results by <a href="http://php-and-symfony.matthiasnoback.nl/2012/03/symfony2-creating-a-paramconverter-for-deserializing-request-content/">creating your own ParamConverters</a>.</p>
<p>We have now removed a lot of the boiler plate code that is needed in a lot of actions and we are starting to be able to see what our action is doing better. It looks like it is doing a bit too much around the saving of the product changes. Keeping track of when it was last updated is really a job for the entity itself rather than the controller. Fortunately with a Doctrine entity this can be easily achieved with Doctrine's lifecycle callbacks. By enabling these with an annotations and then annotating a method that updates the <code>lastUpdated</code> field before the update is persisted:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks()
 */
class Product
{
    /**
     * @ORM\column
     */
    private $lastUpdated;

    //..

    /**
     * @ORM\preUpdate
     */
    public function setUpdated()
    {
        $this-&gt;lastUpdated = new \DateTime();
    }
}
</code></pre>
<p>We can now remove worrying about keeping this up to date from the controller. This time not only have we reduced the controller action we have ensured that the last update field is kept up to date however the entity is updated and not just from our controller action.</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Entity\Product;
use Acme\DemoBundle\Form\ProductType;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Secure(&quot;ROLE_ADMIN&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction(Request $request, Product $product)
    {
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $em = $this-&gt;getDoctrine()-&gt;getManager();
            $em-&gt;flush();

            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($this-&gt;container-&gt;getParameter('acme.product_email.from'))
                -&gt;setTo($this-&gt;container-&gt;getParameter('acme.product_email.to'))
                -&gt;setBody($this-&gt;renderView(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $product))
                )
            ;
            $this-&gt;get('mailer')-&gt;send($message);

            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $product-&gt;getId()))
            ); 
        }

        return array(
            'product'      =&gt; $product,
            'edit_form'   =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>The last step is to remove the sending of the email, we can again do this with an event. In this case we need to use the mailer service and we do not want to have to inject it into our entity. We can use a standalone event listener instead and inject the services and parameters we need directly into the constructor:</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Listener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Acme\DemoBundle\Entity\Product;

class ProductEmailler
{
    protected $mailer;
    protected $templating;
    protected $emailFrom;
    protected $emailTo;

    public function __construct($mailer, $templating, $emailFrom, $emailTo)
    {
        $this-&gt;mailer = $mailer;
        $this-&gt;templating = $templating;
        $this-&gt;emailFrom = $emailFrom;
        $this-&gt;emailTo = $emailTo;
    }

    public function postUpdate(LifecycleEventArgs $args)
    {
        $entity = $args-&gt;getEntity();

        if ($entity instanceof Product) {
            $message = \Swift_Message::newInstance()
                -&gt;setSubject('Product updated')
                -&gt;setFrom($emailFrom)
                -&gt;setTo($emailTo)
                -&gt;setBody($this-&gt;templating-&gt;render(
                    'AcmeDemoBundle:Product:email.txt.twig',
                    array('product' =&gt; $entity))
                )
            ;
            $this-&gt;mailer-&gt;send($message);
        }
    }
}
</code></pre>
<p>In the service configuration file we specify the services and parameters to pass into the listener and tag it as an Doctine event listener. The listener will now be called after an entity is updated:</p>
<pre><code class="language-language-markup">&lt;services&gt;
    &lt;service id=&quot;acme.listener.product_email&quot;
             class=&quot;Acme\DemoBundle\Listener\ProductEmailler&quot;&gt;
        &lt;argument type=&quot;service&quot; id=&quot;mailer&quot;/&gt;
        &lt;argument type=&quot;service&quot; id=&quot;templating&quot;/&gt;
        &lt;argument&gt;%acme.product_email.from%&lt;/argument&gt;
        &lt;argument&gt;%acme.product_email.to%&lt;/argument&gt;
        &lt;tag name=&quot;doctrine.event_listener&quot; event=&quot;postUpdate&quot; /&gt;
     &lt;/service&gt;
&lt;/services&gt;
</code></pre>
<p>We can now remove the sending of the email from the controller. Again as well as reducing the size of our controller we have introduced flexibility to our application. It is now easy to change or remove the listener without having to touch the controller code. We could even add another listener to send SMS notifications without touching the controller. If you are not using Doctrine then you can still gain these benefits by raising your own events with the <a href="http://symfony.com/doc/master/components/event_dispatcher/introduction.html">event dispatcher</a>.</p>
<pre><code class="language-language-php">&lt;?php

namespace Acme\DemoBundle\Controller;

use Acme\DemoBundle\Entity\Product;
use Acme\DemoBundle\Form\ProductType;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

/**
 * @Route(&quot;/product&quot;)
 */
class ProductController extends Controller
{
    //...

    /**
     * @Route(&quot;/edit&quot;, name=&quot;product_update&quot;)
     * @Method(&quot;POST&quot;)
     * @Secure(&quot;ROLE_ADMIN&quot;)
     * @Template(&quot;AcmeDemoBundle:Product:edit.html.twig&quot;)
     */
    public function updateAction(Request $request, Product $product)
    {
        $editForm = $this-&gt;createForm(new ProductType(), $product);
        $editForm-&gt;bind($request);

        if ($editForm-&gt;isValid()) {
            $em = $this-&gt;getDoctrine()-&gt;getManager();
            $em-&gt;flush();
            return $this-&gt;redirect(
                $this-&gt;generateUrl('product', array('id' =&gt; $product-&gt;getId()))
            ); 
        }

        return array(
            'product' =&gt; $product,
            'edit_form' =&gt; $editForm-&gt;createView(),
        );
    }

    //...
}
</code></pre>
<p>Our controller is now much shorter than before by removing much of that boiler plate code and it is easier to see what is happening. The decision about what happens when a product is updated have been moved away from the controller and into the model layer.</p>
<p><strong>Note</strong>: The example controller extends from the base controller and makes direct use of the service container. I have <a href="https://richardmiller.co.uk/2011/06/14/symfony2-moving-away-from-the-base-controller/">previously written about</a> moving away from in favour of controllers as services. I do think there are advantages to that but since extending the base controller is more common, I have based my example for this post on that.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Symfony2: Console Usage Notes]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>There is quite a lot of documentation, blog posts etc out there on writing console commands for <a href="http://symfony.com">Symfony2</a>. Here though I am going to look at the more basic usage of the console with a few notes on getting more out of it.</p>
<h2>Listing Commands</h2>
<p>You can get a list</p>]]></description><link>https://richardmiller.co.uk/2012/08/17/symfony2-console-usage-notes/</link><guid isPermaLink="false">5e3825edde21b10018bb8273</guid><category><![CDATA[symfony2]]></category><dc:creator><![CDATA[Richard Miller]]></dc:creator><pubDate>Fri, 17 Aug 2012 13:23:02 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>There is quite a lot of documentation, blog posts etc out there on writing console commands for <a href="http://symfony.com">Symfony2</a>. Here though I am going to look at the more basic usage of the console with a few notes on getting more out of it.</p>
<h2>Listing Commands</h2>
<p>You can get a list of the options for running commands as well as the currently registered commands by runnning</p>
<pre><code class="language-language-markup">$ app/console list
</code></pre>
<p>you can omit the <code>list</code> and just run</p>
<pre><code class="language-language-markup">$ app/console
</code></pre>
<p>for the same output.</p>
<p>Third party bundles can register new commands so the list can change as you install more bundles into an application.</p>
<p>The commands are namespaced using : as the separator, you can list just the commands in a particular namespace by specifying the namespace with the list commands. For example to just see a list of <code>doctrine</code> commands:</p>
<pre><code class="language-language-markup">$ app/console list doctrine
</code></pre>
<p>You can be more specific again with:</p>
<pre><code class="language-language-markup">$ app/console list doctrine:mapping
</code></pre>
<p>to just see the Doctrine mapping related commands.</p>
<h2>Help</h2>
<p>You can just get usage details and options without the list of commands with</p>
<pre><code class="language-language-markup">$ app/console help
</code></pre>
<p>You can get help specific to an individual by specifying that command a well, e.g.:</p>
<pre><code class="language-language-markup">$ app/console help router:debug
</code></pre>
<h2>Shell</h2>
<p>If you have several commands to run then using the <code>shell</code> option will stop you being returned to the normal command line and allow you to just run Symfony2 commands without the need for specifying <code>app/console</code>:</p>
<pre><code class="language-language-markup">$ app/console --shell
Symfony &gt; cache:clear 
</code></pre>
<h2>Shortcut Syntax</h2>
<p>You can avoid having to type out the full names of commands by just typing the shortest part needed to make it unambiguous. For example, to clear the cache you can just type:</p>
<pre><code class="language-language-markup">$ app/console ca:c
</code></pre>
<p><code>ca</code> rather than <code>c</code> is needed to avoid ambiguity with <code>config</code> and <code>container</code>.</p>
<h2>Different Environments</h2>
<p>By default when you run a console command it will run in the <code>dev</code> environment. You can change this by specifying the environment:</p>
<pre><code class="language-language-markup">$ app/console clear:cache --env=prod
</code></pre>
<p>For some commands the environment you run in important because it will change the effect of running the command e.g. <code>cache:clear</code> and <code>assetic:dump</code>. For other commands though they will run the same but you will get them to run quicker and use less memory by using the <code>prod</code> environment - remember to clear the production cache if necessary first though.</p>
<p>You can still run commands in the <code>dev</code> environment and get some performance gain for commands which collect a lot of debug information by turning off debug mode. For example, the <code>populate</code> command in the FOQElasticaBundle will, by default, collect a lot of debug information which will cause it to use a lot of memory when indexing a lot of entities, this can be avoided  by specifying no debug:</p>
<pre><code class="language-language-markup">$ app/console foq:elastica:populate --no-debug 
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>