Skip to content
This repository was archived by the owner on Jan 16, 2019. It is now read-only.

List bindings

mikey179 edited this page Mar 4, 2012 · 8 revisions

List bindings

List bindings are a way to inject a list of values (aka an PHP array) into a class. The great thing about list bindings is that the elements of the list can be created using dependency injection as well, and that adding values to the list can be spread over several different binding modules. Suppose we have an interface like this:

interface Plugin
{
    function getName()
    function getAuthor()
    function getVersion()
    function getDependencies()
}

This interface has to be implemented by every plugin. Let's assume we have the following two plugin definitions:

class SecurityPlugin implements Plugin
{
   // Implementation
}
class AnotherCoolPlugin implements Plugin
{
   // Implementation
}
```

We have two plugins that should be managed by our application which uses the PluginManager for this:

```php
class PluginManager
{
    private $plugins;

    /**
     * @Inject
     * @List(example\Plugin.class)
     */
    public __construct($plugins)
    {
        $this->plugins = $plugins;
    }

    // Methods for managing plugins
}
```
The PluginManager only knows about the Plugin interface, and never about concrete Plugin implementations. We can now use list bindings to tell the IoC container how to construct the list:

```php
$binder->bindList('example\Plugin')
       ->withValue(new SecurityPlugin())
       ->withValueFromProvider('example\\CoolPluginProvider'); // provides AnotherCoolPlugin
```

Stubbles IoC will now take care of creating the plugin list and injecting it into the PluginManager. Additionally you don't have to create the concrete values in this place, but defer their creation to Stubbles IoC as well. In this example both the CoolPluginProvider and AnotherCoolPlugin are subject to dependency injection and also created by the Stubbles IoC container.

It is also possible to separate the adding of values to the list over different binding modules:

```php
class BindingModuleOne extends BaseObject implements BindingModule
{
    /**
     * configure the binder
     *
     * @param  Binder  $binder
     */
    public function configure(Binder $binder)
    {
         $binder->bindList('example\Plugin')
                ->withValue(new SecurityPlugin());
    }
}

class BindingModuleTwo extends BaseObject implements BindingModule
{
    /**
     * configure the binder
     *
     * @param  Binder  $binder
     */
    public function configure(Binder $binder)
    {
         $binder->bindList('example\Plugin')
                ->withValueFromProvider('example\\CoolPluginProvider');
    }
}
```

If both binding modules are used to configure the same binder the result will be a list which contains both the SecurityPlugin and the AnotherCoolPlugin. The reason is that both list bindings use the same name. If they would have used different names it would have resulted in different lists.

## Typed lists

All examples from above refer on how to created typed lists. A typed list means that each entry within the list is of the same type. This is also enforced by Stubbles IoC. If a value gets added which is not of the required type a `net\stubbles\ioc\binding\BindingException` will be thrown when the list is created.

The type of the list is defined with the value of the `@List` annotation. In the PluginManager above you can see such a definition. The type is also used to identify the list when you add values to it, even though only the type name is used here without the _.class_ addition.

## Untyped lists

List bindings can also be untyped. To create an untyped list, simply use a string name as value for the `@List` annotation:

```php
class Configuration
{
    private $config;

    /**
     * @Inject
     * @List('config')
     */
    public __construct($config)
    {
        $this->config = $config;
    }

    // more methods
}

$binder->bindList('config')
       ->withValue('foo')
       ->withValueFromProvider('example\\ConfigValueProvider'); // provides another config value
```

## Named bindings and list bindings

It is not possible to annotate list bindings with the `@Named` annotation. As lists already are identified with their own names it is not required to use `@Named` for lists.
Clone this wiki locally