A PSR-11 compliant Dependency Injector component
With composer:
composer require omarphp/di
You can instantiate a class without a constructor parameter with zero configuration.
use Omar\DependencyInjection\Container;
class RockBand {}
$container = Container::create();
$band = $container->get(RockBand::class);
assert($band instanceof RockBand);
OmarDI can autowire parameter constructors.
use Omar\DependencyInjection\Container;
class Guitarist {}
class Drummer {}
class RockBand
{
public function __construct(Guitarist $guitarist, Drummer $drummer) {}
}
$container = Container::create();
$band = $container->get(RockBand::class);
assert($band instanceof RockBand);
You can bind implementations to abstract classes and interfaces with configuration.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
interface Guitarist {}
abstract class Drummer {}
class JimmyPage implements Guitarist {}
class JohnBonham extends Drummer {}
$config = Config::init()
->bind(Guitarist::class, JimmyPage::class)
->bind(Drummer::class, JohnBonham::class);
$container = Container::create($config);
$guitarist = $container->get(Guitarist::class);
$drummer = $container->get(Drummer::class);
assert($guitarist instanceof JimmyPage);
assert($drummer instanceof JohnBonham);
Autowiring can use the bound parameters.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
interface Guitarist {}
abstract class Drummer {}
class JimmyPage implements Guitarist {}
class JohnBonham extends Drummer {}
class RockBand
{
public function __construct(Guitarist $guitarist, Drummer $drummer) {}
}
$config = Config::init()
->bind(Guitarist::class, JimmyPage::class)
->bind(Drummer::class, JohnBonham::class);
$container = Container::create($config);
$band = $container->get(RockBand::class);
assert($band instanceof RockBand);
You can wire the constructor parameters by their name. That's how you can inject different implementations for the same interfaces.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
use Omar\DependencyInjection\Setup;
interface Guitarist {}
interface Drummer {}
class JimmyPage implements Guitarist {}
class George implements Guitarist {}
class JohnBonham implements Drummer {}
class Ringo implements Drummer {}
abstract class RockBand
{
public function __construct(Guitarist $guitarist, Drummer $drummer) {}
}
class LedZeppelin extends RockBand {}
class Beatles extends RockBand {}
$config = Config::init()
->setup(LedZeppelin::class, Config::params()
->wire('guitarist', JimmyPage::class)
->wire('drummer', JohnBonham::class)
)
->setup(Beatles::class, Config::params()
->wire('guitarist', George::class)
->wire('drummer', Ringo::class)
);
$container = Container::create($config);
$ledzep = $container->get(LedZeppelin::class);
assert($ledzep instanceof LedZeppelin);
$beatles = $container->get(Beatles::class);
assert($beatles instanceof Beatles);
Scalar values or object instances can be configured to constructor parameters by their name.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
use Omar\DependencyInjection\Setup;
class Guitarist
{
public function __construct(string $guitarType, int $bornInYear) {}
}
$config = Config::init()
->setup(Guitarist::class, Config::params()
->config('guitarType', 'Les Paul')
->config('bornInYear', 1944)
);
$container = Container::create($config);
$jimmyPage = $container->get(Guitarist::class);
assert($jimmyPage instanceof Guitarist);
They can be used together.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
use Omar\DependencyInjection\Setup;
interface Guitar {}
class LesPaul implements Guitar {}
class Guitarist
{
public function __construct(Guitar $guitar, int $bornInYear) {}
}
$config = Config::init()
->setup(Guitarist::class, Config::params()
->wire('guitar', LesPaul::class)
->config('bornInYear', 1944)
);
$container = Container::create($config);
$jimmyPage = $container->get(Guitarist::class);
assert($jimmyPage instanceof Guitarist);
You can set up your instances to be created with a callback function. These functions can also get their parameters from the container.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
interface Guitar {}
class LesPaul implements Guitar {}
class Guitarist
{
public function __construct(Guitar $guitar, int $bornInYear) {}
}
$config = Config::init()
->bind(Guitar::class, LesPaul::class)
->provider(Guitarist::class, function (Guitar $guitar) {
return new Guitarist($guitar, 1944);
});
$container = Container::create($config);
$jimmyPage = $container->get(Guitarist::class);
assert($jimmyPage instanceof Guitarist);
You can create your instances with factories. These factories can be configured with the parameters in the constructor and in the __invoke() method.
use Omar\DependencyInjection\Config;
use Omar\DependencyInjection\Container;
interface Guitar {}
class LesPaul implements Guitar {}
class Guitarist
{
public function __construct(Guitar $guitar) {}
}
interface Drummer {}
class JohnBonham implements Drummer {}
class RockBand
{
public function __construct(Guitarist $guitarist, Drummer $drummer) {}
}
class RockBandFactory
{
/** @var Drummer */
private $drummer;
public function __construct(Drummer $drummer) {
$this->drummer = $drummer;
}
public function __invoke(Guitar $guitar): RockBand
{
return new RockBand(new Guitarist($guitar), $this->drummer);
}
}
$config = Config::init()
->bind(Drummer::class, JohnBonham::class)
->bind(Guitar::class, LesPaul::class)
->factory(RockBand::class, RockBandFactory::class);
$container = Container::create($config);
$band = $container->get(RockBand::class);
assert($band instanceof RockBand);
- Pull requests are welcome.
- For major changes, please open an issue first to discuss what you would like to change.