Laravel – Dependency InjectionDrupal 8

As my understanding

Dependency Injection is about how to - defer concreting service class.

Only create the service instance along with the client instance, it means no new keyword in client construct function.

But we still need to clarify the dependency between client and service classes, so we inject the service instance as a parameter into the client construct function.

This is the implementation without DI

class Brush {
  private $color;
  private $texture;
  public function __construct($color, $texture) {
    $this->setColor($color);
  }
  public function setColor($color) {
    $this->color = $color;
  };
  public function getColor() {
    print $this->color;
  };
  public function setTextture($texture) {
    $this->texture = $texture;
  };
  public function getTextture() {
    print $this->texture;
  };
}
class Painter {
  public function draw($color, $texture) {
    $brush = new Brush($color, $texture);
    $brush.getColor();
    $brush.getTexture();
  }
}
$picasso = new Paiter();
$picasso.draw('red', 'soft');

Use Dependency Injection.

class Painter {
  private $brush;
  public function __construct(Brush $brush) {
    $this->brush = $brush;
  }
  public function draw() {
    $this->brush.getColor();
    $this->brush.getTexture();
  }
}
$picasso = new Paiter(new Brush('blue', 'hard'));
$picasso.draw();

Laravel: use service container (Inversion of Control)

Sample 1: for the normal class

// We don't need to bind method here, as Laravel is smart enough to 
// detect we need an instance and use PHP Reflection to new the Brush 
// class for us automatically.
// App:bind( 'Brush', function() {
//  return new Brush;
//});

class Painter {
  private $tool;
  public function __construct(Brush $brush) {
    $this->tool = $tool;
  }
}

Sample 2: for the interface

interface Tool {
}
class Brush implement Tool{
}
class Pencil implement Tool{
}
// App is the Facade of Application extend from Container
// Without this binding, the Painter construct function will get error 
// for binding a interface class. 
App:bind( 'Tool', 'Pencil' );

class Painter {
  private $tool;
  public function __construct(Tool $tool) {
    $this->tool = $tool;
  }
}

Reference: sitepoint blog.

Symfony, use service container

// Register brush in container as a service.
use SymfonyComponentDependencyInjectionContainerBuilder;
$container = new ContainerBuilder();
$container
    ->register('brush', 'Brush');

class Painter {
  private $brush;
  public function __construct(Brush $brush) {
    $this->brush = $brush;
  }
}
// This kind of code will be stored in container.
// And the InvokeAll will be the service.
 Drupal::moduleHandler()->invokeAll('help').