Slim研讀筆記五之依賴注入容器(補)

上節,我們研讀了Pimple容器的具體實現,這節我們來查看Slim默認容器的實現細節。簡單瀏覽代碼我們可知,Slim默認容器其實就是對Pimple容器進行的一層封裝。前面我們已知Slim\Container完成了集成默認配置項,註冊默認服務。現在,讓我們接着看剩下的代碼。 

    /**
     * 通過標識符查找容器的條目並將其返回
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws ContainerValueNotFoundException  No entry was found for this identifier.
     * @throws ContainerException               Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get($id)
    {
        // 檢查參數或對象是否存在
        if (!$this->offsetExists($id)) {
            throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id));
        }
        try {
            // 根據$id返回一個參數或對象
            return $this->offsetGet($id);
        } catch (\InvalidArgumentException $exception) {
            // 是否該類offsetGet()出現異常。
            if ($this->exceptionThrownByContainer($exception)) {
                throw new SlimContainerException(
                    sprintf('Container error while retrieving "%s"', $id),
                    null,
                    $exception
                );
            } else {
                throw $exception;
            }
        }
    }

爲了研讀進度,我們暫時不會詳細講解異常,後面我們會專門準備一個章節來研讀異常類。但大致對異常有個瞭解還是必須的。

PHP標準庫提供了內置了異常類。
異常
  • BadFunctionCallException —錯誤函數調用異常
  • BadMethodCallException —錯誤方法調用異常
  • DomainException —作用域異常
  • InvalidArgumentException —非法參數異常
  • LengthException —長度異常
  • LogicException —邏輯異常
  • OutOfBoundsException —違背安全原則異常
  • OutOfRangeException —越界索引異常
  • OverflowException —上溢異常
  • RangeException —範圍異常
  • RuntimeException —運行時異常
  • UnderflowException —下溢異常
  • UnexpectedValueException —意外數值異常
讓我們瞭解容器是如何使用異常類的吧
    private function exceptionThrownByContainer(\InvalidArgumentException $exception)
    {
        // 跟蹤異常(包括文件地址、報錯類、函數信息等)
        $trace = $exception->getTrace()[0];

        return $trace['class'] === PimpleContainer::class && $trace['function'] === 'offsetGet';
    }
$exception異常對象的getTrace()方法返回了一個數組,數組項中包括報錯類,報錯文件地址等信息。這裏取第一條,然後返回是否該類的offsetGet方法出現異常。
爲何要這樣寫呢?
其實不難理解,當程序出錯時,我們一般要想確定異常報錯位置,都會自定義一個異常類。但這裏使用了SPL的標準異常類,報錯信息中也可能存在多處有\InvalidArgumentException異常,那要如何確定當前方法就是出錯位置呢?這裏採用自定義判斷函數根據跟蹤信息來確定報錯位置的方式。

OK,讓我們一起瀏覽剩下的代碼吧。
   /**
     * 如果容器可以返回給定標識符的條目,則返回true。
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return boolean
     */
    public function has($id)
    {
        return $this->offsetExists($id);
    }


    /********************************************************************************
     * Magic methods for convenience
     *******************************************************************************/
    // 魔術方法,讀取不可訪問的屬性時__get會使用,然後調用get方法
    public function __get($name)
    {
        return $this->get($name);
    }
    // 魔術方法,當對不可訪問屬性調用isset()或empty()時,__isset()會被調用
    public function __isset($name)
    {
        return $this->has($name);
    }

經過一段時間的努力,相信大家對容器已經有個清晰的瞭解啦。雖然路途艱險,但我們終究克服了困難,默默成長,取得了前進的一大步。柚子也相信每個堅持到這裏的人都是執着的,值得誇讚的!哈哈!

發佈了47 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章