Simple Dependency Injection Library
, (*1)
, (*2)
This is my simple dependency injection library in PHP, (*3)
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., (*4)
Autowiring:
Assume you have a class:, (*5)
<?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, (*6)
<?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, (*7)
<?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., (*8)
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., (*9)
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:, (*10)
<?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:, (*11)
<?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, (*12)
<?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., (*13)
<?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, (*14)
<?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:, (*15)
<?php
namespace Unused;
interface BaseInterface
{
public function setFirstName($firstName);
public function setMiddleName($middleName);
public function setLastName($lastName);
}
And, concrete class which implements Unused\BaseInterface, (*16)
<?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), (*17)
<?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., (*18)
$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:, (*19)
<?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), (*20)
<?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:, (*21)
vendor/bin/phpunit
If you need more verbose:, (*22)
vendor/bin/phpunit --verbose