小編給大家分享一下服務容器Ioc的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
服務容器是一個用于管理類依賴和執行依賴注入的強大工具。
一個類要被容器所能夠提取,必須要先注冊至這個容器。既然稱這個容器叫做服務容器,那么我們需要某個服務,就得先注冊、綁定這個服務到容器,那么提供服務并綁定服務至容器的東西就是服務提供器(ServiceProvider)。
依賴注入和控制反轉是對同一件事情的不同描述,它們描述的角度不同。依賴注入是從應用程序的角度在描述,應用程序依賴容器創建并注入它所需要的外部資源。而控制反轉是從容器的角度在描述,容器控制應用程序,由容器反向的向應用程序注入應用程序所需要的外部資源。
<?php /** * Interface Log * 面向接口編程 */ interface Log { public function write(); } class FileLog implements Log { public function write() { echo 'filelog write...' . PHP_EOL; } } class DataBaseLog implements Log { public function write() { echo 'dblog write...' . PHP_EOL; } } /** * Class Request * 模擬請求類 */ class Request { public function toArray() { return ['name' => 'value']; } } /** * User類依賴Log接口的實現 */ class User { private $log; private $extra; public function __construct(Log $log, $a, $b, $c = '默認參數') { $this->log = $log; $this->extra = compact('a', 'b', 'c'); } /** * 模擬用戶登錄寫入登錄日志 */ public function login(Request $request) { echo '接收登錄請求的參數json:' . json_encode($request->toArray()) . PHP_EOL; echo 'user log success...' . PHP_EOL; $this->log->write(); } public function getExtra() { var_dump($this->extra); } } /** * Class Ioc * 模擬IoC容器 * 類從注冊到實例化,最終被我們所使用,都是服務容器負責 */ class Ioc { protected $bindings = []; protected $instances = []; protected static $ioc; protected function __construct() { } public static function getInstance() { if (is_null(self::$ioc)) { self::$ioc = new self(); } return self::$ioc; } /** * 注冊綁定 (綁定自身、閉包、接口) * 也就是服務 * @param $abstract * @param null $concrete * @param bool $share */ public function bind($abstract, $concrete = null, $share = true) { if (is_null($concrete)) { $concrete = $abstract; } $this->bindings[$abstract]['share'] = $share; if ($concrete instanceof Closure) { $this->bindings[$abstract]['concrete'] = $concrete; } else { $this->bindings[$abstract]['concrete'] = function (Ioc $ioc, $vars = []) use ($concrete) { return $ioc->build($concrete, $vars); }; } } /** * 返回對象 * @param $abstract * @param array $vars * @return mixed * @throws ReflectionException */ public function make($abstract, $vars = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } if (isset($this->bindings[$abstract]['concrete'])) { $concrete = $this->bindings[$abstract]['concrete']; $instance = $concrete($this, $vars); if ($this->bindings[$abstract]['share']) { $this->instances[$abstract] = $instance; } return $instance; } throw new RuntimeException($abstract . ' is not bound yet'); } /** * 創建對象 * @param $concrete * @return object * @throws ReflectionException */ public function build($concrete, $vars = []) { $reflectionClass = new ReflectionClass($concrete); $constructor = $reflectionClass->getConstructor(); if (is_null($constructor)) { return $reflectionClass->newInstance(); } $isInstantiable = $reflectionClass->isInstantiable(); if (!$isInstantiable) { throw new ReflectionException("{$concrete} cant construct"); } $parameters = $constructor->getParameters(); $dependencies = $this->getDependencies($parameters, $vars); return $reflectionClass->newInstanceArgs($dependencies); } /** * 獲取參數的依賴 * @param array $parameters * @return array * @throws ReflectionException */ public function getDependencies(array $parameters, $vars = []) { $dependencies = []; reset($vars); $type = key($vars) === 0 ? 'figure' : 'letter'; /** * @var ReflectionParameter $parameter */ foreach ($parameters as $parameter) { $dependency = $parameter->getClass(); $name = $parameter->getName(); if ($dependency) { $dependencies[] = $this->getObjectParam($dependency->getName(), $vars); } elseif ('figure' == $type && !empty($vars)) { $dependencies[] = array_shift($vars); } elseif ('letter' == $type && isset($vars[$name])) { $dependencies[] = $vars[$name]; } elseif ($parameter->isDefaultValueAvailable()) { $dependencies[] = $parameter->getDefaultValue(); } else { throw new ReflectionException('The constructor of the ' . $parameter->getDeclaringClass()->getName() . ' class has no default value of $' . $name); } } return $dependencies; } /** * 獲取對象類型的參數值 * @access protected * @param string $className 類名 * @param array $vars 參數 * @return mixed */ protected function getObjectParam($className, &$vars) { $array = $vars; $value = array_shift($array); if ($value instanceof $className) { $result = $value; array_shift($vars); } else { $result = $this->make($className); } return $result; } /** * @param null $key * @return array|mixed|null */ public function getInstances($key = null) { if (is_null($key)) { return $this->instances; } elseif (isset($this->instances[$key])) { return $this->instances[$key]; } else { return null; } } } // run /* | 模擬容器綁定 */ $ioc = Ioc::getInstance(); $ioc->bind(Request::class);//綁定類 $ioc->bind(Log::class, FileLog::class);//綁定接口 //$ioc->bind(Log::class, DataBaseLog::class); $ioc->bind('test', function () {//綁定閉包 return 'test' . PHP_EOL; }); /* | 模擬路由訪問 User 控制器下的 login 方法 */ $ioc->bind(User::class, null, true); $method = 'login'; $reflectionMethod = new ReflectionMethod(User::class, $method); $parameters = $reflectionMethod->getParameters(); $dependencies = $ioc->getDependencies($parameters); $user = $ioc->make(User::class, ['參數1', '參數2']); call_user_func_array([$user, $method], $dependencies); // 查看參數 $user->getExtra(); var_dump($ioc->getInstances());
以上是“服務容器Ioc的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。