本文采用类似java中annotation的形式实现set注入
首先DI容器代码
require 'DocParser.php';
class Container
{
/**
* 利用容器来实例化对象,外部调用接口
*@param $name 为类名 eg. 'User'
*/
public function get($name)
{
static $cache = array();
if(isset($cache[$name]))
{
return $cache[$name];
}
require 'models/' . ucfirst($name) . '.php';
$reflection = new ReflectionClass($name);
$depends = $this->getDependency($reflection);
$cache[$name] = $this->createObject($reflection, $depends);
return $cache[$name];
}
/**
* 利用反射获取类需要的依赖条件,注释中包含@inject 注解的public 变量
* @param $reflection ReflectionClass
*/
public function getDependency($reflection)
{
$depends = array();
$props = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
$str = $prop->getDocComment();
$parser = new DocParser();
$anotations = $parser->parse($str);
if(isset($anotations['inject']))
{
$depends[$prop->getName()] = $anotations['inject'];
}
}
return $depends;
}
/**
* 实例化对象的方法
* @param $instance ReflectionClass
* @param $depends array( 'field' => 'Class' ), field 为注入的变量名,class为注入的类
*/
public function createObject($instance, $depends)
{
$instance = $instance->newInstanceArgs(array());
foreach ($depends as $key => $value)
{
$instance->{$key} = $this->get($value);
}
return $instance;
}
}
其中 DocParser.php
为解析php注释的工具类。
- 使用方法篇
在同级目录下新建models
文件夹,新建User.php
class User
{
/**
* 使用inject注解来标明该变量需要注入,后面跟着需要注入的类名
* @inject Email
*/
public $email;
public function sendEmail()
{
$this->email->sendEmail();
}
}
新建Email.php
class Email
{
public function sendEmail()
{
echo 'send email!';
}
}
在根目录下新建index.php
require 'Container.php';
$di = new Container();
$user = $di->get('User');
$user->sendEmail();
运行一下index.php
就能看到结果了。
本文只是演示IOC的实现过程,没有考虑实际使用场景。
源码 下载地址