Skip to content

Instantly share code, notes, and snippets.

@moon0326
Last active August 29, 2015 14:14
Show Gist options
  • Save moon0326/35becfa058e4358272c0 to your computer and use it in GitHub Desktop.
Save moon0326/35becfa058e4358272c0 to your computer and use it in GitHub Desktop.
Simple PHP DI
<?php
class Container
{
protected $index = array();
const TYPE_SINGLETON = 'singleton';
const TYPE_INSTANCE = 'instance';
const TYPE_BIND = 'bind';
public function make($abstract)
{
if ($this->has($abstract)) {
$data = &$this->index[$abstract];
switch ($data['type']) {
case static::TYPE_INSTANCE:
return $data['concret'];
break;
case static::TYPE_SINGLETON:
if ($data['singleton'] === null) {
$data['singleton'] = $data['concret']();
}
return $data['singleton'];
break;
case static::TYPE_BIND:
return $this->resolve($data['concret']);
break;
}
} else {
return $this->resolve($abstract);
}
}
protected function resolve($concret)
{
$reflector = new ReflectionClass($concret);
$method = $reflector->getConstructor();
// the class doesn't have a cosntructor
if (is_null($method)) {
return new $concret();
}
$dependencies = $method->getParameters();
$parameters = array();
foreach ($dependencies as $dependency) {
$dependencyClass = $dependency->getClass();
if (!$dependencyClass) {
continue;
} else {
$dependencyClass = $dependencyClass->name;
}
if ($this->has($dependencyClass)) {
$dependencyObject = $this->make($dependencyClass);
} else {
$dependencyObject = $this->resolve($dependencyClass);
}
array_push($parameters, $dependencyObject);
}
return $reflector->newInstanceArgs($parameters);
}
public function has($key)
{
return array_key_exists($key, $this->index);
}
protected function register($abstract, $concret, $type)
{
if (!is_string($abstract) && !is_callable($concret)) {
throw new InvalidArgumentException("binding name must be a string or callable object.");
}
if ($this->has($abstract)) {
throw new InvalidArgumentException($abstract." is already binded.");
}
$this->index[$abstract] = array(
'type' => $type,
'concret' => $concret,
);
if ($type == static::TYPE_SINGLETON) {
$this->index[$abstract]['singleton'] = null;
}
}
public function bind($abstract, $concret)
{
$this->register($abstract, $concret, static::TYPE_BIND);
}
public function singleton($abstract, $concret)
{
$this->register($abstract, $concret, static::TYPE_SINGLETON);
}
public function instance($abstract, $concret)
{
$this->register($abstract, $concret, static::TYPE_INSTANCE);
}
}
// Interface binding
interface Emailer {}
class SwiftMailer implements Emailer {}
$container = new Container();
$container->bind('Emailer', 'SwiftMailer');
// Autowire/Automatic Resolution
class Food { }
class Human
{
private $food;
public function __construct(Food $food)
{
$this->food = $food;
}
}
$human = $container->make('Human');
// Singleton
$container->singleton('Human', function() {
return new Human(new Food);
});
var_dump($container->make('Human') === $container->make('Human'));
// Instance Binding
$human = new Human(new Food);
$container->instance('Human', $human);
var_dump($human === $container->make('Human'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment