Symfony2: Top Down Perspective of Service Configuration

One issue many people have with Dependency Injection is the way you can no longer jump to an implementation of a dependency in an IDE and see what it actually does or make changes to it. This is indeed a side effect of moving towards much more loosely coupled code. If you are injecting a dependency and type hinting it with an interface, then you cannot jump straight to the particular implementation without looking at the DI configuration to see what implementation is being used.

This is not a bad thing though in my opinion, it is just part of moving away from coding to an implementation instead coding to an interface. The code you are working on does not know about the details of the implementation only its public methods, so in many ways it helps to, in effect, only know that yourself when working on that class. A big advantage of Dependency Injection is shifting the decision of what implementation to use out of the code and into a separate configuration, which is  why it is a good thing to be ignorant of this configuration when coding.

The inverse way of looking at this issue is that if you are not using Dependency Injection to pull all of this configuration out of the code then you cannot get a top down perspective of how the application is wired together without digging through the code itself. By separating the configuration from the classes themselves  you can more easily get an overview of how all the classes work together in an application.  Once you have made this shift in your way of thinking then it seems less problematic to not be able to jump to the implementation when working in the code.

If you are working with Symfony2 then as well as just looking at the services config files there are some great tools to get an overview of the services.

Out of the box there is a console command that will print out a list of all the services in the service container.

You can also specify a service by id to get more detailed information:

Whilst the console command is certainly helpful, especially for resolving service ids to actual class names, there is more information it would be helpful to be able to view. Johannes M. Schmitt‘s Debugging Bundle provides more useful tools for working with services in Symfony2. Once installed it adds a new section to the web profiler called service container where you can view information about the services being used in your application.

There is an overall graph of the services, this is split into pages since a typical service graph will include a lot of services:

Service Graph

You can also view the services as a list. The list shows what calls were made to include services including where they originated from, the type of injection which took place, e.g. during construction and whether it was constructed for this call or already existed:

Service List

Most helpfully if you are trying to find out more about a particular service, you can search by service name with an auto-complete facility:

Service Id Autocomplete

You can then view the outgoing services for the chosen service, that is the services that are injected into that service and their dependencies:

Outgoing Service Graph

You can also choose to view the incoming services, that is the services that the chosen service is injected into.

Incoming Service

This all helps to visualise the use of the various services and how they interact with each other. This is a much more difficult task when the dependencies are not injected into classes. You may be able to see what dependencies a class has just from the code but you cannot see which other classes use those dependencies as well nor can you easily see what code uses the class you are working in.

Why use a Dependency Injection Container?

In this post I am going to look at the basics of Dependency Injection again and how they tie in with the move to using a Dependency Injection Container. The basics of why injecting an object’s dependencies is a good idea are fairly easy to grasp, how this then leads to the use of a container is not so easily apparent.

Starting Point

So let’s start by introducing the examples to be used. First up we have a controller that validates POST data and if valid sets up a Product object and passes it to a ProductSaver object to deal with persisting it. For the sake of simplicity the validation part is not actually shown:

The ProductSaver object persists the Product, again not actually shown, and then passes the product to an EmailNotifier object:

The EmailNotifier object creates a message notifying of the addition of the Product and sends it via a Mailer object:

First Steps

Let’s say we need to change the address we are sending the email notification to, to do this we will have to edit this code. If we wanted to use it in a different application where the email went to a different address then we would need to maintain two different versions. So let’s move the address out of the class and inject it instead:

So by passing the email address in via the constructor we have now removed the need to have different versions of the class for different addresses. For the other application we want to CC the email to two different addresses, this means that the technique we used above would not work as we can only pass in one email address, instead what we can do is use setter injection and add the addresses to an array:

So now we can add as many CC addresses or even no CC addresses without having to change the class at all. To make it fully clear of any dependencies we could also inject the Mailer object, this is best suited to constructor injection again as it is a required dependency:

It looks like we can do the same with the Mail object but we need to be careful, whilst we can use the same Mailer object each time notify() is called, we actually want a fresh Mail object on each call. So, if we want to remove the Mail object, we would be better using a factory. Whilst many factory examples use a call to a static method to fetch the object we would then be stuck with a particular factory. Instead we can inject the factory into the class leaving us free to choose what factory to inject.

For more information on the types of dependency injection see my post Symfony2: Dependency Injection Types.

What have we achieved? Well we have made our class look much more complicated, is this really a good thing? Whilst it looks more difficult to maintain and possibly harder to follow, we can now reuse it in different applications with different email addresses and even a different Mailer. This means that we now only need to maintain one version of it and not one for each combination of addresses and Mailer. This means that we have reduced the overall potential maintenance. We have also simplified the role of this class, it now only needs to concern itself with creating the email to send and no longer with whom to send it to and which Mailer to use.

Pushing Creation Upwards

Great then, but where does all the injection of these dependencies go? If we just now tried to use this from our ProductSaver class, we would have problems, as the EmailNotifier is not set up with all its dependencies. To set it up in the ProductSaver we would need to make these changes:

This no longer looks so good, by shifting the set up of the EmailNotifier out of the class itself to the point of creation we have ended up giving the responsibility of setting it up to the ProductSaver. If we didn’t want the EmailNotifer to be concerned with where the email is sent then we definitely don’t want the ProductSaver to be responsible for it. So what do we do? The same as we did in the EmailNotifier, remove the point of creation of its dependencies out of the class:

Whilst we are at it lets move the DataMapper out as well:

Ok problem solved, well sort of. We have pushed the creation up to our controller so that now looks like this:

So I guess we had better repeat the process and push it up out of our controller and into a bootstrap file that sets up our controller. So the controller now looks like this:

With a bootstrap file to set it up:

Great now we can just have a different bootstrap file for each application and set up the configuration of which services we want to use and how to configure them without needing to touch any of the other code.

Managing the Configuration

At the moment this still looks fairly manageable in this way but this is of course a huge simplification. In a real world app, in which we had performed this process of moving the dependencies up through out, the configuration would be much more complicated. For a start we would need to set up the configuration and dependencies of our DataMapper and EmailNotifier. There is also the code that was not shown for the validation of the POST request, we would also need to set up a response to send back to the browser. So the configuration will grow and grow and start to become difficult to maintain itself. That is only for a single action taking place in our application, for the other actions of the controller we may well need to set up other dependencies and configuration. Then there are all the other Controllers and their set ups.

At this point you will probably also have noticed that all the code in the set up is essentially repetitive instantiation of objects and calling of setter methods. Of course, we will want to do something about all this repetition. This is essentially what a Dependency Injection Container (DIC) is, it deals with the instantiation and set up of our dependencies for us and allows us to just specify them in a configuration file.

For the examples, I am going to look at the Symfony2 Dependency Injection Container or Service container as it is also known in the documentation. This is because Symfony2 is the next generation PHP framework which is closest to release and which has a working DIC. In Symfony2 we can set up this configuration using YAML, XML or PHP, I cam going to look at the XML version here. So our set up above could now be done with the following XML file:

We can now get the ProductController from the DIC which will set it up with all of its dependencies:

So the DIC has helped us to clean up the repetition in our setting up of our dependencies. We can now just maintain config files for the DIC for each application.

So having seen loomed at the low level advantages of using DI, we can start to see some of the the application level benefits of using a DIC for DI. We can now avoid any configuration taking place in our code. It is no longer the responsibility or concern of the code but instead a configuration issue. This allows for rapid application development as we can easily reconfigure the framework to suit the current application.

When we do actually want to write some code rather than config files because we want to add a new feature, then we can write a new version of the class that needs the new functionality and just drop it in using the DIC config. Rather than repeat the existing functionality we could decorate the existing class to add this functionality:

We would then not need to change any existing code just the config, these are the changes to the relevant parts:

Other Advantages

Another advantage of using a DIC over writing the object creation code ourselves is that if we were to write the creation of all our controllers then we would be creating a lot of objects that are not used in a request. This is a problem in PHP where everything is created on each request, using a DIC if we request the controller from it then only that controller and its dependencies will be created and not the other controllers. In fact better than this, a good container will use proxies for dependencies and only create them as needed. This means that any objects that are not used due to the execution path of the code are not created, so the cost of creating unused dependencies is avoided.

Other performance measures taken by a DIC such as Symfony2’s include the compilation and caching of the config files so that this is avoided on each request and caching of the actual classes as well. I do not know the internals of Symfony2’s DIC to go into any real details about this though.

Conclusion

To get the benefits of Dependency Injection you need to keep pushing the creation of dependencies up through the code until it reaches the top. Once this is done a Dependency Injection Container helps to manage the resulting complicated configuration code as well providing performance benefits over directly creating the classes.

Disclaimer: As well as the usual issues of error checking and what have you in the code examples, there is the specific issue that having the ProductSaver directly invoke the email sending and logging is not really the best approach. It would instead be preferable to do something such as making the ProductSaver observable and registering logging and email notification as observers or using Symfony2’s event dispatcher.

Symfony2: Checking Coding Standards

Note: the coding standards used by Symfony2 have changed since this post was written, you can read more about this in my post Symfony2: Coding Standards Update

Coding standards are good, they are especially important on large projects with many collaborators such as Symfony2. Obviously very messy code with no consistency is a problem, it is difficult to read, making it hard to maintain.

There is not only one way to write well formatted code and not everyone agrees on which is the best way to format certain things to say the least. This means that it is important to not just write tidy code but code that is consistent with the code of everyone else involved in the project. So projects such as Symfony2 standardise on a particular set of coding standards which you should adhere to if you are contributing to the project or in Symfony2’s case writing third party bundles. You may also want to make sure that any code you write for an application based on Symfony2 meets the same standards.

The Symfony2 coding standard follows the Pear/ZendFramework standards with a few differences. You can read a detailed list of the standards in the contributing section of the documentation.

PHP_CodeSniffer

Whilst a great starting point trying to actually remember all that when coding will be difficult. Fortunately you can use the PHP_CodeSniffer tool to find any where in your code that does not meet the standards.

You can install PHP_CodeSniffer using Pear:

The Symfony2 coding standard is not included, you can obtain it from Git though, the README.md goes through how to install the custom standard.

So if you had a file with the following code in it:

You can then run PHP_CodeSniffer at the command line to get a report of any errors or warnings, against this file:

This outputs the following report:

You can also run PHP_CodeSniffer against directories rather than individual files.

Phing

As well as running PHPCodeSniffer manually you may want to run in from a build tool such Phing you can then run PHPCodeSniffer along with other tools such as PHPUnit, PHPDepend with one CLI command rather than having to run each separately. There is a built in Phing task for PHP_CodeSniffer that you can use for this. The following will provide a full report on my LimeThinkingSpring bundle:

If you also include in the build file other targets for other tests and a target that depends on them:

you can run them altogether with simple command:

If you prefer to use Ant for builds then it does not have a built in task but you can still use an Exec task to call PHP_codeSniffer:

Jenkins

As simple as it is to run the tests using Phing, you still need to remember to do it. If you are using a tool such as Jenkins for Continuous Integration then you can use it to run these sorts of tests automatically when you commit changes to version control.

There are instructions for setting up Hudson with Phing, Jenkins is a fork of Hudson so you will need to make some changes to the instructions. Whilst my preference is for Phing it is currently easier to set up Jenkins for PHP CI using Ant using Sebastian Bergmann’s excellent Template for Jenkins Jobs for PHP Projects.

The most useful way of integrating PHP_CodeSniffer into Jenkins is to have it output a checkstyle report. You can then use the checkstyle Jenkins plugin to display the results in the build report. This includes details of any errors and warnings. It also displays a graph of the number of errors and warnings across builds:

Example of Checkstyle graph in Jenkins

Eclipse Integration

As well as catching any errors by running PHPCodeSniffer against your code it is possible to integrate it into some IDEs to provide real time checking so you can see any violations as you code. Here I will look at implementing it in Eclipse. There is a plugin to integrate PHPCodeSniffer which is part of the PHP Tool Integration project, you can find more information and installation instructions here.

Again you will need to add in the Symfony2 standard, instructions for doing this are in the configuration section.

Now in Eclipse you will get immediate feedback on any coding standards violations. So our code from before will look like this:
Example of Coding Standards violation being highlighted in Eclipse

This allows you to correct any violations as you code rather than afterwards by running the PHP_CodeSniffer later.

Note: at the time of writing Symfony2 is at Release Candidate stage and moving towards a stable release so they are looking for bug fixes only and not Pull Requests with coding standards changes.

Symfony2: Assetic Twig Functions

In my post Symfony2: Using Assetic for Image Optimisation I looked at using Assetic for image optimisation. In that I looked at OptiPNG set up like this in the config:

and using a Twig template that looks like this:

In order to optimise a PNG file. It is possible however to achieve this with a much simpler Twig template by setting up a Twig function from the Assetic config. By adding the following config:

The Twig template can be changed to the following:

Note that we are no longer using the apply_to filter and instead explicitly specifying the optipng filter with the function call.

You can specify the output directory in the config in the following way:

The function name maps directly to the filter name so these must be the same for this to work. You can only use this to map using a single filter, so for more complex combining of files and use of multiple filters, as you may want to do for JavaScript and CSS files, this is not an appropriate solution. For images though, where you will usually only want to apply a single filter to a single file this is an excellent way of simplifying your Twig templates.

Symfony2: Moving Away From the Base Controller

When you start learning Symfony2 using the book, you are introduced to the base controller. The base controller has some helpful methods to make common tasks easier. After a while though you may want to move away from extending this controller, in fact, it is the advised best practice for controllers in shared bundles. When you do, you will no longer have access to these useful methods, in this post I am going to look at how to accomplish the same tasks without them.

I have created a simple controller for some basic form interaction with a model which uses the base controllers methods. I am going to go through how to change this to a service which does not extend the base controller. The starting point looks like this:

It uses a form type object LimeThinkingSpringBundleFormTestimonialType for the form which looks like this:

The controller as it stands has actions for displaying, adding and editing testimonials. I have extracted the common tasks, retrieving a testimonial from the database and rendering the form, into their own methods. It is routed to like this:

Removing Helper Methods

To start with I am going to change the helper methods to use services still retrieved using the get() helper method which is a short cut for getting services from the container. After this is complete we can convert to a service and inject the required services instead.

The methods we need to replace are:

  • getDoctrine()
  • generateUrl()
  • render()
  • createForm()
  • redirect()
  • createNotFoundException()
  • get()

Once all these are gone we can stop extending SymfonyBundleFrameworkBundleControllerController. To start we will actually introduce more use of get() as this allows us to access services from the Dependency Injection Container (aka Service Container).

getDoctrine()

The easiest to remove is getDoctrine():

becomes

generateUrl()

Next up generateUrl():

becomes

render()

becomes:

createForm()

becomes:

redirect()

Now for a couple that are slightly different:

becomes:

We also need to add:

to the use statements at the top of the file.

createNotFoundException()

becomes:

with:

added to the use statements.

get()

is just a shortcut for

So we can replace all the get() calls throughout.

Now that all the methods from the base controller have been removed we can change to extending ContainerAware instead. doing so means that the container is available to the controller. So the class now looks like this:

Defining the Controller as a Service

We can also now move to defining our controller as a service. See this cookbook recipe and my post Symfony2: Controller as Service for details on how to do this and how to set up an Dependency Injection extension to load a service definition for a bundle. In this case we would change to routing to the controller like this:

with a services XML config like this:

Note that the container is explicitly injected into the service using the method defined in ContainerAware as this is no longer automatically done.

Injecting Services

Now for the more controversial bit. In my opinion injecting the container in this way is not the correct way to use it. I have written about this in these posts: When Dependency Injection goes Wrong and In Defence of Dependency Injection Containers. This is not the opinion of everyone and not an official best practice, it is just my recommendation.

I have also looked at how to inject dependencies in Symfony2 in these posts: Symfony2: Dependency Injection Types and Symfony2: Injecting Dependencies Step by Step. So I am not going to go over how to do this in detail again this time, the end result of removing the services is that the class looks like this:

and the services XML like this:

Edit: As per Stof’s comment the predefined request service should be used. As this is scoped to request the controller will also need to be scoped to request to avoid scope widening. The services.xml should then look like this:

There are still some objects being created using the new keyword. These are all effectively value objects though rather than services. That is to say that they hold specific values and would not be reusable in other classes in the same way that the other injected services are. The RedirectResponse, for example, is specific to the testimonial not being found and is not something we could inject using the container. There is an argument that this is still a dependency that should be removed. If you are that way inclined then a way to do it would be to instead inject Factory objects to create these objects on demand. The factory could then be mocked for testing or a different factory used if you wanted to change the object returned. If you do want to do this then at the moment you will have to write your own though.

In Defence of Dependency Injection Containers

There has been some criticism recently of the use of Dependency Injection Containers (DICs) with a lot of people saying that DI != DICs. For example see http://till.klampaeckel.de/blog/archives/154-Dependency-Injection-Containers.html and the comments on it. Whilst I agree with that DI !+ DICs, I do not agree with it being turned into DI good, DICs bad. In this post I want to look a bit more at this. Disclaimer: A lot of what follows is just my opinion and is not particularly intended as a direct response to the above article. It is as much a response to me sounding a bit anti Dependency Injection Containers in this post When Dependency Injection goes Wrong.

DICs as Glorified Registries

A lot of the criticism has been focused on how DICs are essentially just a glorified registry and introduce dependencies on the container. I fully agree that using a DIC in this way, that is requesting services from it, is indeed problematic.

The problematic usage I am mean is code that looks like this:

So what are the issues with code like this?

Reduced re-usability

We may have removed the direct dependency on whatever my_service is but we have a dependency on the container now. So this code cannot be used without the container, this reduces the re-usability of the code.

Only Slightly Less Tight Coupling

The tight coupling between this class and myservice has been removed, however we have created a coupling between all code that requests myservice from the container as they will receive the same object from the container. We have not created the ability to configure these classes independently of each other.

What is my_service?

In the example code you cannot tell what class my_service is, or more relevantly for using it, what interface(s) it implements. In order to find out you need to consult the configuration of the DIC. Not only can you not tell but your IDE cannot either, so there will be no auto-completion when you are using the service. (I appreciate there are workarounds to this). Additionally nothing enforces the interface of the service so no checking is being done to make sure it is a suitable service before it is put to use.

Unit Testing Difficulties

To write tests for the above code you cannot just mock my_service directly, you either need to use the service container itself to get the mock in or mock the service container and get the mocked container to hand out the mocked service.

This is indeed not Dependency Injection at all in my opinion, you are not injecting the dependencies if you are doing this, you are requesting services from the container, no injection is taking place. Dependency Injection is injecting a class’s dependencies through means such as the constructor or a setter method. The container itself is not seen in such classes.

Actual Dependency Injection

So how can we remove the dependency on my_service without running into the above issues? By injecting it directly into the class. In this example it is injected into the constructor:

So our code now has no direct dependencies on another object, just a requirement that an object implementing the MyServiceInterface interface is passed into the constructor. So there is no tight coupling between the class and a particular implementation of the interface. We have also avoided any coupling with the container.

Other classes which require an implementation of MyServiceInterface can receive the same or a different implementation now so there is no coupling with them. You and your IDE now know you are working with a MyServiceInterface implementation so you will get auto-completion. To test this class we can now just create a mock implementation of the interface and inject it in directly with no need to involve the container.

A big advantage to using DI in this way throughout your code, is that it fully separates the configuration from the rest of the code. This means that you can wire up the classes differently for different applications easily. None of the code outside of the parts doing the wiring needs to be aware of the particular configuration. There is no need for messy code choosing which version of a class to use. If you need different functionality for a different app then you can just drop in a class with the new functionality without needing to touch the existing code.

There is a learning curve to starting to code in this way, as well as getting used to having to create the DI configuration instead of creating classes directly in the code, but its one that is well worth it.

Where does this leave DICs?

So does this mean that DICs are bad full stop? No quite the opposite. If you do DI properly and use constructor and/or setter injection (and possibly property injection) then in a large application DICs offer many advantages in wiring up the application.

For very small apps and when writing tests it is easy enough to just create the classes and pass them in as dependencies. In a large application with a complicated object graph this becomes a difficult task. This is where a DIC comes into its own. I am mainly going to concentrate on the Symfony2 service container when looking at the advantages of using a DIC for this large scale wiring, as it is the one I am most familiar with.

The first advantage is that the Symfony2 container allows you to configure services using YAML, XML or PHP and then takes care of the actual creation of the objects. This means that you can write much more readable configurations. For examples of configuring Dependency Injection in Symfony2 using XML see my post: Symfony2: Dependency Injection Types

Another advantage is that you do not have to configure everything in one place. In Symfony2 the code is separated into bundles, both the core code and third party code is all in this bundle form. Each bundle contains its own services configuration files so only the DI configuration for the bundles actually being used is read into the DIC. Trying to create such a complex wiring in one place without the help of a DIC would be a mammoth task.

The DIC also carries out other tasks to aid in performance. This is particularly important when doing large scale DI in PHP as these are not long running services as with Java but created on each request. One aspect of this is caching of the confguration once it has been “compiled” from the XML or YAML config files. Another is the use of proxy classes for lazy loading, meaning that the full object graph is not created every time but only when services are actually used. All this happens behind the scenes but is completely separated from the code that is wired together, which itself is unaware of the way in which it is wired up.

Conclusion

So is it true to say that DI != DICs, well yes sort of. More accurate would be to say that DI, possibly using a DIC for configuration != requesting services directly from a DIC being used as a glorified registry. Unfortunately that’s not quite as snappy.

Symfony2: A Few Assetic Notes

Just a quick post with a few notes on Assetic. These are mainly on topics people have been searching for when they have visited this blog.

Loading Filters

If you are using Assetic from Symfony2 then its worth being aware that it does not automatically load up all the available filters. Only the filters you specify in your app’s config will be loaded. So for example to use the yui_css filter you need to specify it like this in the app’s config.yml:

It will then be loaded and available to use. If you do not do this you will get error messages such as:

If the filter you want to use does not need options setting for it then you can make sure it is loaded like this:

Watch for Changes to Dumped Files

Your assets can be dumped to the file systems as static files in order to serve them efficiently. For production you can do this on deploy. For development you can just let Assetic produce them on demand, however you can instead dump them as static files using the watch option like this:

With this the command will not exit and loop constantly checking for changes to the files you are serving using Assetic, if any changes are detected they will be dumped again so you will see the changes. It will also respond to changes in the Twig templates, so if you do something such as include an additional CSS file in the collection of assets to be served as a single file then it will be dumped again including the extra asset.

Avoid Overwriting your Working Files

If you are dumping your files to web/css and web/js etc. then do not keep the working files there, they will get overwritten when you dump the files.

Image Resizing/Manipulation

You can use Assetic for some image processing, see my post Symfony2: Using Assetic for Image Optimisation for more details. However you cannot currently use it for tasks such as resizing and cropping. You can still do these tasks from Twig templates by using the AvalancheImagineBundle, which is a Symfony2 bundle to allow you to use the Imagine library from Twig. Imagine provides a standard Object Oriented interface for image manipulation in PHP and uses extensions such as GD2, Imagick and Gmagick for the processing. The bundle currently only has a built in filter for thumbnailing images but you can create custom filters for your own needs.

Symfony2: Writing a Dependency Injection Extension Configuration

In this post I will look at how to write a more sophisticated Dependency Injection Extension for your Symfony2 bundles.

Bundle Level Config

In my earlier post Symfony2: Controller as Service I looked at creating a very basic extension that would allow us to load an XML file defining the services. The class looked like this:

This loads a single service config XML file. You are not tied to using XML for this, YAML or PHP configuration can also be used and would be loaded as follows:

Doing any of the above will load the relevant service config into the Dependency Injection Container (or Service Container as it is also known). Whilst you can use YAML or PHP config files the best practice recommendation is to use XML for bundle service configuration if the bundle is intended to be released as a third party bundle. Whilst YAML is good for simpler config files the verbosity of XML is actually an advantage when maintaining a more complicated one. Likewise the nature of the PHP config means it is more difficult to decipher, the choice is still your’s though.

You are not limited to loading a single config file, this way you can split up complicated service definitions into manageable files. For any parameters or service definitions that appear in multiple files those loaded later will overwrite these values. You can also then only load the definitions needed for an app rather then everything. For example in the AsseticBundle only the filters specified in the app config will have their service definition loaded.

For more details on how to write the bundle level XML config please read my posts, Symfony2: Dependency Injection Types and Symfony2: Injecting Dependencies Step by Step

App level config

So far I have only looked at loading config kept within the bundle. You can open up parameters to be set from an app’s config file. Any config parameters relating to the bundle from the app’s config will be passed into the load method of our extension as the $configs argument. So if the app’s config.yml file contained the following settings:

then the passed in $configs array will be the following array

It is nested in an array because you can have multiple config files, each will be placed into an array. So if you have also have settings in config_dev.yml:

Then the received configs array would like this:

You can then use these to set parameters in the Container in the following way:

Edit: Accessing the config variables in the above example does not deal with merging the values from different configs, it has effectively ignored the setting in config_dev.yml. Using the Config component as described below will avoid this problem.

Configuration Building

It is not however advisable to just set any values in the config to the DIC’s service definitions. It would be much better to only set the values you want and to do some validation of the values passed in. Fortunately the pain of this is alleviated by using the built in Config component. We can build a configuration using its fluid interface which allows us to build up complex configurations specifying value types and more . Lets start with an example to show how to do this:

We can then use this to process the values passed in from the app’s configs by adding to our Extension’s load method:

The Processor will merge the values from $configs with the Configurtaion we have built checking the values as we go. In the above case we will end up with a a merged config that looks like this:

The Processor merges the values from the config tree with those from the app level config, if there are multiple app level configs then any repeated values are overwritten by those later in the array. The order they are in the array depends on which file imported which with those imported later appearing earlier in the array. Whilst this sounds counter intuitive it is what allows the values in config_dev.yml, which imports config.yml, to overwrite the ones in config.yml.

The Processor will not merge this config into the Service Container’s config automatically but returns it as an array, you still need to choose which values from the config to write to the Service Container.

One thing to note is that when merging a configuration in this way is that an exception will be thrown if any values not specified are included in the app’s config rather than them just being ignored.

Configuration Nodes

So let’s look at the Configuration in some more details and look at some of the node types and their settings. The first thing to note is that the TreeBuilder uses a fluid interface so we can chain method class, each time you add a node you move to calling its methods, a call to the end() method moves you back up to the parent.

In the example above I used three types of node, scalar, boolean and array, so have a look at these and the other node types in a bit more detail:

Variable Node

variableNode() This is the most basic node type and does nothing to enforce the value of the node.

Scalar Node

scalarNode() A scalar node can be used for the following types: booleans, strings, null, integers, floats. Attempting to set something else to it, such as an array, will result in an exception being thrown.

Boolean Node

booleanNode() Whilst you can use a scalar node for boolean values using a boolean node will ensure that only boolean values can be set as an exception will be thrown for any other values.

Array Node

arrayNode() You can use an array node to allow nested config values in the app level configuration. In the above example I then explicitly set the children of the arrays type. Of course we do not always want to specify what every child of the array should be to allow some flexibility in the config. This means there is much more to using Array Nodes, howver I am not going to cover this here but will look at it in a future post. Edit: I have not covered this in a future post but it is not documented in the Symfony2 component documentation

Configuration Settings

Using the correct node type will provide us with some immediate checking of the value to ensure it is the correct type. Additionally further settings for each node can be made to further validate the config. Some of the settings we can use to enforce use are as follows.

Default Value

defaultValue($value) You can use this to set a default value for the node, if the node is then not given a value in the app level config the default value will be used. If no default value is given and the node is not given a value in the app level config then it will not appear in the processed config.

There are short cut methods available for setting the default value to true, false and null, these are respectively defaultTrue(), defaultFalse() and defaultNull()

Required

isRequired() You can specify that a node is required, if it is set and the node has no value set in the app level config an exception is thrown.

Allow Overwrite

cannotBeOverwritten() You can use this to say that the value of a node and its children cannot be overwritten. This does not mean that a default value is used and no value can be set in the app level config but that it can only have its value set in one app level config file.

Treat Like

treatTrueLike($value) This allows you to make your configuration easier for end users, by treating them setting true as something else in the background. For example if you had treatTrueLike('complicatedValue') then if the node is set to true in the user level config then it will be set to complicatedValue in the processed config. As well as treatTrueLike() there is treatFalseLike() and treatNullLike().

These are by no means a full list of the configuration possibilities, whilst there is not much documentation for this available at the moment you can learn a lot by having a look at the Configuration classes in the Bundles included in the standard distribution of Symfony2.

Symfony2: Using Assetic for Image Optimisation

Symfony2 uses Assetic for asset management, I have previously written about its use for JavaScript and CSS files. In this post I am going to look at another of its uses, optimising images. Amongst its many filters, Assetic currently has four which can be used for on-the-fly image optimisation. This way you can get the benefits of smaller file sizes without having to use an image editor to process each image. The results are cached and can be saved for production so there is no performance hit for your end users.

I am going to look at two of these filters in this post OptiPNG and jpegtran, There is also support for PNGOUT and Jpegoptim. The former two were available for install through my package manager so they won.

OptiPNG

This can be used to compress PNG images, all you need to do is add this to the Assetic section in your app’s config.yml file:

The bin setting is only needed if OptiPNG is not in the default location of /usr/bin/optipng.

All PNG files that you include in your Twig templates will now be automatically optimise providing you use Assetic to the serve them. This means including them in this way:

The default optimisation level used by OptiPNG depends on the version, you can get more information on this and what the levels actually mean in the options section of the OptiPNG manual. You can set the level in the config.yml:

Setting the level option is only available in the latest version of Symfony2 from Git at the time of writing and was not in the latest release (beta 2). Edit: It is possible with the beta 3 release now available.

jpegtran

jpegtran can be used for JPEG optimisation, in this case there are two main things you can do. The first is to optimise the file by removing meta information stored in the file that is not used for display. To do this you just need to specify optimisation in the config, since jpegtran has other uses:

and the following in Twig:

Note the use of apply_to: ".jpe?g$" in the config to target both .jpg amd .jpeg file extensions. You may find this optimisation makes no difference though as some image editors will strip out this information by default when saving as a JPEG, this was the case in Gimp for me anyway.

You can also use jpegtran to convert JPEGs to progressive JPEGs, this does not always make the file size smaller though so it is not an automatic gain, there is a lot more information about this in this YUI blog article on image optimisation. To convert all your JPEGs change the config settings to

Again, at the time of writing this, both of these options will only work with the latest Symfony2 from git and not with beta 2. Edit: they will work with the beta 3 release now available.

Saving for Production

For production, rather than using Assetic to serve the files up as requested, checking the cache each time, it is better to save them as static files. In fact by default Assetic is not routed to in the prod environment so the images will not appear if you do not do this. Dumping the files is easy though using the Symfony2 console:

The files will now be served up as static files and PHP will not be used at all. You just need to remember to regenerate the files whenever they have changed. Making this part of an automated build process with a tool like Phing or Ant will ensure this happens.

Symfony2: Make your own Assetic Filter

Symfony2 uses Assetic as its asset manager, it provides many excellent filters for processing CSS, JavaScript and Image files. You may find though that the existing filters do not perform a task you need. Thanks to the excellent Dependency Injection in Symfony2 it is easy to write your own filter and put it to use without touching any of the code for Assetic itself.

Your filter can live where ever you see fit as we will be able to point to it using our service config, I am going to put mine in the test bundle I have been using. My post, Symfony2: Controller as Service, has details of how to create a Dependency Injection extension to load a service config for your bundle as you will need to use this to configure the filter later.

Your filter needs to implement the Assetic/Filter/FilterInterface which is as follows:

So you need to implement the two methods filterLoad and filterDump, the former is run when the filter is first loaded and the latter when the assets are dumped. In most cases the work can be done in filterDump so you can just have an empty filterLoad method:

So how do we put this to use? The key is to use the tag element in the service config:

Tagging the service with assetic.filter will register it with Assetic, the alias attribute is required and is the name which you will use to reference the filter from Twig. You can now use your filter from Twig:

You can use Dependency Injection to configure any object dependencies and parameters needed by your filter from the service config, there is more on this in my posts Symfony2: Dependency Injection Types and Symfony2: Injecting Dependencies Step by Step. The basic service config loader in my post Symfony2: Controller as Service just uses the parameters in your XML config file, it is possible though to open up these parameters to be set in an app’s config file, I will look at how to do this in a forthcoming post.