Inversion of Control: Working with singletons
In the above example, multiple calls to $injector->getInstance('Car'); will return different objects. In most cases, this is probably what you want, as the IoC framework behaves like the new operator. If you want to create only one instance of the BMW class, you can easily convert the BMW class to a singleton.
<?php $binder = new stubBinder(); $binder->bind('Car')->to('BMW')->in(stubBindingScopes::$SINGLETON); // other bindings $injector = $binder->getInjector(); $bmw1 = $injector->getInstance('Car'); $bmw2 = $injector->getInstance('Car'); if ($bmw1 === $bmw2) { echo "Same object.\n"; } ?>
You may specify a scope for each binding using the in() method. In the above example, the $SINGLETON scope has been used. This makes sure, that the instance is created only once and subsequent calls to getInstance() will return the same instance.
It is also possible to create your own scope. You only need to write a new class that implementes the stubBindingScope interface. For instance, this would allow you to create a scope so that a class is only instantiated once per session.
Another way to treat a class as a singleton is using the @Singleton annotation, which is used to annotate the class. The following example makes sure, that the application uses only one instance of the class Schst:
<?php /** * @Singleton */ class Schst implements Person { public function sayHello() { echo "My name is Stephan\n"; } } ?>
The following code will now create two instances of the class BMW, but both should have a reference to the same Schst instance:
<?php $binder = new stubBinder(); $binder->bind('Car')->to('BMW'); // other bindings $injector = $binder->getInjector(); $bmw1 = $injector->getInstance('Car'); $bmw2 = $injector->getInstance('Car'); var_dump($bmw1); var_dump($bmw1); ?>
If you run the code snippet, you get the following output:
object(BMW)#34 (3) {
["driver:protected"]=>
object(Schst)#50 (0) {
}
["engine:protected"]=>
object(TwoLitresEngine)#38 (0) {
}
["tire:protected"]=>
object(Goodyear)#41 (0) {
}
}
object(BMW)#30 (3) {
["driver:protected"]=>
object(Schst)#50 (0) {
}
["engine:protected"]=>
object(TwoLitresEngine)#44 (0) {
}
["tire:protected"]=>
object(Goodyear)#39 (0) {
}
}
As you can see, the two BMW instances have different object handles (#30 and #34), but the $driver properties point to the same Schst instance (object handle #50).
Implementing the singleton pattern never has been this easy.
