<?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爲 抓手的一類 函數的執行 // 就是這個意思,根本就沒有所謂監聽的意圖
[李景山php]每天TP5-20170106|thinkphp5-Hook.php
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.