Skip to content
Loïc Frering edited this page Oct 8, 2010 · 1 revision

Annotation Loader

Introduction

While declaring services by configuration files is supported out of the box by Symfony DI Container, losolib comes with an additional loader: AnnotationLoader. This loader allows to declare services in a more intuitive manner by directly annotating classes that will be managed by the container and configure them thanks to other annotations. Configuration of the services and their code are now located in the same place!

@Service

The @Service annotation declare the class as managed by the container. You can specify the id of the service, if it is a shared service or not and a list of tags applied to the service.

Usage:

@Service
@Service("service.id")
@Service(name="service.id", shared=false, tags={{name=tag1}, {name=tag2}})

If you do not explicitly set the service id, this one will be determined from the class name. All the following three classes would have myService as id:

  • MyService a simple non namespaced class.
  • Application_Service_MyService an old fashioned PEAR style namespaced class.
  • ApplicationServiceMyService a PHP 5.3 namespaced class.

@Inject

The @Inject annotation declare a service's dependency that have to be injected by the container when the service is retrieved. You can declare dependencies upon the constructor, properties or setter methods.

Usage:

@Inject
@Inject("service.id")

Let's see the @Inject behavior in each of his emplacement possibilities.

Constructor

Annotating the constructor with @Inject annotation will declare each arguments of the method as a dependency whose id is the argument id. For now you can't explicitly define the individual service id that needs to be injected as argument.

Example:

/** @Service */
class MyService
{
    protected $fooService;
    protected $barService;

    /** @Inject */
    public function __construct($fooService, $barService)
    {
        $this->fooService = $fooService;
        $this->barService = $barService;
    }
}

Will declare in YAML:

services:
    myService:
        class: MyService
        arguments: [@fooService, @barService]

Methods

On a method, the @Inject annotation will declare a call method on the service with another service reference as parameter. The same way than previously, you can explicitly specify the id of the service you want to inject, otherwise it will be determined thanks to the method name.

Example:

/** @Service */
class MyService
{
    protected $fooService;
    protected $barService;

    /** @Inject */
    public function setFooService($fooService)
    {
        $this->fooService = $fooService;
        return $this;
    }

    /** @Inject("bar.service") */
    public function setBarService($barService)
    {
        $this->barService = $barService;
        return $this;
    }
}

Will declare in YAML:

services:
    myService:
        class: MyService
        methodCalls:
            setFooService: [@fooService]
            setBarService: [@bar.service]

Properties

Finally, on a property, the @Inject annotation will also declare a method call on a setter whose method name is calculated among the property name and with the service reference you want to inject as parameter. The service reference id can be explicitly specified, the property name will be used otherwise.

Example:

/** @Service */
class MyService
{
    /** @Inject */
    protected $fooService;

    /** @Inject("bar.service") */
    protected $barService;

    public function setFooService($fooService)
    {
        $this->fooService = $fooService;
        return $this;
    }

    public function setBarService($barService)
    {
        $this->barService = $barService;
        return $this;
    }
}

Will declare in YAML:

services:
    myService:
        class: MyService
        methodCalls:
            setFooService: [@fooService]
            setBarService: [@bar.service]

@Value

The @Value annotation allows to inject parameters defined in the Container. You can refer to the Symfony Dependency Injection Component documentation to see how you can define parameters in the different configuration file formats.

Example in YAML:

parameters:
    foo: fooValue
    bar.array:
        - true
        - false
        - 786
        - value

The same way that an @Service annotation, @Value can be used either on a class property or on a method. The parameter name determination strategies remains the same that with the @Service annotation: explicitly defined or determined from the property or method name. Here are some examples with the above YAML loaded in the Container.

Methods

/** @Service */
class MyService
{
    protected $foo;

    protected $bar;

    /** @Value */
    public function setFoo($foo)
    {
        $this->foo = $foo;
        return $this;
    }

    /** @Value("bar.array") */
    public function setBar($bar)
    {
        $this->bar = $bar;
        return $this;
    }
}

Properties

/** @Service */
class MyService
{
    /** @Value */
    protected $foo;

    /** @Value("bar.array") */
    protected $bar;

    public function setFoo($foo)
    {
        $this->foo = $foo;
        return $this;
    }

    public function setBar($bar)
    {
        $this->bar = $bar;
        return $this;
    }
}