X、数组$fdi['X] * - 初始化的途径:直接赋值、类名、匿名函数 * *
使用示例:
``` * $di = new PhalApi_DI(); * * // 用的方式有:set/get函数 魔法方法setX/getX、类属性$di->X、数组$di['X'] * $di->key = 'value'; * $di['key'] = 'value'; * $di->set('key', 'value'); * $di->setKey('value'); * * echo $di->key; * echo $di['key']; * echo $di->get('key'); * echo $di->getKey(); * * // 初始化的途径:直接赋值、类名(会回调onInitialize函数)、匿名函数 * $di->simpleKey = array('value'); * $di->classKey = 'PhalApi_DI'; * $di->closureKey = function () { * return 'sth heavy ...'; * }; ``` * * @property PhalApi_Request $request 请求 * @property PhalApi_Response_Json $response 结果响应 * @property PhalApi_Cache $cache 缓存 * @property PhalApi_Crypt $crypt 加密 * @property PhalApi_Config $config 配置 * @property PhalApi_Logger $logger 日记 * @property PhalApi_DB_NotORM $notorm 数据库 * @property PhalApi_Loader $loader 自动加载 * @property PhalApi_Helper_Tracer $tracer 全球追踪器 * * @package PhalApi\DI * @link http://docs.phalconphp.com/en/latest/reference/di.html 实现统一的资源设置、获取与管理,支持延时加载 * @license http://www.phalapi.net/license GPL 协议 * @link http://www.phalapi.net/ * @author dogstar 2014-01-22 */ class PhalApi_DI implements ArrayAccess { /** * @var PhalApi_DI $instance 单例 */ protected static $instance = NULL; /** * @var array $hitTimes 服务命中的次数 */ protected $hitTimes = array(); /** * @var array 注册的服务池 */ protected $data = array(); public function __construct() { } /** * 获取DI单体实例 * * - 1、将进行service级的构造与初始化 * - 2、也可以通过new创建,但不能实现service的共享 */ public static function one() { if (static::$instance == NULL) { static::$instance = new PhalApi_DI(); static::$instance->onConstruct(); } return static::$instance; } /** * service级的构造函数 * * - 1、可实现一些自定义业务的操作,如内置默认service * - 2、首次创建时将会调用 */ public function onConstruct() { $this->request = 'PhalApi_Request'; $this->response = 'PhalApi_Response_Json'; $this->tracer = 'PhalApi_Helper_Tracer'; } public function onInitialize() { } /** * 统一setter * * - 1、设置保存service的构造原型,延时创建 * * @param string $key service注册名称,要求唯一,区分大小写 * @parms mixed $value service的值,可以是具体的值或实例、类名、匿名函数、数组配置 */ public function set($key, $value) { $this->resetHit($key); $this->data[$key] = $value; return $this; } /** * 统一getter * * - 1、获取指定service的值,并根据其原型分不同情况创建 * - 2、首次创建时,如果service级的构造函数可调用,则调用 * - 3、每次获取时,如果非共享且service级的初始化函数可调用,则调用 * * @param string $key service注册名称,要求唯一,区分大小写 * @param mixed $default service不存在时的默认值 * @param boolean $isShare 是否获取共享service * @return mixed 没有此服务时返回NULL */ public function get($key, $default = NULL) { if (!isset($this->data[$key])) { $this->data[$key] = $default; } $this->recordHitTimes($key); if ($this->isFirstHit($key)) { $this->data[$key] = $this->initService($this->data[$key]); } return $this->data[$key]; } /** ------------------ 魔法方法 ------------------ **/ public function __call($name, $arguments) { if (substr($name, 0, 3) == 'set') { $key = lcfirst(substr($name, 3)); return $this->set($key, isset($arguments[0]) ? $arguments[0] : NULL); } else if (substr($name, 0, 3) == 'get') { $key = lcfirst(substr($name, 3)); return $this->get($key, isset($arguments[0]) ? $arguments[0] : NULL); } throw new PhalApi_Exception_InternalServerError( T('Call to undefined method PhalApi_DI::{name}() .', array('name' => $name)) ); } public function __set($name, $value) { $this->set($name, $value); } public function __get($name) { return $this->get($name, NULL); } /** ------------------ ArrayAccess(数组式访问)接口 ------------------ **/ public function offsetSet($offset, $value) { $this->set($offset, $value); } public function offsetGet($offset) { return $this->get($offset, NULL); } public function offsetUnset($offset) { unset($this->data[$offset]); } public function offsetExists($offset) { return isset($this->data[$offset]); } /** ------------------ 内部方法 ------------------ **/ protected function initService($config) { $rs = NULL; if ($config instanceOf Closure) { $rs = $config(); } elseif (is_string($config) && class_exists($config)) { $rs = new $config(); if(is_callable(array($rs, 'onInitialize'))) { call_user_func(array($rs, 'onInitialize')); } } else { $rs = $config; } return $rs; } protected function resetHit($key) { $this->hitTimes[$key] = 0; } protected function isFirstHit($key) { return $this->hitTimes[$key] == 1; } protected function recordHitTimes($key) { if (!isset($this->hitTimes[$key])) { $this->hitTimes[$key] = 0; } $this->hitTimes[$key] ++; } }