-
Notifications
You must be signed in to change notification settings - Fork 0
Docs IOC NamedInstances
For the next example, you have to modify the used classes a little bit:
- Add a new class Mikey which implements the Person interface
- Add a new property $coDriver and the matching setter-method to the BMW class
#php <?php class BMW implements Car { protected $driver; protected $coDriver; protected $engine; protected $tire; // existing methods left out... /** ***@Inject ***/ public function setCoDriver(Person $coDriver) { $this->coDriver = $coDriver; } } class Mikey implements Person { public function sayHello() { echo "My name is Frank\n"; } } // existing classes left out ?>
If you now create an instance of BMW, you will get the following object structure:
object(BMW)#35 (4) { ["driver:protected"]=> object(Schst)#51 (0) { } ["coDriver:protected"]=> object(Schst)#51 (0) { } ["engine:protected"]=> object(TwoLitresEngine)#39 (0) { } ["tire:protected"]=> object(Goodyear)#42 (0) { } }
The properties $driver and $coDriver both contain references to the instance of Schst as both setter methods require an instance that implements the Person interface. In real-life, you would probably be able to inject a different co-driver, but until now, an interface could only be bound to one implementation. This can be changed using the @Named annotation.
Again, you need to modify the BMW class a little bit:
#php <?php class BMW implements Car { protected $driver; protected $coDriver; protected $engine; protected $tire; // existing methods left out... /** ***@Inject ***@Named('Co-Driver') ***/ public function setCoDriver(Person $coDriver) { $this->coDriver = $coDriver; } } ?>
By adding the @Named('Co-Driver') annotation, you gave Stubbles the possibility to distinguish the Person instance passed to setCoDriver from all other Person instances. You may now specify a separate binding for this instance:
#php <?php $binder->bind('Person')->to('Schst'); $binder->bind('Person')->named('Co-Driver')->to('Mikey'); // other bindings $injector = $binder->getInjector(); $bmw = $injector->getInstance('Car'); var_dump($bmw); ?>
Now, the $injector will return the following object structure:
object(BMW)#34 (4) { ["driver:protected"]=> object(Schst)#50 (0) { } ["coDriver:protected"]=> object(Mikey)#57 (0) { } ["engine:protected"]=> object(TwoLitresEngine)#38 (0) { } ["tire:protected"]=> object(Goodyear)#41 (0) { } }
As desired, Stubbles created an instance of the new class Mikey and injected it using the setCoDriver() method. You may use as many named bindings for one type as you like and combine it with all other features like scoping.
Named instances work on setter and constructor injection, and can even be restricted to a certain parameter if the method expects more then one parameter:
#php <?php class BMW implements Car { protected $driver; protected $coDriver; protected $engine; protected $tire; // existing methods left out... /** ***@Inject ***@Named{coDriver}('Co-Driver') ***/ public function setDrivers(Person $driver, Person $coDriver) { $this->driver = $driver; $this->coDriver = $coDriver; } } ?>
Here, the @Named annotation is restricted to the $coDriver parameter, but $driver is not restricted. The @Named annotation can be used in several ways:
- per method, binding all parameters to this name
- per parameter, binding only the parameter to this name