国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

香港云服务器
服務器之家 - 編程語言 - PHP教程 - PHP實現一個輕量級容器的方法

PHP實現一個輕量級容器的方法

2019-06-27 16:47烏啦啦 PHP教程

這篇文章主要介紹了PHP實現一個輕量級容器的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

什么是容器

在開發過程中,經常會用到的一個概率就是依賴注入。我們借助依懶注入來解耦代碼,選擇性的按需加載服務,而這些通常都是借助容器來實現。

容器實現對類的統一管理,并且確保對象實例的唯一性

常用的容器網上有很多,如PHP-DI 、 YII-DI 等各種實現,通常他們要么大而全,要么高度適配特定業務,與實際需要存在沖突。

出于需要,我們自己造一個輕量級的輪子,為了保持規范,我們基于PSR-11 來實現。

PSR-11

PSR 是 php-fig 提供的標準建議,雖然不是官方組織,但是得到廣泛認可。PSR-11 提供了容器接口。他包含 ContainerInterface 和 兩個異常接口,提供使用建議。

01/**
02 * Describes the interface of a container that exposes methods to read its entries.
03 */
04interface ContainerInterface
05{
06  /**
07   * Finds an entry of the container by its identifier and returns it.
08   *
09   * @param string $id Identifier of the entry to look for.
10   *
11   * @throws NotFoundExceptionInterface No entry was found for **this** identifier.
12   * @throws ContainerExceptionInterface Error while retrieving the entry.
13   *
14   * @return mixed Entry.
15   */
16  public function get($id);
17 
18  /**
19   * Returns true if the container can return an entry for the given identifier.
20   * Returns false otherwise.
21   *
22   * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
23   * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
24   *
25   * @param string $id Identifier of the entry to look for.
26   *
27   * @return bool
28   */
29  public function has($id);
30}

實現示例

我們先來實現接口中要求的兩個方法

01abstract class AbstractContainer implements ContainerInterface
02{
03 
04  protected $resolvedEntries = [];
05 
06  /**
07   * @var array
08   */
09  protected $definitions = [];
10 
11  public function __construct($definitions = [])
12  {
13    foreach ($definitions as $id => $definition) {
14      $this->injection($id, $definition);
15    }
16  }
17 
18  public function get($id)
19  {
20 
21    if (!$this->has($id)) {
22      throw new NotFoundException("No entry or class found for {$id}");
23    }
24 
25    $instance = $this->make($id);
26 
27    return $instance;
28  }
29 
30  public function has($id)
31  {
32    return isset($this->definitions[$id]);
33  }

實際我們容器中注入的對象是多種多樣的,所以我們單獨抽出實例化方法。

001public function make($name)
002  {
003    if (!is_string($name)) {
004      throw new \InvalidArgumentException(sprintf(
005        'The name parameter must be of type string, %s given',
006        is_object($name) ? get_class($name) : gettype($name)
007      ));
008    }
009 
010    if (isset($this->resolvedEntries[$name])) {
011      return $this->resolvedEntries[$name];
012    }
013 
014    if (!$this->has($name)) {
015      throw new NotFoundException("No entry or class found for {$name}");
016    }
017 
018    $definition = $this->definitions[$name];
019    $params = [];
020    if (is_array($definition) && isset($definition['class'])) {
021      $params = $definition;
022      $definition = $definition['class'];
023      unset($params['class']);
024    }
025 
026    $object = $this->reflector($definition, $params);
027 
028    return $this->resolvedEntries[$name] = $object;
029  }
030 
031  public function reflector($concrete, array $params = [])
032  {
033    if ($concrete instanceof \Closure) {
034      return $concrete($params);
035    } elseif (is_string($concrete)) {
036      $reflection = new \ReflectionClass($concrete);
037      $dependencies = $this->getDependencies($reflection);
038      foreach ($params as $index => $value) {
039        $dependencies[$index] = $value;
040      }
041      return $reflection->newInstanceArgs($dependencies);
042    } elseif (is_object($concrete)) {
043      return $concrete;
044    }
045  }
046 
047  /**
048   * @param \ReflectionClass $reflection
049   * @return array
050   */
051  private function getDependencies($reflection)
052  {
053    $dependencies = [];
054    $constructor = $reflection->getConstructor();
055    if ($constructor !== null) {
056      $parameters = $constructor->getParameters();
057      $dependencies = $this->getParametersByDependencies($parameters);
058    }
059 
060    return $dependencies;
061  }
062 
063  /**
064   *
065   * 獲取構造類相關參數的依賴
066   * @param array $dependencies
067   * @return array $parameters
068   * */
069  private function getParametersByDependencies(array $dependencies)
070  {
071    $parameters = [];
072    foreach ($dependencies as $param) {
073      if ($param->getClass()) {
074        $paramName = $param->getClass()->name;
075        $paramObject = $this->reflector($paramName);
076        $parameters[] = $paramObject;
077      } elseif ($param->isArray()) {
078        if ($param->isDefaultValueAvailable()) {
079          $parameters[] = $param->getDefaultValue();
080        } else {
081          $parameters[] = [];
082        }
083      } elseif ($param->isCallable()) {
084        if ($param->isDefaultValueAvailable()) {
085          $parameters[] = $param->getDefaultValue();
086        } else {
087          $parameters[] = function ($arg) {
088          };
089        }
090      } else {
091        if ($param->isDefaultValueAvailable()) {
092          $parameters[] = $param->getDefaultValue();
093        } else {
094          if ($param->allowsNull()) {
095            $parameters[] = null;
096          } else {
097            $parameters[] = false;
098          }
099        }
100      }
101    }
102    return $parameters;
103  }

如你所見,到目前為止我們只實現了從容器中取出實例,從哪里去提供實例定義呢,所以我們還需要提供一個方水法

01/**
02   * @param string $id
03   * @param string | array | callable $concrete
04   * @throws ContainerException
05   */
06  public function injection($id, $concrete)
07  {
08    if (is_array($concrete) && !isset($concrete['class'])) {
09      throw new ContainerException('數組必須包含類定義');
10    }
11 
12    $this->definitions[$id] = $concrete;
13  }

只有這樣嗎?對的,有了這些操作我們已經有一個完整的容器了,插箱即用。

不過為了使用方便,我們可以再提供一些便捷的方法,比如數組式訪問。

01class Container extends AbstractContainer implements \ArrayAccess
02{
03 
04  public function offsetExists($offset)
05  {
06    return $this->has($offset);
07  }
08 
09  public function offsetGet($offset)
10  {
11    return $this->get($offset);
12  }
13 
14  public function offsetSet($offset, $value)
15  {
16    return $this->injection($offset, $value);
17  }
18 
19  public function offsetUnset($offset)
20  {
21    unset($this->resolvedEntries[$offset]);
22    unset($this->definitions[$offset]);
23  }
24}

這樣我們就擁有了一個功能豐富,使用方便的輕量級容器了,趕快整合到你的項目中去吧。

點擊這里查看完整代碼

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
382
主站蜘蛛池模板: 欧洲精品在线观看 | 免费成人在线观看视频 | 日韩国产高清在线 | 黄色片免费看 | 免费一级片在线 | 特一级毛片 | 二区在线视频 | 久久精品国产一区二区三区不卡 | av一区二区在线观看 | 国产在亚洲 线视频播放 | 2级毛片 | 国产精品视频入口 | 成人爱情偷拍视频在线观看 | 日韩中文在线 | 日韩欧美网 | 国产成人午夜 | 成人免费视频在线观看 | 亚洲青涩在线 | 91精品国产91久久久 | 欧美性久久 | 亚洲色图50p | 欧美成年黄网站色视频 | av不卡在线播放 | 欧美日韩精品一区二区三区四区 | 日韩av免费在线 | 日本福利在线观看 | 国产精品久久久久久婷婷天堂 | 久久777 | 999精品视频 | 日韩精品影院 | 黄色精品网站 | 一区二区三区四区在线 | 欧美日韩亚洲国产 | 91精品国产综合久久香蕉922 | 日本一区二区高清视频 | 青青青国产精品一区二区 | 视频在线一区二区三区 | 国产在线1 | 免费三级黄色片 | 国产成人精品免高潮在线观看 | 欧美性生活片 |