Skip to content

guiwoda/lazy-container

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

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

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages