gandung / dependency-injection
A dependency injection container
Requires
- php: >=5.6.0 || >=7.1.0
- psr/container: ^1.0
Requires (Dev)
- phpunit/phpunit: ~4.0
- satooshi/php-coveralls: dev-master
- squizlabs/php_codesniffer: ^2.7.0
This package is auto-updated.
Last update: 2024-10-19 18:20:30 UTC
README
This is my simple dependency injection library in PHP
Features:
- Can resolve class dependency that placed only on constructor (autowiring)
- Binding concrete dependency into unresolved abstract, either closure or class name.
- Can do shared binding concrete dependency into unresolved abstract, either closure or class name.
- Can resolve concrete implementation on typehinted interface on constructor method.
- Can resolve concrete implementation which bound on interface directly.
- Registering service under an alias.
Setter injection and method injection not yet implemented. Feel free to look, or clone it for your own needs.
Autowiring:
Assume you have a class:
<?php namespace Unused; class Foo { /** * @var \SplPriorityQueue */ private $heap; public function __construct(\SplPriorityQueue $heap) { $this->heap = $heap; } }
And you have a class that depends on class Unused\Foo, however class Unused\Foo depends on class \SplPriorityQueue
<?php namespace Unused; class Bar { /** * @var Foo */ private $foo; public function __construct(Foo $foo) { $this->foo = $foo; } }
You can resolve an instance of class Bar without resolving Bar and \SplPriorityQueue manually
<?php use Unused\Bar; $container = new Container(); $bar = $container->make(Bar::class);
Binding concrete dependency into unresolved abstract (only class name)
<?php use Unused\Bar; use Unused\Foo; $container = new Container(); $container->bind(Bar::class, Foo::class); $bar = $container->make(Bar::class);
Now, $bar is an instance of Bar::class.
Binding concrete dependency into unresolved abstract (with closure)
<?php use Unused\Bar; use Unused\Foo; $container = new Container(); $container->bind(Bar::class, function($container) { return $container->make(Foo::class); }); $bar = $container->make(Bar::class);
Now, $bar is an instance of Bar::class too.
Shared binding concrete dependency into unresolved abstract (only class name)
<?php use Unused\Base; use Unused\BaseInterface; $container = new Container(); $container->singleton(BaseInterface::class, Base::class); $base = $container->make(BaseInterface::class);
Shared binding concrete dependency into unresolved abstract (with closure)
<?php use Unused\Base; use Unused\BaseInterface; $container = new Container(); $container->singleton(BaseInterface::class, function($container) { return $container->make(Base::class); }); $base = $container->make(BaseInterface::class);
Binding typehinted interface into unresolved abstract (class based and with closure)
Assume you have an BaseInterface interface:
<?php namespace Unused; interface BaseInterface { public function setFirstName($firstName); public function setMiddleName($middleName); public function setLastName($lastName); }
And a class which implements BaseInterface interface under the same namespace:
<?php namespace Unused; class Base implements BaseInterface { /** * @var string */ private $firstName; /** * @var string */ private $middleName; /** * @var string */ private $lastName; public function setFirstName($firstName) { $this->firstName = $firstName; } public function setMiddleName($middleName) { $this->middleName = $middleName; } public function setLastName($lastName) { $this->lastName = $lastName; } }
And a class which have typehinted interface in it's constructor
<?php namespace Unused; class Foo { /** * @var BaseInterface */ private $base; public function __construct(BaseInterface $base) { $this->base = $base; } }
You can resolve class Foo with binding class Base into BaseInterface first.
<?php use Unused\BaseInterface; use Unused\Base; use Unused\Foo; $container = new Container(); $container->bind(BaseInterface::class, Base::class); $foo = $container->make(Foo::class);
Or, you and bind concrete implementation of BaseInterface with closure
<?php use Unused\BaseInterface; use Unused\Base; use Unused\Foo; $container = new Container(); $container->bind(BaseInterface::class, function($container) { return $container->make(Base::class); }); $foo = $container->make(Foo::class);
Resolve concrete implementation which bound on interface directly
Assume you have an interface:
<?php namespace Unused; interface BaseInterface { public function setFirstName($firstName); public function setMiddleName($middleName); public function setLastName($lastName); }
And, concrete class which implements Unused\BaseInterface
<?php namespace Unused; class Base implements BaseInterface { /** * @var string */ private $firstName; /** * @var string */ private $middleName; /** * @var string */ private $lastName; /** * @implements */ public function setFirstName($firstName) { $this->firstName = $firstName; } /** * @implements */ public function setMiddleName($middleName) { $this->middleName = $middleName; } /** * @implements */ public function setLastName($lastName) { $this->lastName = $lastName; } }
Bind concrete implementation on that interface first (use either direct class name or closure)
<?php use Unused\Base; use Unused\BaseInterface; $container = new Container(); // with direct class name. $container->bind(BaseInterface::class, Base::class); // or, use a closure. $container->bind(BaseInterface::class, function($container) { return $container->make(Base::class); });
Then, get it directly.
$base = $container->make(BaseInterface::class);
Registering service under an alias (PSR-11 compatible.)
Assume you have a service which require a concrete implementation of a BaseInterface:
<?php namespace Unused; class FooService { /** * @var BaseInterface */ private $base; public function __construct(BaseInterface $base) { $this->base = $base; } }
Just bind a concrete implementation of BaseInterface, then register FooService under an alias (e.g: foo.service)
<?php $container = new Container(); $container->bind(BaseInterface::class, function($container) { return $container->make(Base::class); }); $container->register('foo.service', FooService::class); $service = $container->get('foo.service');
Unit Testing
If you want to run unit tests:
vendor/bin/phpunit
If you need more verbose:
vendor/bin/phpunit --verbose