class Di implements DiInterface{}
DiInterface接口继承自ArrayAccess自定义接口。php
interface DiInterface extends \\ArrayAccess{}
因此,在Di中,必须实现以下接口方法:app
其中继承自\ArrayAccess预约义接口的:函数
其中继承自DiInterface接口的:fetch
/** * Sets a service using a raw Phalcon\Di\Service definition */ public function setRaw(string! name, <ServiceInterface> rawDefinition) -> <ServiceInterface> { let this->_services[name] = rawDefinition; return rawDefinition; }
一、构造方法__construct():this
/** * Phalcon\\Di constructor */ public function __construct() { var di; let di = self::_default; if !di { let self::_default = this; } }
在构造函数中,会先判断是否设置了默认使用的di容器,若没有,则使用当前的di类做为默认容器。spa
二、set()方法:.net
/** * Registers a service in the services container */ public function set(string! name, var definition, boolean shared = false) -> <ServiceInterface> { var service; let service = new Service(name, definition, shared), this->_services[name] = service; return service; }
该方法主要用于向services container中注入一个服务,而且能够设置是不是可共享的,set服务时,实际上是实例化了一个\Phalcon\Di\Service类,将该Service实例设置为了di->_services属性的一项。code
三、setShared()方法:blog
和set()方法不一样的是,setShared()方法注入的服务默认是共享的(let service = new Service(name, definition, true))。
四、remove()方法:
在当前di的_services中去掉该服务,且去掉共享的实例属性。
五、attempt()方法:
/** * 该方法在注入时,会判断要注入的服务是否已经存在,若已存在,则不会注入(set和setShared都会覆盖) */ public function attempt(string! name, definition, boolean shared = false) -> <ServiceInterface> | boolean { var service; if !isset this->_services[name] { let service = new Service(name, definition, shared), this->_services[name] = service; return service; } return false; }
六、setRaw()方法:
/** * 使用该方法注入时,要求注入的是Phalcon\\Di\\Service接口的一个实例(不会再去实例化Service,而是直接使用该Service接口的实例) */ public function setRaw(string! name, <ServiceInterface> rawDefinition) -> <ServiceInterface> { let this->_services[name] = rawDefinition; return rawDefinition; }
七、getRaw()方法:
/** * 返回一个服务的定义 */ public function getRaw(string! name) -> var { var service; if fetch service, this->_services[name] { return service->getDefinition(); } throw new Exception("Service '" . name . "' wasn't found in the dependency injection container"); }
八、getService()方法:
返回某个服务的Service实例。
九、get()方法:
解析并返回某个服务的实例。
/** * 解析并返回Service实例 */ public function get(string! name, parameters = null) -> var { var service, instance, reflection, eventsManager; let eventsManager = <ManagerInterface> this->_eventsManager; // 在解析service前会执行di:beforeServiceResolve事件 if typeof eventsManager == "object" { eventsManager->fire("di:beforeServiceResolve", this, ["name": name, "parameters": parameters]); } // 判断该服务是否已经注册 if fetch service, this->_services[name] { /** * 若已经注册,则直接调用Service->resolve()方法解析获取实例 */ let instance = service->resolve(parameters, this); } else { /** * 当未在Service中注册时,直接调用get某个服务时,di自己也能够做为解析器来使用,去解析获取实例。 */ if !class_exists(name) { throw new Exception("Service '" . name . "' wasn't found in the dependency injection container"); } // 判断参数是不是数组 if typeof parameters == "array" { // 参数是数组且不为空时,经过反射newInstanceArgs()方法获取实例 if count(parameters) { if is_php_version("5.6") { let reflection = new \ReflectionClass(name), instance = reflection->newInstanceArgs(parameters); } else { let instance = create_instance_params(name, parameters); } } else { // 参数为空时,经过反射的newInstance()方法返回实例 if is_php_version("5.6") { let reflection = new \ReflectionClass(name), instance = reflection->newInstance(); } else { let instance = create_instance(name); } } } else { if is_php_version("5.6") { let reflection = new \ReflectionClass(name), instance = reflection->newInstance(); } else { let instance = create_instance(name); } } } /** * 若是解析出来的服务实例自己实现了InjectionAwareInterface接口(即也是一个容器的话),则为该实例设置使用的DI容器 */ if typeof instance == "object" { if instance instanceof InjectionAwareInterface { instance->setDI(this); } } // 解析完成后,执行di:afterServiceResolve事件 if typeof eventsManager == "object" { eventsManager->fire( "di:afterServiceResolve", this, [ "name": name, "parameters": parameters, "instance": instance ] ); } return instance; }
十、getShared()方法:
/** * 获取Shared服务 */ public function getShared(string! name, parameters = null) { var instance; /** * 若存在已经实例化的服务,则直接返回 */ if fetch instance, this->_sharedInstances[name] { let this->_freshInstance = false; } else { /** * 若不存在已实例化的服务,则解析返回服务 */ let instance = this->get(name, parameters); /** * 将实例化的服务放到服务池中 */ let this->_sharedInstances[name] = instance, this->_freshInstance = true; } return instance; }
十一、has()方法:
DI容器的标准方法,判断容器中是否已经注入了该服务。
十二、wasFreshInstance()方法:判断最新获得的实例,是从服务池中直接获取的仍是拿的是已经存在的一个现成的(参照getShared()方法)。
1三、getServices()方法:从容器DI中获取全部已经注入的服务。
1四、offsetExists()方法:因为继承自\ArrayAccess接口,di容器支持数组化访问,该方法用于判断某个服务是否存在。
1五、offsetSet()方法:di支持经过数组方式设置服务,例如:$this['a'] = 'b';
1六、offsetGet()方法:数组方式获取服务,例如:$a = $this['a'];
1七、offsetUnset()方法:代码中直接return false,目前di不支持unset($this['a'])的方式,移除某个注入的服务。
1八、__call()方法:
/** * 支持经过getA或setA等方法获取或注入服务。 * @param string method * @param array arguments */ public function __call(string! method, arguments = null) -> var|null { var instance, possibleService, services, definition; /** * get开头表示获取 */ if starts_with(method, "get") { let services = this->_services, possibleService = lcfirst(substr(method, 3)); if isset services[possibleService] { if count(arguments) { let instance = this->get(possibleService, arguments); } else { let instance = this->get(possibleService); } return instance; } } /** * set注入服务 */ if starts_with(method, "set") { if fetch definition, arguments[0] { this->set(lcfirst(substr(method, 3)), definition); return null; } } /** * 当服务不存在时,返回异常 */ throw new Exception("Call to undefined method or service '" . method . "'"); }
1九、setDefault()方法:设置默认使用的di容器,具体使用可参考构造函数。
20、getDefault()方法:获取di容器。
2一、reset():将当前默认使用的di容器置null。
一、setShared():默认注入的是可共享的服务。二、set():容许定义当前注入的服务是不是可共享的。
三、attempt():容许注入还未注入过的服务,并自定义是否可共享。
四、setRaw():直接注入一个service实例。
五、offsetSet():数组形式注入一个服务,例如:\$this['app'] = $this。
六、__call():魔术方法注入,例如:setA()的方式注入。
一、get():获取某个服务实例。二、getShared():获取可共享的服务。
三、offsetGet():数组方式获取,例如:\$app = $this['app']。
四、__call():魔术方法获取,例如:getA()的方式获取。