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:

<?php

namespace LimeThinking\SpringBundle\Controller;

class StaticController
{


    protected $response;
    protected $request;


    public function indexAction()
    {
        //do stuff to create response
        return $this->response;
    }


}

The XML configuration like this:

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        
        <service id="lime_thinking_spring.response" 
                 class="Symfony\Component\HttpFoundation\Response"/>      
        <service id="lime_thinking_spring.response" 
                 class="Symfony\Component\HttpFoundation\Request"/> 

        <service id="lime_thinking_spring.static" 
                 class="LimeThinking\SpringBundle\Controller\StaticController">
            <property name="request"  type="service" id="lime_thinking_spring.response" />
            <property name="response" type="service" id="lime_thinking_spring.request" />
        </service>        
        
    </services>

</container>

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.