Dependency Injection
Autowiring
No configuration needed. Just type-hint your constructor parameters and the container can guess which dependencies to inject.
class Bar {}
class Foo {
public $bar;
public function __construct(Bar $bar, $id = null, $alias = null) {
$this->bar = $bar;
}
}
$container = new Container;
$foo = $container->get(Foo::class);
In example above, a new Bar
instance is created automatically each time Foo
is created. This mechanism rely on Reflection
to resolve objects dependencies. This is the default behavior of Peak Di.
Autowiring will try to create the object instance if no stored instance or matching definition found.
You can get a stored class instance by using get()
. If no instance can be found, it will check definitions and finally use autowiring in last resort.
Under the hood, the flow of get()
is:
- Check for stored instance that match class or interface
- Check for definition
- Try to resolve class with autowiring
- Throw exception
You can disable the autowiring to prevent step 3
and let the container throw an exception if no definition match the requested object.
$container->disableAutowiring();
Limitation of autowiring
Autowiring cannot always resolve dependencies like interfaces without help.
Consider this example:
interface Widget {}
class Toolbar implements Widget {}
class WidgetDecorator
{
public function __construct(Widget $myWidget) { ... }
}
$widgetDecorator = $container->get(WidgetDecorator::class);
Trying to resolve WidgetDecorator
will throw an Exception
because Widget
is an interface. There is 2 way to resolve this:
- The first way is to create a
Toolbar
instance and store it in your container before you try to resolveWidgetDecorator
:$toolbar = new Toolbar(); $container->set($toolbar); $widgetDecorator = $container->get(WidgetDecorator::class); // $toolbar instance will be used to create $widgetDecorator
- The second way is to tell the container which class should be used when encountering
Widget
interface dependency:$container->bind(Widget::class, Toolbar::class); $widgetDecorator = $container->get(WidgetDecorator::class);
The 2 solutions above achieve the same result but there are subtilities that are good to know. Learn more about definitions here.