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.

When Dependency Injection goes Wrong

Introduction

Dependency Injection (DI) is finally starting to take off in a big way in PHP. Whilst there have been projects such as Phemto for a while now it has taken it being made a fundamental part of, the now in beta, Symfony2 to really make its mark. Whilst you can still avoid it when writing Symfony2 application it is used throughout the framework components themselves and it provides an excellent Dependency Injection Container (DIC) to make using it application easy. In this post I am going to look at the advantages of using Dependency Injection and how to avoid missing out on these advantages whilst appearing to be using it.

Dependency Injection Advantages

Easier Testing

If you have a dependency in a class then it makes true Unit Testing difficult as you will be testing the functionality of the dependency when you actually want to test the functionality of the code using it.

In the following example we are using a Logger object to log a message:

In a unit test for this class the real logger will be instantiated and a log actually made. This is unwanted behaviour for several reasons. Firstly we are not testing the Logger but any bugs in it will break our test. A real log will be created, in this case in a file, interactions with things such as the file system, database etc. will slow tests making you less likely to run them. Checking whether the log method is called requires checking the actual log.

Much better is to inject the Logger object into the class:

In the test we can now inject a mock object instead. Any bugs in the real Logger will not break the test (they will hopefully though break the test for the FileLogger), the interaction with the file system will not take place and we can just ask the mock if its Log method was called. You can read more about using mock objects in PHPUnit tests in the PHPUnit manual.

Loosely coupled code

If you have a dependency instantiated directly in a class then you are tied to that implementation of the dependency. This means that if you want to swap to a different implementation you need to change the code. Perhaps creating a whole new version which uses a different dependency or introducing switch statements that check configuration to decide which to use, which can quickly lead to very messy code:

Using Dependency Injection you just pass in the object you want to use and use it, the client code does not need to be involved in the decision of which to use at all.

Seems simple enough, what’s all the fuss?

It is simple, it really is just passing dependencies in via the constructor or a method, so where does it go wrong? Well the first mistake would be to just shift the dependencies up to the next level of code. So the code that uses the object has to deal with its dependencies.

This has just shifted the problem elsewhere, so how do we deal with this? Well the problem is that we have not gone far enough, this class also needs its dependencies injecting. This will mean that it looks like this:

If we keep doing this we will end up at the top, at what ever the point of entry is. This is not a bad thing as we have now effectively separated the creation of our objects from their use. This mean that the choice of how to wire together the objects is done as they are executed but before hand. This means that we can now reassemble them for different applications that have different requirements without needing to touch the code itself.

Of course wiring up the objects now becomes a fairly big job which is where Dependency Injection Containers come in to play as they can ease the process of doing this. They are not however Dependency Injection but rather tools to help with its implementation. They are a fantastic tool when done right but they do cloud the issue rather and make DI seem more complicated than it is.

How to avoid the benefits of Dependency Injection

Poor Type Hinting

Using dependency injection goes hand in hand with using type hinting in my opinion. If you do not use type hinting at all on the injection points then you either need to check the type of the injected dependency before using it or risk running into unexpected errors. If the wrong dependency is passed in then methods called on it may not exist or worse a method with that name exists but calling has unfortunate results.

So type hinting will ensure that the error is thrown at the expected place, when the incorrect type of dependency is injected. Type hinting in this way is easy with constructor and setter injection (see my post Symfony2: Dependency Injection Types for details of these types of DI), with property injection you cannot do this and must rely on other checks rather than the simplicity of type hinting.

So if we just start using type hints then all is good? Well not necessarily, its still possible to lose the benefit of loosely coupled code by enforcing that a certain class has to be passed in:

If you type hint the name of a class then that needs to be passed in so changing to a different dependency is only possible by subclassing it. Much better is to type hint using interfaces, this way you can be sure that the dependencies has all the correct methods without being tied to any particular implementation:

Making the Container a Dependency

The advantages of DI are lost if you do not avoid making a DIC itself a dependency in your code. So how and why would you do that. How, is by requesting objects from the container directly. Why, is usually because of failing to push all your dependencies all the way out of the code. Often learning about DI with reference to a container is part of the problem as it makes you think DI is about getting things from a DIC when it is not at all. Doing this makes the container into a Service Locater and not a DIC at all. Especially if you make it a Singleton and request from it statically:

Not quite as bad but still problematic is injecting the container itself:

So why is this bad? well to start with you now need to use the container in your tests or a mock container if you are injecting it. This leads to additional unnecessary code making tests harder to write in the first place and maintain, and let’s face it hard to maintain tests don’t get maintained.

This is not the only issue though and it is wrong to think of DI as only being about improving testability. If we inject the container and ask it for a particular service in multiple locations in our code then we are no longer as loosely coupled as we should be. Now all code requesting that service is tied to having one implementation of it.

Being Dependant on the Container

You can avoid any direct use of the DIC in your class and still fall into the trap of being dependant on it. This is by using one of the less common forms of DI, property injection. With property injection you inject the dependency by just setting a property of the object to it. It seems attractive at first, no need to write setter methods which often do nothing but set the property anyway. The whole point of setters is to avoid having public properties though and this is particularly important if you do not want the dependencies to be changed by any bit of code but set at the time of creation and left alone.

Some DICs though, such as Symfony2’s allow you to avoid this problem by making the property protected or private. they do this by then using reflection when creating the objects allowing the property to be set despite not being public. So great, best of both worlds then? Unfortunately not, you have here introduced a more subtle dependency on the DIC, the object can no longer be directly instantiated and its dependencies set without using reflection. So it is now difficult to test as we cannot just create it and set its dependencies without using the container or reflection directly.

It is also now difficult to make use of this class in a small application where you may not need a heavy weight DIC if it used setter injection rather than property injection it could be created easily but now we need to use the DIC to create it. You are also tied to a particular DIC since any good one will support constructor and setter injection but not all will support property injection to non-public properties.

Tying dependency choice to class definition

It is easy to tie the choice of dependency to the class definition using interface injection: some DICs let you specify injecting dependencies via interfaces, this means that any class that has that interface will have the dependency injected into it. It is effectively a form of setter injection as the classes implementing the interface will have to have the setter method. The following example shows interface injection as done in an early version of Symfony2, it has now been removed because of the issues it raises:

The problem is that you are not specifying the dependencies a class should have independently of it any more but in the class definition by implementing the interface. Whilst you may have separated the specifying the dependency to inject into the interface it is now injected to all classes implementing that interface which has introduced a tight coupling between all classes with that interface. If a particular application’s wiring does not require a class to have that dependency then the interface needs to be removed from the class to avoid it receiving it which means making changes to the class itself which we should not have to do with DI.

Another way to tie the DI configuration to the class definition would be to use annotations in the comments to decide what dependency to inject. This is a bad way of doing the configuration as it now needs a different set of comments for any change in configuration.

Conclusion

Dependency Injection is a must if you want to create easily testable, loosely coupled code. However it is important to ensure that you avoid the above if you actual want to get these benefits. If you do not then you are still creating code that is hard to test and/or tightly coupled with the additional complexity of a DIC thrown in.

Symfony2: Using CoffeeScript with Assetic

CoffeeScript is a scripting language which is compiled to run as JavaScript. It let you write simpler code with improvements in much of the JavaScript syntax, mainly inspired by Ruby and Python. It is served up to the end user as JavaScript so it requires nothing on the end users part.

If you are using Symfony2‘s asset manager Assetic then this can deal with the compilation of your CoffeeScript files into JavaScript for you. This offers the advantages of caching the end result so the compilation does not run every time whilst also automatically recompiling when ever the script changes during development.

Installation

Whilst Assetic’s CoffeeScriptFilter will do the work for you it does not do the actual compilation, you will still need to install CoffeeScript itself along with node.js on which it runs. Details of how to do this for various platforms can be found on the CoffeeScript GitHub page. For me, running on Fedora 13, I downloaded the latest node.js tar and built it from source using:

I then installed NPM the Node Package Manager with the following

I had to su to root rather than sudo as the script run needed to run as root. I could then install coffee using:

Configuration

Then main configuration in the app’s config.yml is just the paths to coffee and node. These default respectively to /usr/bin/coffee and /usr/bin/node. This was not where they had been installed for me so I needed the following config:

Use

It is easy to configure what assets and filters Assetic should output from within Twig templates (Twig is Symfony2’s default templating engine). I placed a test CoffeeScript file in my bundle and the following in my base.html.twig file in order to serve it up compiled into JavaScript:

This is all was needed and the file was served up as regular JavaScript. You can combine multiple CoffeeScript files into a single output file by just listing them as such:

Both the files will now be served up as a single file compiled into regular JavaScript.

Combining JavaScript and CoffeeScript files

One of the great advantages of using Assetic is reducing the number of asset files to lower HTTP requests. In order to make full use of this it would be good to combine all your JavaScript and CoffeeScript files together since they will ultimately all be served as JavaScript. Unfortunately just adding the JavaScript files to the files to be combined as above will not work as the regular JavaScript files will not survive the CoffeeScript compilation.

The good news though is that Kris Wallsmith has added a way round this to the latest version of Assetic, so that as of the beta 2 version of Symfony2 you will be able to configure the CoffeeScriptFilter to be run against any file with a specified extension. So changing my configuration to be the following:

means that he filter is automatically applied to my files as they have the .coffee extension.
So I can now remove specifying the filter in the Twig template and list any regular JavaScript files which will now be combined into the output file without having been run through coffee:

You could of course then run this through the YUI Compressor using Assetic to reduce the size of the output file with the following:

Please see my post Symfony2: Using Assetic from Twig for more details, its about using the YUI Compressor for CSS but there are only a few minor differences.

Symfony2: Using Assetic from Twig

After my earlier post digging in to how Assetic (Symfony2‘s asset manager) works, I am now going to look at how you should actually use it from Symfony2’s templating engine Twig. Kris Wallsmith the developer of Assetic pointed me in the right direction in the comments on that post. He has now added some official documentation on the Symfony site. This post covers much the same ground, but I had written the bulk of it yesterday before they were added so I am going to post it anyway.

It turns out it’s much simpler than I had made it, putting the following into my base.html.twig file and updating the YUI compressor location in config.yml just achieved the mapping for my main CSS file:

In my defence with regards to overcomplicating things I could just not get this working at all when I last tried with PR7 of Symfony2 which lead to my getting sidetracked.

Basic Usage

So let’s have a look in more detail at what is going on with the above. The only thing that you need to include in the %stylesheets% config is a file to make up the served file:

This will just include the single file as is, this does not provide much advantage over serving it directly apart from allowing you to keep the files out of the public web folder.

To combine multiple files they can just be added to the %stylesheets% tag, there is no separator needed between them:

Both files will now be served up as a single file allowing them to be maintained separately but served as single file to reduce HTTP requests. Further gains can be made by compressing the files, one of the built in Assetic filters is the YUI Compressor, adding the following will compress the combined file:

For more on the installation and configuration of the YUI Compressor for use with Assetic read http://sftuts.com/using-assetic-in-symfony2-for-css-compression

You can specify multiple filters by listing the common separated in the filter attribute e.g. filter=”less,yui_css”. You can see a list of the filters currently included in the GitHub documentation and read more about using the LESS filter at Dustin Dobervich’s Blog.

By default the file will be served up with a URL such as /css/4586f12.css you can specify it though by adding an output attribute:

It will now be served up from /css/main.css

Debug mode

Working in the dev environment it may not be working as you expect from the description above. This is because in debug mode each file is still served separately. You can explicitly set the debug mode in config.yml, by default it is set to the %kernel.debug% global parameter, meaning that it is on in the dev environment. You can also control it from within Twig with the debug attribute:

Note, no quotation marks should be placed around the value.

In debug mode the files are served up separately as /css/mainoverall1.css and /css/mainsocial2.css making it easier to work with them. As it stands though the yui_css filter is still applied in debug mode. This can be changed by placing a question mark in front of it:

Filters specified in that fashion are not applied in debug mode, it needs to explicitly specified like this because turning off filters such as LESS or SASS does not make sense even in debug mode.

Production

By default Assetic is not routed to in production. For production it is better to save the files directly to the location the browser is expecting to find them as static files. Fortunately this can be done easily enough using the command line.

This will speed up the serving of the files by allowing Apache to deal with the caching headers and PHP to never be touched in serving them in production.

Symfony2: Injecting Dependencies Step by Step

In this post I will go through removing directly created dependencies from a Symfony2 controller and instead injecting them using The Dependency Injection Container (DIC).

At the end of my last post I had an Asset Controller which looked like this:

In the post I am going to go through the steps I went through to change it to this:

The second is much cleaner, much of the leg work of setting up the Asset and Filter managers has been removed. Also all the direct instantiation of objects has been removed, this means that testing will be much easier. So where has the missing code gone? It has been replaced by using the Symfony2 Dependency Injection Container to do the work for us. I am going to go through the steps I took to start removing the dependencies.

Note: this asset controller is not actually necessary as Assetic can be configured directly from Twig, see Kris Wallsmith’s comment on my previous post. My follow up post Symfony2: Using Assetic from Twig has more on this. However what it actually does is not relevant to the content of this post, it is more an exercise in how to inject dependencies.

To start with the controller needs to be called as a service and an XML config file created for the bundle. Please read my post Symfony2: Controller as Service for more details. We can start with the low hanging fruit, the controller’s dependencies that have no dependencies themselves. Instead of creating these in the controller they can be passed in via constructor injection. The controller now looks like this:

and the XML config file like this:

Each of the dependencies we are passing in is defined as a service and the id associated with used to pass them as constructor arguments to the controller service. Also of note is that you can parametrise the settings themselves, I have pulled out the name of the class being used for formula loading in order to make this easier to change.

For the next step we can remove the dependencies which have their own simple constructor parameters.

One new introduction here is the use of some of the global parameters: kernel.rootdir and kernel.cachedir within the parameters. These are fairly self explanatory and are an excellent way to avoid having absolute paths in the service configuration. A list of the available global parameters appears in this page of the Symfony2 documentation.

We’re starting to get there now, unfortunately our constructor argument list is growing, fortunately the next step will help with this. Quite a few of the remaining lines of code are calling setter methods on the dependencies, usually with another of our dependencies being passed in. We can use the Symfony2 Dependency Injection Container’s support for Setter Injection to deal with these. The controller can now be changed to this:

The XML file now instructs the DIC to call the methods and which service to pass to them. The YUI Compressor is passed to the filter manager, which is in turn, along with the asset manager, passed to the asset factory. This means that the compressor, filter manager and asset manager can all be removed from the PHP code altogether as the asset factory is injected already set up with them. In a similar way we can now go further and just pass in the AsseticController set up with its dependencies already and eliminate these from the code in the final step.

The LazyAssetManager is passed to the AsseticController by the DIC but as we need to set the formula it still needs to be injected in to the controller as well. It is the same service that is injected into each so this presents to problems, by setting the formula in the LazyAssetManager passed in it is available in the AsseticController.

The code is now cleaner and whilst we have a fairly hefty config file it is now easy to change the configuration by just editing this file. For example to make additional filters available in the filter manager I do not need to touch the PHP code at all, to also make a JavaScript YUICompressor available the config needs changing to this:

Hopefully this post helps with showing you Dependency Injection can be used to clean up code by separating the configuration or “wiring” of the object tree from the execution, as well as how to do this with the Symfony2 Dependency Injection Container.

Symfony2: Using Assetic for CSS and JavaScript Management

Edit: Please read the first the first comment from Kris Wallsmith, this explains that you do not need to write any PHP at all to make use of Assetic, it can be configured directly from Twig templates. My follow up post Symfony2: Using Assetic from Twig has more on this. Nevertheless the following should give you some idea of what is happening when you use it.

In this post I will look at Assetic, Symfony2‘s asset manager.

I am recreating the Lime Thinking website using Symfony2 as a learning exercise. As part of our in house LimePickle framework we manage CSS and JS files using PHP. Our current code allows us to make up the served files from several source files to reduce HTTP requests as well as applying transformation such as minimisation to them. We also modify the URLS they are served from to include version numbers so that the files can be set to be cached for a long time but with users still getting the latest versions.

I was keen that this functionality is not lost, if not improved upon, by using Symfony2, so seeing that it has a module for exactly this was reassuring. The documentation at this stage is still sparse, so I am worked from the documentation on the GitHub page. What follows is the stages I went through to arrive at a usable controller.

I wanted to get to a point where I can route from a file name to a config file which will specify the assets to return without needing to make any changes in PHP code, our preference at Lime Thinking would be to store this configuration as XML. I started by just hard coding in the files to serve with a mind to abstracting this to a config file once I progressed to a point where this would be sensible.

The start point is to use an AssetCollection and pass it an array of FileAsset object referencing the files we want to serve, along with an array of filters to apply, in this case a YUICompressor. We can then set the Response to be a dump of the AssetCollection, this will be a combination of the contents of the files which have had the YUI Compressor applied to them.

The next stage is to abstract from this direct creation and to use an AssetMenager and a FilterManager. In this simplistic example it does not gain us much but it does allow the assets and filters to be specified in one location and then references to them used so they only need to be changed in one place if they are used in multiple places. The manager also ensures that the same file is not included twice and the filters are only applied once.

After this we can progress to using an AssetFactory with our managers to create the asset. Again the advantage is not apparent in this simplistic example. However once we start to pass in the files and filters as variables rather than being hard coded it will reduce what we need to pass in to simple arrays.

We are now back to referencing our assets directly even if the AssetFactory has removed the repetition of the path. We can get these back though if we go back to setting them in the AssetManager and useing the @ syntax to reference them by name:

We can further abstract away from this by using the LazyAssetManager, this allows us to pass a formula which is just a nested array specifying the assets and references. Again in the examples the values are hard coded in but it should be easy to see how we could now just pass in this array to allow the controller to be used for serving multiple resources. This version does not use asset references but they can still be used as with the previous example.

As the asset files are not changing constantly and the actual combining and in particular compression are expensive operations the results can easily be cached. The following shows the caching taking place. No checking to see if the file exists is needed if we write them to the location they are served from with the filename the browser is looking for since Symfony2 routing will only be hit when the file does not exist. This is only useful for production though as the files will need deleting before the asset will be recreated.

This is where the built in AsseticController proves useful as it will deal with caching for us, it is a good compromise I think, as it caches the output but recreates it if the files change. This is excellent for development work where we want to keep up to date without clearing caches but without the slow load time of doing the compression for each loaded asset. For production you could still switch to using something like the previous example or better yet use call something like the above from Phing or Ant as part of the build process, so no one has to take the hit of first load.

We still need to do much of the work of above as we need to pass the LazyAssetManager to the AsseticController but it does do the caching work for us.

At this stage I decided I was ready to move away from hard coding in the formula and retrieve it from elsewhere. As where this is received from does not need to be fixed I decided to encapsulate this is an object which returns the formula. This means that the way the formula is stored is not fixed in the controller. In my case I am storing the formula in XML files and the FormulaLoader object converts these to the array. I have also moved to specifying a Resources folder rather then the CSS folder in particular so I can start using this for JavaScript as well. This change also meant abstracting the choice of MIME type to set.

You may have noticed that despite many of my previous posts being on Dependency Injection I have not used it at all here and just directly created any dependencies. In my next post I will go through how to use Dependency Injection to clean up this controller.

More information on Assetic including the various filters currently available, other caching methods and integration with Twig, which I have not covered at all, can be found at the documentation at GitHub. The one thing I did not find was a way to easily implement version numbers in the asset URLs, which can avoid the browser having to request the file at all with suitable cache settings, can anyone help with this?

Symfony2: Base Class for Common Dependencies

I have previously written about the different ways of injecting dependencies in Symfony2. In this post I will look at managing common dependencies in order to reduce code and config repetition. I will look at it using the same controller as before but this can be used for any service and not only controllers.

Simply put, common dependencies can be managed in a base class that is then extended. Setter and property injection lend themselves to this much more readily than constructor injection so I will concentrate on these. First up property injection, a simple base class would look like this:

The controller now looks like this:

And the XML config like this:

So the properties are now set for the parent class meaning that this can be reused for multiple controllers without having to rewrite the config for each service. Of note is that the base controller has the abstract attribute set to true preventing it from being requested from the service container. Also that the controller service has a parent attribute referring to the base controller, without this the dependencies would not be injected even though the PHP class extends this base class.

Whilst this reduces the need to repeat configuration for each subclass of the base class there is still the opportunity to change the dependencies for individual subclasses if required. If all the dependencies are different then simply leaving out the parent attribute will stop them being injected via the base class service config. If fewer than all are different then just the changes can be overridden in the service config. For example, to provide a different response object just to the static controller but not all the subclasses of the base controller then the following config could be used:

It is similar using setter injection. The base class looks like this:

The controller stays the same and the XML config like this:

Again the dependency can be overridden for the individual subclasses. Worth knowing is that the setter method will be called for the base controller and again replacing the dependency for the subclass rather the DIC deciding not to call it for the base class. Whilst this does not matter in the above example due to the simplistic nature of the setter it would in some cases, for example, if the setter added the passed dependencies to a collection. The following shows such a case, if the the base controller looks like this:

and the XML config like this:

This would lead to the $filters array containing both a FilterOne and a FilterTwo object. This is great if you just want to add additional filters to the subclasses. If you want to replace the filters passed to the subclass then removing the parent attribute from the service config will prevent the base class call to setFilter.

So managing common dependencies can now be done with much less repetition using these features of Symfony2 Dependency Injection configuration.

Symfony2: Dependency Injection Types – Update

In my previous post I discussed the various ways of injecting dependencies in Symfony2. Symfony2 is not yet in a stable condition and has only just reached the first beta release. As such changes are still being made on regular basis. Some of these changes are to the Dependency Injection Container and some of the information in the previous post is no longer correct.

Interface Injection

Interface injection has been removed from Symfony2 altogether so this is no longer a viable way of injecting dependencies. More information on why can be found by reading this thread from the developers mailing list.

Essentially the problem appears to be that when configuring interface injection it is to easy to override the dependencies passed to any class that implements that interface in third party code. Preventing this from happening altogether would be straight forward but would completely remove the ability to override the dependency passed in cases where doing so is a desirable extension point to a third party bundle. Resolving this issue would prove to be more complicated in the internals of the DIC than is worth it to provide this infrequently used way of injecting dependencies. Someone please correct me if I have missed the point here.

Property injection

A further type of dependency injection has been added which is property injection. This allows the setting of dependencies through an object’s properties. Going back to the class from the previous post the PHP will now look like this:

The XML configuration like this:

Note that the property does not need to be public for this to work. I assumed it would do but some experimentation shows that it works even if the property is protected or private. A quick dig about in the Symfony2 code shows that the dependency is set using reflection and ReflectionProperty::setAccessible is used to set private and protected properties.

This way of injecting dependencies has similar advantages and disadvantages to setter injection except for the usual differences between direct property access and using setter methods. Whether or not this seems like a good way to inject dependencies depends on where you stand on the property access getter/setter methods debate and that is not something I want to get into here. Worth noting though that the usual objections to property access are not as strong as usual as the property does not need to be made public to allow for property injection to work.