中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用PHP編寫一個輕量級容器

發布時間:2021-02-15 08:14:07 來源:億速云 閱讀:194 作者:Leah 欄目:開發技術

今天就跟大家聊聊有關使用PHP編寫一個輕量級容器,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

實現示例

實現接口中要求的兩個方法

abstract class AbstractContainer implements ContainerInterface
{

  protected $resolvedEntries = [];

  /**
   * @var array
   */
  protected $definitions = [];

  public function __construct($definitions = [])
  {
    foreach ($definitions as $id => $definition) {
      $this->injection($id, $definition);
    }
  }

  public function get($id)
  {

    if (!$this->has($id)) {
      throw new NotFoundException("No entry or class found for {$id}");
    }

    $instance = $this->make($id);

    return $instance;
  }

  public function has($id)
  {
    return isset($this->definitions[$id]);
  }

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

public function make($name)
  {
    if (!is_string($name)) {
      throw new \InvalidArgumentException(sprintf(
        'The name parameter must be of type string, %s given',
        is_object($name) ? get_class($name) : gettype($name)
      ));
    }

    if (isset($this->resolvedEntries[$name])) {
      return $this->resolvedEntries[$name];
    }

    if (!$this->has($name)) {
      throw new NotFoundException("No entry or class found for {$name}");
    }

    $definition = $this->definitions[$name];
    $params = [];
    if (is_array($definition) && isset($definition['class'])) {
      $params = $definition;
      $definition = $definition['class'];
      unset($params['class']);
    }

    $object = $this->reflector($definition, $params);

    return $this->resolvedEntries[$name] = $object;
  }

  public function reflector($concrete, array $params = [])
  {
    if ($concrete instanceof \Closure) {
      return $concrete($params);
    } elseif (is_string($concrete)) {
      $reflection = new \ReflectionClass($concrete);
      $dependencies = $this->getDependencies($reflection);
      foreach ($params as $index => $value) {
        $dependencies[$index] = $value;
      }
      return $reflection->newInstanceArgs($dependencies);
    } elseif (is_object($concrete)) {
      return $concrete;
    }
  }

  /**
   * @param \ReflectionClass $reflection
   * @return array
   */
  private function getDependencies($reflection)
  {
    $dependencies = [];
    $constructor = $reflection->getConstructor();
    if ($constructor !== null) {
      $parameters = $constructor->getParameters();
      $dependencies = $this->getParametersByDependencies($parameters);
    }

    return $dependencies;
  }

  /**
   *
   * 獲取構造類相關參數的依賴
   * @param array $dependencies
   * @return array $parameters
   * */
  private function getParametersByDependencies(array $dependencies)
  {
    $parameters = [];
    foreach ($dependencies as $param) {
      if ($param->getClass()) {
        $paramName = $param->getClass()->name;
        $paramObject = $this->reflector($paramName);
        $parameters[] = $paramObject;
      } elseif ($param->isArray()) {
        if ($param->isDefaultValueAvailable()) {
          $parameters[] = $param->getDefaultValue();
        } else {
          $parameters[] = [];
        }
      } elseif ($param->isCallable()) {
        if ($param->isDefaultValueAvailable()) {
          $parameters[] = $param->getDefaultValue();
        } else {
          $parameters[] = function ($arg) {
          };
        }
      } else {
        if ($param->isDefaultValueAvailable()) {
          $parameters[] = $param->getDefaultValue();
        } else {
          if ($param->allowsNull()) {
            $parameters[] = null;
          } else {
            $parameters[] = false;
          }
        }
      }
    }
    return $parameters;
  }

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

/**
   * @param string $id
   * @param string | array | callable $concrete
   * @throws ContainerException
   */
  public function injection($id, $concrete)
  {
    if (is_array($concrete) && !isset($concrete['class'])) {
      throw new ContainerException('數組必須包含類定義');
    }

    $this->definitions[$id] = $concrete;
  }

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

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

class Container extends AbstractContainer implements \ArrayAccess
{

  public function offsetExists($offset)
  {
    return $this->has($offset);
  }

  public function offsetGet($offset)
  {
    return $this->get($offset);
  }

  public function offsetSet($offset, $value)
  {
    return $this->injection($offset, $value);
  }

  public function offsetUnset($offset)
  {
    unset($this->resolvedEntries[$offset]);
    unset($this->definitions[$offset]);
  }
}

看完上述內容,你們對使用PHP編寫一個輕量級容器有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

龙里县| 昭通市| 嵊泗县| 开封县| 鹤庆县| 南丹县| 丽水市| 彭阳县| 兴国县| 双城市| 鹤庆县| 金溪县| 河南省| 曲靖市| 商丘市| 安新县| 枝江市| 那曲县| 怀来县| 甘南县| 澳门| 黄石市| 盐亭县| 祥云县| 镇远县| 巴楚县| 永靖县| 汕尾市| 红安县| 隆化县| 申扎县| 五莲县| 乌兰浩特市| 老河口市| 虎林市| 贡山| 宁都县| 济源市| 育儿| 龙泉市| 苍溪县|