Skip to content

Instantly share code, notes, and snippets.

@simensen
Forked from igorw/gist:6557390
Last active December 23, 2015 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simensen/6665994 to your computer and use it in GitHub Desktop.
Save simensen/6665994 to your computer and use it in GitHub Desktop.
<?php
namespace Yolo;
class ServiceNotFoundException extends \RuntimeException {}
class RecursiveServiceDefinitionException extends \RuntimeException {}
class InvalidArgumentException extends \RuntimeException {}
class Container
{
private $definitions = [];
private $instances = [];
function __construct(array $definitions)
{
$this->definitions = $definitions;
}
function get($name)
{
if (isset($this->instances[$name])) {
return $this->instances[$name];
}
if (!isset($this->definitions[$name])) {
throw new ServiceNotFoundException($name);
}
$definition = $this->definitions[$name];
$instance = $this->createInstance($name, $definition);
$this->instances[$name] = $instance;
if (isset($definition['calls'])) {
foreach ($definition['calls'] as $call) {
$arguments = reset($call);
$method = key($call);
call_user_func_array(
[$instance, $method],
array_map([$this, 'resolveArgument'], $arguments)
);
}
}
return $instance;
}
private function createInstance($name, $definition)
{
$class = $definition['class'];
$arguments = isset($definition['arguments']) ? $definition['arguments'] : [];
$resolvedArgs = array_map([$this, 'resolveArgument'], $arguments);
$reflection = new \ReflectionClass($class);
return $reflection->newInstanceArgs($resolvedArgs);
}
private function resolveArgument(array $arg)
{
if (isset($arg['ref'])) {
return $this->get($arg['ref']);
}
if (isset($arg['value'])) {
return $arg['value'];
}
throw new InvalidArgumentException(sprintf('Got invalid service argument %s', json_encode($arg)));
}
}
namespace _;
use Yolo\Container;
use Yolo\RecursiveServiceDefinitionException;
class Foo
{
public $bar;
function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
class Bar {}
class Baz {
public $name;
function __construct($name)
{
$this->name = $name;
}
}
class ExtendableThingPlugin {
private $name;
public function __construct($name)
{
$this->name = $name;
}
}
class ExtendableThing {
private $plugins = [];
public function addPlugin(ExtendableThingPlugin $plugin)
{
$this->pugins[] = $plugin;
}
}
class ThingOne {
private $thingTwo;
public function setThingTwo(ThingTwo $thingTwo)
{
$this->thingTwo = $thingTwo;
}
}
class ThingTwo {
private $thingOne;
public function setThingOne(ThingOne $thingOne)
{
$this->thingOne = $thingOne;
}
}
$container = new Container([
'foo' => [
'class' => '_\Foo',
'arguments' => [['ref' => 'bar']],
],
'bar' => [
'class' => '_\Bar',
],
'baz' => [
'class' => '_\Baz',
'arguments' => [['value' => 'baz']],
],
'plugin_a' => [
'class' => '_\ExtendableThingPlugin',
'arguments' => [['value' => 'Plugin A!']],
],
'plugin_b' => [
'class' => '_\ExtendableThingPlugin',
'arguments' => [['value' => 'Plugin B!']],
],
'plugin_c' => [
'class' => '_\ExtendableThingPlugin',
'arguments' => [['value' => 'Plugin C!']],
],
'extendable_thing' => [
'class' => '_\ExtendableThing',
'calls' => [
['addPlugin' => [['ref' => 'plugin_a']]],
['addPlugin' => [['ref' => 'plugin_c']]],
['addPlugin' => [['ref' => 'plugin_b']]],
],
],
'thing_one' => [
'class' => '_\ThingOne',
'calls' => [
['setThingTwo' => [['ref' => 'thing_two']]],
],
],
'thing_two' => [
'class' => '_\ThingTwo',
'calls' => [
['setThingOne' => [['ref' => 'thing_one']]],
],
],
]);
var_dump($container->get('foo'));
var_dump($container->get('bar'));
var_dump($container->get('baz'));
var_dump($container->get('extendable_thing'));
var_dump($container->get('thing_one'));
var_dump($container->get('thing_two'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment