Created
December 13, 2017 04:45
-
-
Save wudi/4b5a8a66f3cc7d12827f60c76ec79d0c to your computer and use it in GitHub Desktop.
Demo Dependency injection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Test