Skip to content

Instantly share code, notes, and snippets.

@wudi
Created December 13, 2017 04:45
Show Gist options
  • Save wudi/4b5a8a66f3cc7d12827f60c76ec79d0c to your computer and use it in GitHub Desktop.
Save wudi/4b5a8a66f3cc7d12827f60c76ec79d0c to your computer and use it in GitHub Desktop.
Demo Dependency injection
<?php
/**
* Class Dependency injection
*/
class DI
{
protected $store = [];
public function register($abstruct, $value)
{
$this->store[$abstruct] = $value;
}
public function invoke($method, ...$args)
{
if (strpos($method, '@') === false) {
throw new Exception('Argument 1 missing character @');
}
$segements = explode('@', $method, 2);
list($class, $method) = $segements;
$object = null;
if ($this->exists($class)) {
$object = $this->getValue($class);
} else {
$object = new $class();
}
$ref = new ReflectionClass($object);
$method = $ref->getMethod($method);
if (!$method) {
throw new Exception("{$class} without method named {$method}");
}
$params = [];
foreach ($method->getParameters() as $value) {
$type = $value->getType();
if ($type) {
$typeName = $type->getName();
if ($this->exists($typeName)) {
$params[] = $this->getValue($typeName);
} elseif ($value->allowsNull()) {
$params[] = $value->getDefaultValue();
} else {
$params[] = new $typeName();
}
} elseif ($value->allowsNull()) {
$params[] = $value->getDefaultValue();
} else {
throw new Exception("{$value->getName()} has no matched");
}
}
foreach ($args as $arg) {
$params[] = $arg;
}
return $method->invokeArgs($object, $params);
}
/**
* @param $abstruct
* @return mixed|null
*/
public function getValue($abstruct)
{
$value = $this->store[$abstruct] ?? null;
return $value instanceof Closure ? $value() : $value;
}
/**
* @param $abstruct
* @return bool
*/
public function exists($abstruct)
{
return isset($this->store[$abstruct]);
}
}
class UserModel
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
class OrderModel
{
public function description()
{
return "I'm order model.";
}
}
$di = new DI();
$di->register(UserModel::class, function () {
return new UserModel("WatchDog");
});
// 不提前注册,尝试自动实例化
//$di->register(OrderModel::class, function () {
// return new OrderModel();
//});
class Controller
{
/**
* @param OrderModel $order 依赖订单模型(自动处理)
* @param UserModel $user 依赖用户模型(获取提前注册的对象)
* @param array $options 配置
* @return string
*/
public function index(OrderModel $order, UserModel $user, $options = ['key' => 'value'])
{
return sprintf("%s: %s\nOptions: %s", $user->getName(), $order->description(), serialize($options));
}
}
$result = $di->invoke('Controller@index');
echo $result . PHP_EOL;
@wudi
Copy link
Author

wudi commented Dec 13, 2017

Test

→ php di.php
WatchDog: I'm order model.
Options: a:1:{s:3:"key";s:5:"value";}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment