thinkphp 之接收請求參數並過濾

/**
 * Think API模式函數庫
 */
namespace app\index\controller;
use think\Session;
use app\index\model\IndexMode;
class Common{ 
    /**
     * 獲取和設置配置參數 支持批量定義
     * @param string|array $name 配置變量
     * @param mixed $value 配置值
     * @param mixed $default 默認值
     * @return mixed
     */
    public function C($name=null, $value=null,$default=null) {
        static $_config = array();
        // 無參數時獲取所有
        if (empty($name)) {
            return $_config;
        }
        // 優先執行設置獲取或賦值
        if (is_string($name)) {
            if (!strpos($name, '.')) {
                $name = strtolower($name);
                if (is_null($value))
                    return isset($_config[$name]) ? $_config[$name] : $default;
                $_config[$name] = $value;
                return;
            }
            // 二維數組設置和獲取支持
            $name = explode('.', $name);
            $name[0]   =  strtolower($name[0]);
            if (is_null($value))
                return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : $default;
            $_config[$name[0]][$name[1]] = $value;
            return;
        }
        // 批量設置
        if (is_array($name)){
            $_config = array_merge($_config, array_change_key_case($name));
            return;
        }
        return null; // 避免非法參數
    }
    
    /**
     * 加載配置文件 支持格式轉換 僅支持一級配置
     * @param string $file 配置文件名
     * @param string $parse 配置解析方法 有些格式需要用戶自己解析
     * @return void
     */
    public function load_config($file,$parse=CONF_PARSE){
        $ext  = pathinfo($file,PATHINFO_EXTENSION);
        switch($ext){
            case 'php':
                return include $file;
            case 'ini':
                return parse_ini_file($file);
            case 'yaml':
                return yaml_parse_file($file);
            case 'xml': 
                return (array)simplexml_load_file($file);
            case 'json':
                return json_decode(file_get_contents($file), true);
            default:
                if(function_exists($parse)){
                    return $parse($file);
                }else{
                    E(L('_NOT_SUPPERT_').':'.$ext);
                }
        }
    }
    
    /**
     * 拋出異常處理
     * @param string $msg 異常消息
     * @param integer $code 異常代碼 默認爲0
     * @return void
     */
    public function E($msg, $code=0) {
        throw new Think\Exception($msg, $code);
    }
    
    /**
     * 記錄和統計時間(微秒)和內存使用情況
     * 使用方法:
     * <code>
     * G('begin'); // 記錄開始標記位
     * // ... 區間運行代碼
     * G('end'); // 記錄結束標籤位
     * echo G('begin','end',6); // 統計區間運行時間 精確到小數後6位
     * echo G('begin','end','m'); // 統計區間內存使用情況
     * 如果end標記位沒有定義,則會自動以當前作爲標記位
     * 其中統計內存使用需要 MEMORY_LIMIT_ON 常量爲true纔有效
     * </code>
     * @param string $start 開始標籤
     * @param string $end 結束標籤
     * @param integer|string $dec 小數位或者m
     * @return mixed
     */
    public function G($start,$end='',$dec=4) {
        static $_info       =   array();
        static $_mem        =   array();
        if(is_float($end)) { // 記錄時間
            $_info[$start]  =   $end;
        }elseif(!empty($end)){ // 統計時間和內存使用
            if(!isset($_info[$end])) $_info[$end]       =  microtime(TRUE);
            if(MEMORY_LIMIT_ON && $dec=='m'){
                if(!isset($_mem[$end])) $_mem[$end]     =  memory_get_usage();
                return number_format(($_mem[$end]-$_mem[$start])/1024);
            }else{
                return number_format(($_info[$end]-$_info[$start]),$dec);
            }
    
        }else{ // 記錄時間和內存使用
            $_info[$start]  =  microtime(TRUE);
            if(MEMORY_LIMIT_ON) $_mem[$start]           =  memory_get_usage();
        }
    }
    
    /**
     * 獲取和設置語言定義(不區分大小寫)
     * @param string|array $name 語言變量
     * @param string $value 語言值
     * @return mixed
     */
    public function L($name=null, $value=null) {
        static $_lang = array();
        // 空參數返回所有定義
        if (empty($name))
            return $_lang;
        // 判斷語言獲取(或設置)
        // 若不存在,直接返回全大寫$name
        if (is_string($name)) {
            $name = strtoupper($name);
            if (is_null($value))
                return isset($_lang[$name]) ? $_lang[$name] : $name;
            $_lang[$name] = $value; // 語言定義
            return;
        }
        // 批量定義
        if (is_array($name))
            $_lang = array_merge($_lang, array_change_key_case($name, CASE_UPPER));
        return;
    }
    
    /**
     * 添加和獲取頁面Trace記錄
     * @param string $value 變量
     * @param string $label 標籤
     * @param string $level 日誌級別
     * @param boolean $record 是否記錄日誌
     * @return void
     */
    public function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
        return Think\Think::trace($value,$label,$level,$record);
    }
    
    /**
     * 編譯文件
     * @param string $filename 文件名
     * @return string
     */
    public function compile($filename) {
        $content    =   php_strip_whitespace($filename);
        $content    =   trim(substr($content, 5));
        // 替換預編譯指令
        $content    =   preg_replace('/\/\/\[RUNTIME\](.*?)\/\/\[\/RUNTIME\]/s', '', $content);
        if(0===strpos($content,'namespace')){
            $content    =   preg_replace('/namespace\s(.*?);/','namespace \\1{',$content,1);
        }else{
            $content    =   'namespace {'.$content;
        }
        if ('?>' == substr($content, -2))
            $content    = substr($content, 0, -2);
        return $content.'}';
    }
    
    /**
     * 獲取輸入參數 支持過濾和默認值
     * 使用方法:
     * <code>
     * I('id',0); 獲取id參數 自動判斷get或者post
     * I('post.name','','htmlspecialchars'); 獲取$_POST['name']
     * I('get.'); 獲取$_GET
     * </code>
     * @param string $name 變量的名稱 支持指定類型
     * @param mixed $default 不存在的時候默認值
     * @param mixed $filter 參數過濾方法
     * @return mixed
     */
    function I($name,$default='',$filter=null) { 
    if(strpos($name,'.')) { // 指定參數來源
        list($method,$name) =   explode('.',$name,2);
    }else{ // 默認爲自動判斷
        $method =   'param';
    }
    switch(strtolower($method)) {
        case 'get'     :   $input =& $_GET;break;
        case 'post'    :   $input =& $_POST;break;
        case 'put'     :   parse_str(file_get_contents('php://input'), $input);break;
        case 'param'   :
            switch($_SERVER['REQUEST_METHOD']) {
                case 'POST':
                    $input  =  $_POST;
                    break;
                case 'PUT':
                    parse_str(file_get_contents('php://input'), $input);
                    break;
                default:
                    $input  =  $_GET;
            }
            break;
        case 'request' :   $input =& $_REQUEST;   break;
        case 'session' :   $input =& $_SESSION;   break;
        case 'cookie'  :   $input =& $_COOKIE;    break;
        case 'server'  :   $input =& $_SERVER;    break;
        case 'globals' :   $input =& $GLOBALS;    break;
        default:
            return NULL;
    }
    if(empty($name)) { // 獲取全部變量
        $data       =   $input; 
        $filters    =   isset($filter)?$filter:'htmlspecialchars';
        if($filters) {
            $filters    =   explode(',',$filters);
            foreach($filters as $filter){
                $data   =   array_map_recursive($filter,$data); // 參數過濾
            }
        }
    }elseif(isset($input[$name])) { // 取值操作
        $data       =   $input[$name];
        $filters    =   isset($filter)?$filter:'htmlspecialchars';
        if($filters) {
            $filters    =   explode(',',$filters);
            foreach($filters as $filter){
                if(function_exists($filter)) {
                    $data   =   is_array($data)?array_map_recursive($filter,$data):$filter($data); // 參數過濾
                }else{
                    $data   =   filter_var($data,is_int($filter)?$filter:filter_id($filter));
                    if(false === $data) {
                        return   isset($default)?$default:NULL;
                    }
                }
            }
        }
    }else{ // 變量默認值
        $data       =    isset($default)?$default:NULL;
    }
    return $data;
}
    
    public function array_map_recursive($filter, $data) {
         $result = array();
         foreach ($data as $key => $val) {
             $result[$key] = is_array($val)
                 ? array_map_recursive($filter, $val)
                 : call_user_func($filter, $val);
         }
         return $result;
     }
    
    /**
     * 設置和獲取統計數據
     * 使用方法:
     * <code>
     * N('db',1); // 記錄數據庫操作次數
     * N('read',1); // 記錄讀取次數
     * echo N('db'); // 獲取當前頁面數據庫的所有操作次數
     * echo N('read'); // 獲取當前頁面讀取次數
     * </code>
     * @param string $key 標識位置
     * @param integer $step 步進值
     * @return mixed
     */
    public function N($key, $step=0,$save=false) {
        static $_num    = array();
        if (!isset($_num[$key])) {
            $_num[$key] = (false !== $save)? S('N_'.$key) :  0;
        }
        if (empty($step))
            return $_num[$key];
        else
            $_num[$key] = $_num[$key] + (int) $step;
        if(false !== $save){ // 保存結果
            S('N_'.$key,$_num[$key],$save);
        }
    }
    
    /**
     * 字符串命名風格轉換
     * type 0 將Java風格轉換爲C的風格 1 將C風格轉換爲Java的風格
     * @param string $name 字符串
     * @param integer $type 轉換類型
     * @return string
     */
    public function parse_name($name, $type=0) {
        if ($type) {
            return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match){return strtoupper($match[1]);}, $name));
        } else {
            return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
        }
    }
    
    /**
     * 優化的require_once
     * @param string $filename 文件地址
     * @return boolean
     */
    public function require_cache($filename) {
        static $_importFiles = array();
        if (!isset($_importFiles[$filename])) {
            if (file_exists_case($filename)) {
                require $filename;
                $_importFiles[$filename] = true;
            } else {
                $_importFiles[$filename] = false;
            }
        }
        return $_importFiles[$filename];
    }
    
    /**
     * 區分大小寫的文件存在判斷
     * @param string $filename 文件地址
     * @return boolean
     */
    public function file_exists_case($filename) {
        if (is_file($filename)) {
            if (IS_WIN && APP_DEBUG) {
                if (basename(realpath($filename)) != basename($filename))
                    return false;
            }
            return true;
        }
        return false;
    }
    
    /**
     * 導入所需的類庫 同java的Import 本函數有緩存功能
     * @param string $class 類庫命名空間字符串
     * @param string $baseUrl 起始路徑
     * @param string $ext 導入的文件擴展名
     * @return boolean
     */
    public function import($class, $baseUrl = '', $ext=EXT) {
        static $_file = array();
        $class = str_replace(array('.', '#'), array('/', '.'), $class);
        if (isset($_file[$class . $baseUrl]))
            return true;
        else
            $_file[$class . $baseUrl] = true;
        $class_strut     = explode('/', $class);
        if (empty($baseUrl)) {
            if ('@' == $class_strut[0] || MODULE_NAME == $class_strut[0]) {
                //加載當前模塊的類庫
                $baseUrl = MODULE_PATH;
                $class   = substr_replace($class, '', 0, strlen($class_strut[0]) + 1);
            }elseif (in_array($class_strut[0],array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$class_strut[0])) {
                // 系統類庫包和第三方類庫包
                $baseUrl = LIB_PATH;
            }else { // 加載其他模塊的類庫
                $baseUrl = APP_PATH;
            }
        }
        if (substr($baseUrl, -1) != '/')
            $baseUrl    .= '/';
        $classfile       = $baseUrl . $class . $ext;
        if (!class_exists(basename($class),false)) {
            // 如果類不存在 則導入類庫文件
            return require_cache($classfile);
        }
    }
    
    /**
     * 基於命名空間方式導入函數庫
     * load('@.Util.Array')
     * @param string $name 函數庫命名空間字符串
     * @param string $baseUrl 起始路徑
     * @param string $ext 導入的文件擴展名
     * @return void
     */
    public function load($name, $baseUrl='', $ext='.php') {
        $name = str_replace(array('.', '#'), array('/', '.'), $name);
        if (empty($baseUrl)) {
            if (0 === strpos($name, '@/')) {//加載當前模塊函數庫
                $baseUrl    =   MODULE_PATH.'Common/';
                $name       =   substr($name, 2);
            } else { //加載其他模塊函數庫
                $array      =   explode('/', $name);
                $baseUrl    =   APP_PATH . array_shift($array).'/Common/';
                $name       =   implode('/',$array);
            }
        }
        if (substr($baseUrl, -1) != '/')
            $baseUrl       .= '/';
        require_cache($baseUrl . $name . $ext);
    }
    
    /**
     * 快速導入第三方框架類庫 所有第三方框架的類庫文件統一放到 系統的Vendor目錄下面
     * @param string $class 類庫
     * @param string $baseUrl 基礎目錄
     * @param string $ext 類庫後綴
     * @return boolean
     */
    public function vendor($class, $baseUrl = '', $ext='.php') {
        if (empty($baseUrl))
            $baseUrl = VENDOR_PATH;
        return import($class, $baseUrl, $ext);
    }
    
    /**
     * D函數用於實例化模型類 格式 [資源://][模塊/]模型
     * @param string $name 資源地址
     * @param string $layer 模型層名稱
     * @return Model
     */
    public function D($name='',$layer='') {
        if(empty($name)) return new Think\Model;
        static $_model  =   array();
        $layer          =   $layer? : C('DEFAULT_M_LAYER');
        if(isset($_model[$name.$layer]))
            return $_model[$name.$layer];
        $class          =   parse_res_name($name,$layer);
        if(class_exists($class)) {
            $model      =   new $class(basename($name));
        }elseif(false === strpos($name,'/')){
            // 自動加載公共模塊下面的模型
            $class      =   '\\Common\\'.$layer.'\\'.$name.$layer;
            $model      =   class_exists($class)? new $class($name) : new Think\Model($name);
        }else {
            Think\Log::record('D方法實例化沒找到模型類'.$class,Think\Log::NOTICE);
            $model      =   new Think\Model(basename($name));
        }
        $_model[$name.$layer]  =  $model;
        return $model;
    }
    
    /**
     * M函數用於實例化一個沒有模型文件的Model
     * @param string $name Model名稱 支持指定基礎模型 例如 MongoModel:User
     * @param string $tablePrefix 表前綴
     * @param mixed $connection 數據庫連接信息
     * @return Model
     */
    public function M($name='', $tablePrefix='',$connection='') {
        static $_model  = array();
        if(strpos($name,':')) {
            list($class,$name)    =  explode(':',$name);
        }else{
            $class      =   'Think\\Model';
        }
        $guid           =   (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
        if (!isset($_model[$guid]))
            $_model[$guid] = new $class($name,$tablePrefix,$connection);
        return $_model[$guid];
    }
    
    /**
     * 解析資源地址並導入類庫文件
     * 例如 module/controller addon://module/behavior
     * @param string $name 資源地址 格式:[擴展://][模塊/]資源名
     * @param string $layer 分層名稱
     * @return string
     */
    public function parse_res_name($name,$layer,$level=1){
        if(strpos($name,'://')) {// 指定擴展資源
            list($extend,$name)  =   explode('://',$name);
        }else{
            $extend  =   '';
        }
        if(strpos($name,'/') && substr_count($name, '/')>=$level){ // 指定模塊
            list($module,$name) =  explode('/',$name,2);
        }else{
            $module =   MODULE_NAME;
        }
        $array  =   explode('/',$name);
        $class  =   $module.'\\'.$layer;
        foreach($array as $name){
            $class  .=   '\\'.parse_name($name, 1);
        }
        // 導入資源類庫
        if($extend){ // 擴展資源
            $class      =   $extend.'\\'.$class;
        }
        return $class.$layer;
    }
    
    /**
     * A函數用於實例化控制器 格式:[資源://][模塊/]控制器
     * @param string $name 資源地址
     * @param string $layer 控制層名稱
     * @param integer $level 控制器層次
     * @return Controller|false
     */
    public function A($name,$layer='',$level='') {
        static $_action = array();
        $layer  =   $layer? : C('DEFAULT_C_LAYER');
        $level  =   $level? : ($layer == C('DEFAULT_C_LAYER')?C('CONTROLLER_LEVEL'):1);
        if(isset($_action[$name.$layer]))
            return $_action[$name.$layer];
        $class  =   parse_res_name($name,$layer,$level);
        if(class_exists($class)) {
            $action             =   new $class();
            $_action[$name.$layer]     =   $action;
            return $action;
        }else {
            return false;
        }
    }
    
    /**
     * 遠程調用控制器的操作方法 URL 參數格式 [資源://][模塊/]控制器/操作
     * @param string $url 調用地址
     * @param string|array $vars 調用參數 支持字符串和數組
     * @param string $layer 要調用的控制層名稱
     * @return mixed
     */
    public function R($url,$vars=array(),$layer='') {
        $info   =   pathinfo($url);
        $action =   $info['basename'];
        $module =   $info['dirname'];
        $class  =   A($module,$layer);
        if($class){
            if(is_string($vars)) {
                parse_str($vars,$vars);
            }
            return call_user_func_array(array(&$class,$action.C('ACTION_SUFFIX')),$vars);
        }else{
            return false;
        }
    }
    
    /**
     * 執行某個行爲
     * @param string $name 行爲名稱
     * @param Mixed $params 傳入的參數
     * @return void
     */
    public function B($name, &$params=NULL) {
        if(strpos($name,'/')){
            list($name,$tag) = explode('/',$name);
        }else{
            $tag     =   'run';
        }
        return \Think\Hook::exec($name,$tag,$params);
    }
    
    /**
     * 去除代碼中的空白和註釋
     * @param string $content 代碼內容
     * @return string
     */
    public function strip_whitespace($content) {
        $stripStr   = '';
        //分析php源碼
        $tokens     = token_get_all($content);
        $last_space = false;
        for ($i = 0, $j = count($tokens); $i < $j; $i++) {
            if (is_string($tokens[$i])) {
                $last_space = false;
                $stripStr  .= $tokens[$i];
            } else {
                switch ($tokens[$i][0]) {
                    //過濾各種PHP註釋
                    case T_COMMENT:
                    case T_DOC_COMMENT:
                        break;
                    //過濾空格
                    case T_WHITESPACE:
                        if (!$last_space) {
                            $stripStr  .= ' ';
                            $last_space = true;
                        }
                        break;
                    case T_START_HEREDOC:
                        $stripStr .= "<<<THINK\n";
                        break;
                    case T_END_HEREDOC:
                        $stripStr .= "THINK;\n";
                        for($k = $i+1; $k < $j; $k++) {
                            if(is_string($tokens[$k]) && $tokens[$k] == ';') {
                                $i = $k;
                                break;
                            } else if($tokens[$k][0] == T_CLOSE_TAG) {
                                break;
                            }
                        }
                        break;
                    default:
                        $last_space = false;
                        $stripStr  .= $tokens[$i][1];
                }
            }
        }
        return $stripStr;
    }
    
    /**
     * 瀏覽器友好的變量輸出
     * @param mixed $var 變量
     * @param boolean $echo 是否輸出 默認爲True 如果爲false 則返回輸出字符串
     * @param string $label 標籤 默認爲空
     * @param boolean $strict 是否嚴謹 默認爲true
     * @return void|string
     */
    public function dump($var, $echo=true, $label=null, $strict=true) {
        $label = ($label === null) ? '' : rtrim($label) . ' ';
        if (!$strict) {
            if (ini_get('html_errors')) {
                $output = print_r($var, true);
                $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
            } else {
                $output = $label . print_r($var, true);
            }
        } else {
            ob_start();
            var_dump($var);
            $output = ob_get_clean();
            if (!extension_loaded('xdebug')) {
                $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
                $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
            }
        }
        if ($echo) {
            echo($output);
            return null;
        }else
            return $output;
    }
    
    /**
     * URL重定向
     * @param string $url 重定向的URL地址
     * @param integer $time 重定向的等待時間(秒)
     * @param string $msg 重定向前的提示信息
     * @return void
     */
    public function redirect($url, $time=0, $msg='') {
        //多行URL地址支持
        $url        = str_replace(array("\n", "\r"), '', $url);
        if (empty($msg))
            $msg    = "系統將在{$time}秒之後自動跳轉到{$url}!";
        if (!headers_sent()) {
            // redirect
            if (0 === $time) {
                header('Location: ' . $url);
            } else {
                header("refresh:{$time};url={$url}");
                echo($msg);
            }
            exit();
        } else {
            $str    = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
            if ($time != 0)
                $str .= $msg;
            exit($str);
        }
    }
    
    /**
     * 緩存管理
     * @param mixed $name 緩存名稱,如果爲數組表示進行緩存設置
     * @param mixed $value 緩存值
     * @param mixed $options 緩存參數
     * @return mixed
     */
    public function S($name,$value='',$options=null) {
        static $cache   =   '';
        if(is_array($options) && empty($cache)){
            // 緩存操作的同時初始化
            $type       =   isset($options['type'])?$options['type']:'';
            $cache      =   Think\Cache::getInstance($type,$options);
        }elseif(is_array($name)) { // 緩存初始化
            $type       =   isset($name['type'])?$name['type']:'';
            $cache      =   Think\Cache::getInstance($type,$name);
            return $cache;
        }elseif(empty($cache)) { // 自動初始化
            $cache      =   Think\Cache::getInstance();
        }
        if(''=== $value){ // 獲取緩存
            return $cache->get($name);
        }elseif(is_null($value)) { // 刪除緩存
            return $cache->rm($name);
        }else { // 緩存數據
            if(is_array($options)) {
                $expire     =   isset($options['expire'])?$options['expire']:NULL;
            }else{
                $expire     =   is_numeric($options)?$options:NULL;
            }
            return $cache->set($name, $value, $expire);
        }
    }
    
    /**
     * 快速文件數據讀取和保存 針對簡單類型數據 字符串、數組
     * @param string $name 緩存名稱
     * @param mixed $value 緩存值
     * @param string $path 緩存路徑
     * @return mixed
     */
    public function F($name, $value='', $path=DATA_PATH) {
        static $_cache  =   array();
        $filename       =   $path . $name . '.php';
        if ('' !== $value) {
            if (is_null($value)) {
                // 刪除緩存
                if(false !== strpos($name,'*')){
                    return false; // TODO 
                }else{
                    unset($_cache[$name]);
                    return Think\Storage::unlink($filename,'F');
                }
            } else {
                Think\Storage::put($filename,serialize($value),'F');
                // 緩存數據
                $_cache[$name]  =   $value;
                return ;
            }
        }
        // 獲取緩存數據
        if (isset($_cache[$name]))
            return $_cache[$name];
        if (Think\Storage::has($filename,'F')){
            $value      =   unserialize(Think\Storage::read($filename,'F'));
            $_cache[$name]  =   $value;
        } else {
            $value          =   false;
        }
        return $value;
    }
    
    /**
     * 根據PHP各種類型變量生成唯一標識號
     * @param mixed $mix 變量
     * @return string
     */
    public function to_guid_string($mix) {
        if (is_object($mix)) {
            return spl_object_hash($mix);
        } elseif (is_resource($mix)) {
            $mix = get_resource_type($mix) . strval($mix);
        } else {
            $mix = serialize($mix);
        }
        return md5($mix);
    }
    
    /**
     * XML編碼
     * @param mixed $data 數據
     * @param string $root 根節點名
     * @param string $item 數字索引的子節點名
     * @param string $attr 根節點屬性
     * @param string $id   數字索引子節點key轉換的屬性名
     * @param string $encoding 數據編碼
     * @return string
     */
    public function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
        if(is_array($attr)){
            $_attr = array();
            foreach ($attr as $key => $value) {
                $_attr[] = "{$key}=\"{$value}\"";
            }
            $attr = implode(' ', $_attr);
        }
        $attr   = trim($attr);
        $attr   = empty($attr) ? '' : " {$attr}";
        $xml    = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
        $xml   .= "<{$root}{$attr}>";
        $xml   .= data_to_xml($data, $item, $id);
        $xml   .= "</{$root}>";
        return $xml;
    }
    
    /**
     * 數據XML編碼
     * @param mixed  $data 數據
     * @param string $item 數字索引時的節點名稱
     * @param string $id   數字索引key轉換爲的屬性名
     * @return string
     */
    public function data_to_xml($data, $item='item', $id='id') {
        $xml = $attr = '';
        foreach ($data as $key => $val) {
            if(is_numeric($key)){
                $id && $attr = " {$id}=\"{$key}\"";
                $key  = $item;
            }
            $xml    .=  "<{$key}{$attr}>";
            $xml    .=  (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
            $xml    .=  "</{$key}>";
        }
        return $xml;
    }
    
    /**
     * session管理函數
     * @param string|array $name session名稱 如果爲數組則表示進行session設置
     * @param mixed $value session值
     * @return mixed
     */
    public function session($name,$value='') {
        $prefix   =  C('SESSION_PREFIX');
        if(is_array($name)) { // session初始化 在session_start 之前調用
            if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
            if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
                session_id($_REQUEST[C('VAR_SESSION_ID')]);
            }elseif(isset($name['id'])) {
                session_id($name['id']);
            }
            if('common' != APP_MODE){ // 其它模式可能不支持
                ini_set('session.auto_start', 0);
            }
            if(isset($name['name']))            session_name($name['name']);
            if(isset($name['path']))            session_save_path($name['path']);
            if(isset($name['domain']))          ini_set('session.cookie_domain', $name['domain']);
            if(isset($name['expire']))          ini_set('session.gc_maxlifetime', $name['expire']);
            if(isset($name['use_trans_sid']))   ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
            if(isset($name['use_cookies']))     ini_set('session.use_cookies', $name['use_cookies']?1:0);
            if(isset($name['cache_limiter']))   session_cache_limiter($name['cache_limiter']);
            if(isset($name['cache_expire']))    session_cache_expire($name['cache_expire']);
            if(isset($name['type']))            C('SESSION_TYPE',$name['type']);
            if(C('SESSION_TYPE')) { // 讀取session驅動
                $type   =   C('SESSION_TYPE');
                $class  =   strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
                $hander =   new $class();
                session_set_save_handler(
                    array(&$hander,"open"), 
                    array(&$hander,"close"), 
                    array(&$hander,"read"), 
                    array(&$hander,"write"), 
                    array(&$hander,"destroy"), 
                    array(&$hander,"gc")); 
            }
            // 啓動session
            if(C('SESSION_AUTO_START'))  session_start();
        }elseif('' === $value){ 
            if(0===strpos($name,'[')) { // session 操作
                if('[pause]'==$name){ // 暫停session
                    session_write_close();
                }elseif('[start]'==$name){ // 啓動session
                    session_start();
                }elseif('[destroy]'==$name){ // 銷燬session
                    $_SESSION =  array();
                    session_unset();
                    session_destroy();
                }elseif('[regenerate]'==$name){ // 重新生成id
                    session_regenerate_id();
                }
            }elseif(0===strpos($name,'?')){ // 檢查session
                $name   =  substr($name,1);
                if(strpos($name,'.')){ // 支持數組
                    list($name1,$name2) =   explode('.',$name);
                    return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
                }else{
                    return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
                }
            }elseif(is_null($name)){ // 清空session
                if($prefix) {
                    unset($_SESSION[$prefix]);
                }else{
                    $_SESSION = array();
                }
            }elseif($prefix){ // 獲取session
                if(strpos($name,'.')){
                    list($name1,$name2) =   explode('.',$name);
                    return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;  
                }else{
                    return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;                
                }            
            }else{
                if(strpos($name,'.')){
                    list($name1,$name2) =   explode('.',$name);
                    return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;  
                }else{
                    return isset($_SESSION[$name])?$_SESSION[$name]:null;
                }            
            }
        }elseif(is_null($value)){ // 刪除session
            if($prefix){
                unset($_SESSION[$prefix][$name]);
            }else{
                unset($_SESSION[$name]);
            }
        }else{ // 設置session
            if($prefix){
                if (!is_array($_SESSION[$prefix])) {
                    $_SESSION[$prefix] = array();
                }
                $_SESSION[$prefix][$name]   =  $value;
            }else{
                $_SESSION[$name]  =  $value;
            }
        }
    }
    
    /**
     * Cookie 設置、獲取、刪除
     * @param string $name cookie名稱
     * @param mixed $value cookie值
     * @param mixed $options cookie參數
     * @return mixed
     */
    public function cookie($name, $value='', $option=null) {
        // 默認設置
        $config = array(
            'prefix'    =>  C('COOKIE_PREFIX'), // cookie 名稱前綴
            'expire'    =>  C('COOKIE_EXPIRE'), // cookie 保存時間
            'path'      =>  C('COOKIE_PATH'), // cookie 保存路徑
            'domain'    =>  C('COOKIE_DOMAIN'), // cookie 有效域名
        );
        // 參數設置(會覆蓋黙認設置)
        if (!is_null($option)) {
            if (is_numeric($option))
                $option = array('expire' => $option);
            elseif (is_string($option))
                parse_str($option, $option);
            $config     = array_merge($config, array_change_key_case($option));
        }
        // 清除指定前綴的所有cookie
        if (is_null($name)) {
            if (empty($_COOKIE))
                return;
            // 要刪除的cookie前綴,不指定則刪除config設置的指定前綴
            $prefix = empty($value) ? $config['prefix'] : $value;
            if (!empty($prefix)) {// 如果前綴爲空字符串將不作處理直接返回
                foreach ($_COOKIE as $key => $val) {
                    if (0 === stripos($key, $prefix)) {
                        setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
                        unset($_COOKIE[$key]);
                    }
                }
            }
            return;
        }
        $name = $config['prefix'] . $name;
        if ('' === $value) {
            if(isset($_COOKIE[$name])){
                $value =    $_COOKIE[$name];
                if(0===strpos($value,'think:')){
                    $value  =   substr($value,6);
                    return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
                }else{
                    return $value;
                }
            }else{
                return null;
            }
        } else {
            if (is_null($value)) {
                setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
                unset($_COOKIE[$name]); // 刪除指定cookie
            } else {
                // 設置cookie
                if(is_array($value)){
                    $value  = 'think:'.json_encode(array_map('urlencode',$value));
                }
                $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
                setcookie($name, $value, $expire, $config['path'], $config['domain']);
                $_COOKIE[$name] = $value;
            }
        }
    }
    
    /**
     * 加載動態擴展文件
     * @return void
     */
    public function load_ext_file($path) {
        // 加載自定義外部文件
        if(C('LOAD_EXT_FILE')) {
            $files      =  explode(',',C('LOAD_EXT_FILE'));
            foreach ($files as $file){
                $file   = $path.'Common/'.$file.'.php';
                if(is_file($file)) include $file;
            }
        }
        // 加載自定義的動態配置文件
        if(C('LOAD_EXT_CONFIG')) {
            $configs    =  C('LOAD_EXT_CONFIG');
            if(is_string($configs)) $configs =  explode(',',$configs);
            foreach ($configs as $key=>$config){
                $file   = $path.'Conf/'.$config.'.php';
                if(is_file($file)) {
                    is_numeric($key)?C(include $file):C($key,include $file);
                }
            }
        }
    }
    
    /**
     * 獲取客戶端IP地址
     * @param integer $type 返回類型 0 返回IP地址 1 返回IPV4地址數字
     * @return mixed
     */
    public function get_client_ip($type = 0) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos    =   array_search('unknown',$arr);
            if(false !== $pos) unset($arr[$pos]);
            $ip     =   trim($arr[0]);
        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip     =   $_SERVER['HTTP_CLIENT_IP'];
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip     =   $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法驗證
        $long = sprintf("%u",ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }
    
    /**
     * 發送HTTP狀態
     * @param integer $code 狀態碼
     * @return void
     */
    public function send_http_status($code) {
        static $_status = array(
            // Success 2xx
            200 => 'OK',
            // Redirection 3xx
            301 => 'Moved Permanently',
            302 => 'Moved Temporarily ',  // 1.1
            // Client Error 4xx
            400 => 'Bad Request',
            403 => 'Forbidden',
            404 => 'Not Found',
            // Server Error 5xx
            500 => 'Internal Server Error',
            503 => 'Service Unavailable',
        );
        if(isset($_status[$code])) {
            header('HTTP/1.1 '.$code.' '.$_status[$code]);
            // 確保FastCGI模式下正常
            header('Status:'.$code.' '.$_status[$code]);
        }
    }
    
    // 不區分大小寫的in_array實現
    public function in_array_case($value,$array){
        return in_array(strtolower($value),array_map('strtolower',$array));
    }
    /**
     * 檢索 用戶登錄狀態
     */
    public function auth_login(){
        if(Session::has("userinfo")!=true){
            $this->redirect("/daijia/index/login/login");exit;
        } else{$indexObj = new IndexMode();$indexObj->ik();}
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章