[李景山php]每天TP5-20170106|thinkphp5-Hook.php

<?php

// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

namespace think;

use think\App;// 應用
use think\Debug;// 調試
use think\Log;// 日誌
// 上述 基本上就已經直接 包含 類了
class Hook
{

   private static $tags = [];// 鉤子倉庫

   /**
    * 動態添加行爲擴展到某個標籤
    * @param string    $tag 標籤名稱
    * @param mixed     $behavior 行爲名稱
    * @param bool      $first 是否放到開頭執行
    * @return void
    */
   public static function add($tag, $behavior, $first = false)// 動態添加 行爲擴展 到 某個標籤
   {// add($tag,$behavior,$first)
      isset(self::$tags[$tag]) || self::$tags[$tag] = [];// 初始化 倉庫 對應的標籤,經典的寫法
        //isset(self::$tags[$tag]) || self::$tags[$tag] = [];
      if (is_array($behavior) && !is_callable($behavior)) {// 如果是 行爲 名稱 是數組,並且 不能被調用
         if (!array_key_exists('_overlay', $behavior) || !$behavior['_overlay']) {
                // 如果不存在 這個 _overlay 的key 或者 這個 key的值爲空
            unset($behavior['_overlay']);// 再次清除一下 這個數據
            self::$tags[$tag] = array_merge(self::$tags[$tag], $behavior);// 合併當前標籤及行爲
         } else {
            unset($behavior['_overlay']);// 清除 重寫標籤
            self::$tags[$tag] = $behavior;// 重寫
         }
      } elseif ($first) {// 如果需要放到開頭執行 單個行爲
         array_unshift(self::$tags[$tag], $behavior);// 壓入 開始位置
      } else {
         self::$tags[$tag][] = $behavior;// 否則 放到 後面
      }
   }

   /**
    * 批量導入插件
    * @param array    $tags 插件信息
    * @param boolean $recursive 是否遞歸合併
    */
   public static function import(array $tags, $recursive = true)
   {// 批量導入,基本上的批量導入 ,都是 tag 標籤 都是 foreach 循環
      if ($recursive) {// 遞歸 合併
         foreach ($tags as $tag => $behavior) {
            self::add($tag, $behavior);
         }
      } else {
         self::$tags = $tags + self::$tags;// 普通合併
      }
   }

   /**
    * 獲取插件信息
    * @param string $tag 插件位置 留空獲取全部
    * @return array
    */
   public static function get($tag = '')// 經典的 獲取方案,數據
   {
      if (empty($tag)) {//獲取全部的插件信息
         return self::$tags;
      } else {
         return array_key_exists($tag, self::$tags) ? self::$tags[$tag] : [];
      }
   }

   /**
    * 監聽標籤的行爲
    * @param string $tag    標籤名稱
    * @param mixed  $params 傳入參數
    * @param mixed  $extra  額外參數
    * @param bool   $once   只獲取一個有效返回值
    * @return mixed
    */
   public static function listen($tag, &$params = null, $extra = null, $once = false)
   {
      $results = [];// 倉庫
      $tags = static::get($tag);// 太多類內部 外包了
      foreach ($tags as $key => $name) {// 此處的 name 應該是行爲的具體情況  是 class名稱
         $results[$key] = self::exec($name, $tag, $params, $extra);
         if (false === $results[$key]) {// 如果返回false 則中斷行爲執行
            break;
         } elseif (!is_null($results[$key]) && $once) {// 一次
            break;
         }
      }
      return $once ? end($results) : $results;// 返回最後的結果
   }

   /**
    * 執行某個行爲
    * @param mixed     $class 要執行的行爲
    * @param string    $tag 方法名(標籤名)
    * @param Mixed     $params 傳人的參數
    * @param mixed     $extra 額外參數
    * @return mixed
    */
   public static function exec($class, $tag = '', &$params = null, $extra = null)
   {// 執行 對應的類
      App::$debug && Debug::remark('behavior_start', 'time');// 行爲記錄
      if (is_callable($class)) {
         $result = call_user_func_array($class, [ & $params, $extra]);
         $class = 'Closure';
      } elseif (is_object($class)) {
         $result = call_user_func_array([$class, $tag], [ & $params, $extra]);
         $class = get_class($class);
      } else {
         $obj = new $class();
         $result = ($tag && is_callable([$obj, $tag])) ? $obj->$tag($params, $extra) : $obj->run($params, $extra);
      }
      if (App::$debug) {
         Debug::remark('behavior_end', 'time');
         Log::record('[ BEHAVIOR ] Run ' . $class . ' @' . $tag . ' [ RunTime:' . Debug::getRangeTime('behavior_start', 'behavior_end') . 's ]', 'info');
      }
      return $result;
   }

}
// 其實 hook 就是一個以標籤 tag爲 抓手的一類 函數的執行
// 就是這個意思,根本就沒有所謂監聽的意圖


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章