greg-md/php-dependency-injection

Dependency Injection technique for PHP.

dev-master 2019-07-23 22:13 UTC

This package is auto-updated.

Last update: 2024-04-24 08:34:00 UTC


README

StyleCI Build Status Total Downloads Latest Stable Version Latest Unstable Version License

Dependency Injection provides a lightweight, but powerful IoC Container that allows you to standardize and centralize the way objects are constructed in your application.

Table of Contents

Requirements

  • PHP Version ^7.1

Installation

composer require greg-md/php-dependency-injection

How It Works

All you need to start using the Dependency Injection technique, is to instantiate an IoC Container and inject objects in it.

$ioc = new \Greg\DependencyInjection\IoCContainer();

Inject

$ioc->inject('foo', Foo::class);

$ioc->inject('bar', new Bar());

You can also inject in a more elegant way, using the object name as abstract.

$ioc->register(new Foo());

The previous example is equivalent with:

$ioc->inject(Foo::class, new Foo());

Customise the way your objects will be instantiated.

$ioc->inject('redis.client', function() {
    $redis = new \Redis();

    $redis->connect();

    return $redis;
});

Get

The next example will return null if the object is not injected in the IoC Container.

$foo = $ioc->get('foo');

Expect

The next example will throw an exception if parameter is not injected in the IoC Container.

$foo = $ioc->expect('foo');

Load

In a real application to take advantage of what's best from Dependency Injection technique, you may want to instantiate objects with dependencies from the IoC Container without defining them manually. The best way to do that is to inject objects with it's names or it's strategies names as abstracts.

Let say we have the Foo class that requires a BarStrategy class.

class Foo
{
    private $bar;
    
    public function __construct(BarStrategy $bar)
    {
        $this->bar = $bar;
    }
}

What we do is inject the BarStrategy into the IoC Container and load the Foo class from it.

BarStrategy is an interface, so, we don't break the SOLID principles.

$ioc->inject(BarStrategy::class, function() {
    return new Bar();
});

$foo = $ioc->load(Foo::class);

Sometimes you may want to redefine one or more dependencies of a class when loading it from the IoC Container.

class Foo
{
    private $bar;
    
    private $baz;
    
    public function __construct(BarStrategy $bar, BazStrategy $bar)
    {
        $this->bar = $bar;
        
        $this->baz = $baz;
    }
}
$ioc->inject(BarStrategy::class, function() {
    return new Bar();
});

$ioc->inject(BazStrategy::class, function() {
    return new Baz();
});

You can easily do it by defining those dependencies next after the class name in load method.

$customBaz = new CustomBaz();

$foo = $ioc->load(Foo::class, $customBaz);

The previous example will instantiate BarStrategy from the IoC Container, which is Bar class and for BazStrategy it will set the CustomBaz defined in the load method.

You can also load with arguments as array.

$ioc->loadArgs(Foo::class, [new CustomBaz()]);

Call

You can call a callable with arguments injected in the Ioc Container the same way as loading classes.

$ioc->call(function(int $foo, Bar $bar) {
    // $bar will be injected from the Ioc Container.
}, 10);

You can also call a callable using arguments as array.

$ioc->callArgs([$someObj, 'someMethod'], ...$arguments);

Autoload

You can autoload some classes by defining their prefixes/suffixes as abstracts.

$ioc->addPrefixes('Foo\\');

$ioc->addSuffixes('Controller');

$controller = $ioc->get(\Foo\BarController::class);

License

MIT © Grigorii Duca

Huuuge Quote

I fear not the man who has practiced 10,000 programming languages once, but I fear the man who has practiced one programming language 10,000 times. © #horrorsquad