Skip to content

Latest commit

 

History

History
82 lines (58 loc) · 2.6 KB

README.md

File metadata and controls

82 lines (58 loc) · 2.6 KB

lazy-container

A lazy (or lazier) version of Laravel's Container.

Install

Composer blah blah

Usage

As with most container bindings, you should limit container dependency to service providers. Make the LazyContainer on your AppServiceProvider, to start with:

use Woda\Container\LazyContainer;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $lazy = $this->app->make(LazyContainer::class);
    }
}

Following examples will assume an instance of the LazyContainer on the $lazy variable.

Closures

A good way to decouple objects is to replace a concrete method call with a higher order function. Laravel's Collection object is a good example of this.

LazyContainer allows you to delegate all dependency resolution of a message call to the container, and build a zero-parameter Closure that can be injected on your objects, thus making them unaware of those dependencies.

$fun = $lazy->closure('SomeComplicated@method');
$moreFun = $lazy->closure(function (Depend $on, Whatever $youNeed) {});

$this->app->bind(MyPretty::class, function () use ($fun) {
    new MyPretty($fun);
});

Any callable (even Laravel's callable strings) will be resolved through the Container when called on.

Commands

Zero-param closures are a great way of decoupling messaging, but sometimes we need more power. Adding parameters to messages will couple ourselves a bit, but in turn we gain more flexibility in our designs.

$doEeet = $lazy->closure(function ($args, Depend $on, Whatever $youNeed) {
	return $on->some($args[0]) + $youNeed($args[1]); 
});

$doEeet('1st param', new SecondParam);

Decorator chains

Decorators are a complicated beast for dependency injection containers:

  • There's a common interface, so you should be able to resolve something when asked for it, but
  • Each decorator depends on that interface, so you need contextual binding, else you'll end up in recursive dependencies.

With Laravel's contextual binding this is doable, but LazyContainer makes it way easier and more readable:

 * // Given an abstract, concrete and two decorators
 * $fn = $lazy->decorate('LoggerInterface', 'Logger', 'BufferingLogger', 'EmailLogger');
 *
 * $logger = $fn(); // new BufferingLogger(new EmailLogger(new Logger)));
 *
 * $logger = $this->app('LoggerInterface'); // Also returns the decorated chain

As you can see, the outermost decorator is bound to the interface, and then each link in the chain is contextually bound to the next until the concrete implementation, which shouldn't depend on the common interface anymore.