PageRenderTime 62ms CodeModel.GetById 3ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 0ms

/ThinkPHP/Common/functions.php

https://github.com/wujingke/thinkphp
PHP | 1457 lines | 1036 code | 58 blank | 363 comment | 232 complexity | f03ec6d574ed965a7236f4b564f41e9a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2// +----------------------------------------------------------------------
   3// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
   4// +----------------------------------------------------------------------
   5// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
   6// +----------------------------------------------------------------------
   7// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
   8// +----------------------------------------------------------------------
   9// | Author: liu21st <liu21st@gmail.com>
  10// +----------------------------------------------------------------------
  11
  12/**
  13 * Think 系统函数库
  14 */
  15
  16/**
  17 * 获取和设置配置参数 支持批量定义
  18 * @param string|array $name 配置变量
  19 * @param mixed $value 配置值
  20 * @param mixed $default 默认值
  21 * @return mixed
  22 */
  23function C($name=null, $value=null,$default=null) {
  24    static $_config = array();
  25    // 无参数时获取所有
  26    if (empty($name)) {
  27        return $_config;
  28    }
  29    // 优先执行设置获取或赋值
  30    if (is_string($name)) {
  31        if (!strpos($name, '.')) {
  32            $name = strtoupper($name);
  33            if (is_null($value))
  34                return isset($_config[$name]) ? $_config[$name] : $default;
  35            $_config[$name] = $value;
  36            return;
  37        }
  38        // 二维数组设置和获取支持
  39        $name = explode('.', $name);
  40        $name[0]   =  strtoupper($name[0]);
  41        if (is_null($value))
  42            return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : $default;
  43        $_config[$name[0]][$name[1]] = $value;
  44        return;
  45    }
  46    // 批量设置
  47    if (is_array($name)){
  48        $_config = array_merge($_config, array_change_key_case($name,CASE_UPPER));
  49        return;
  50    }
  51    return null; // 避免非法参数
  52}
  53
  54/**
  55 * 加载配置文件 支持格式转换 仅支持一级配置
  56 * @param string $file 配置文件名
  57 * @param string $parse 配置解析方法 有些格式需要用户自己解析
  58 * @return void
  59 */
  60function load_config($file,$parse=CONF_PARSE){
  61    $ext  = pathinfo($file,PATHINFO_EXTENSION);
  62    switch($ext){
  63        case 'php':
  64            return include $file;
  65        case 'ini':
  66            return parse_ini_file($file);
  67        case 'yaml':
  68            return yaml_parse_file($file);
  69        case 'xml': 
  70            return (array)simplexml_load_file($file);
  71        case 'json':
  72            return json_decode(file_get_contents($file), true);
  73        default:
  74            if(function_exists($parse)){
  75                return $parse($file);
  76            }else{
  77                E(L('_NOT_SUPPERT_').':'.$ext);
  78            }
  79    }
  80}
  81
  82/**
  83 * 解析yaml文件返回一个数组
  84 * @param string $file 配置文件名
  85 * @return array
  86 */
  87if (!function_exists('yaml_parse_file')) {
  88    function yaml_parse_file($file) {
  89        vendor('spyc.Spyc');
  90        return Spyc::YAMLLoad($file);
  91    }
  92}
  93
  94/**
  95 * 抛出异常处理
  96 * @param string $msg 异常消息
  97 * @param integer $code 异常代码 默认为0
  98 * @return void
  99 */
 100function E($msg, $code=0) {
 101    throw new Think\Exception($msg, $code);
 102}
 103
 104/**
 105 * 记录和统计时间(微秒)和内存使用情况
 106 * 使用方法:
 107 * <code>
 108 * G('begin'); // 记录开始标记位
 109 * // ... 区间运行代码
 110 * G('end'); // 记录结束标签位
 111 * echo G('begin','end',6); // 统计区间运行时间 精确到小数后6位
 112 * echo G('begin','end','m'); // 统计区间内存使用情况
 113 * 如果end标记位没有定义,则会自动以当前作为标记位
 114 * 其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
 115 * </code>
 116 * @param string $start 开始标签
 117 * @param string $end 结束标签
 118 * @param integer|string $dec 小数位或者m
 119 * @return mixed
 120 */
 121function G($start,$end='',$dec=4) {
 122    static $_info       =   array();
 123    static $_mem        =   array();
 124    if(is_float($end)) { // 记录时间
 125        $_info[$start]  =   $end;
 126    }elseif(!empty($end)){ // 统计时间和内存使用
 127        if(!isset($_info[$end])) $_info[$end]       =  microtime(TRUE);
 128        if(MEMORY_LIMIT_ON && $dec=='m'){
 129            if(!isset($_mem[$end])) $_mem[$end]     =  memory_get_usage();
 130            return number_format(($_mem[$end]-$_mem[$start])/1024);
 131        }else{
 132            return number_format(($_info[$end]-$_info[$start]),$dec);
 133        }
 134
 135    }else{ // 记录时间和内存使用
 136        $_info[$start]  =  microtime(TRUE);
 137        if(MEMORY_LIMIT_ON) $_mem[$start]           =  memory_get_usage();
 138    }
 139}
 140
 141/**
 142 * 获取和设置语言定义(不区分大小写)
 143 * @param string|array $name 语言变量
 144 * @param mixed $value 语言值或者变量
 145 * @return mixed
 146 */
 147function L($name=null, $value=null) {
 148    static $_lang = array();
 149    // 空参数返回所有定义
 150    if (empty($name))
 151        return $_lang;
 152    // 判断语言获取(或设置)
 153    // 若不存在,直接返回全大写$name
 154    if (is_string($name)) {
 155        $name   =   strtoupper($name);
 156        if (is_null($value)){
 157            return isset($_lang[$name]) ? $_lang[$name] : $name;
 158        }elseif(is_array($value)){
 159            // 支持变量
 160            $replace = array_keys($value);
 161            foreach($replace as &$v){
 162                $v = '{$'.$v.'}';
 163            }
 164            return str_replace($replace,$value,isset($_lang[$name]) ? $_lang[$name] : $name);        
 165        }
 166        $_lang[$name] = $value; // 语言定义
 167        return;
 168    }
 169    // 批量定义
 170    if (is_array($name))
 171        $_lang = array_merge($_lang, array_change_key_case($name, CASE_UPPER));
 172    return;
 173}
 174
 175/**
 176 * 添加和获取页面Trace记录
 177 * @param string $value 变量
 178 * @param string $label 标签
 179 * @param string $level 日志级别
 180 * @param boolean $record 是否记录日志
 181 * @return void
 182 */
 183function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
 184    return Think\Think::trace($value,$label,$level,$record);
 185}
 186
 187/**
 188 * 编译文件
 189 * @param string $filename 文件名
 190 * @return string
 191 */
 192function compile($filename) {
 193    $content    =   php_strip_whitespace($filename);
 194    $content    =   trim(substr($content, 5));
 195    // 替换预编译指令
 196    $content    =   preg_replace('/\/\/\[RUNTIME\](.*?)\/\/\[\/RUNTIME\]/s', '', $content);
 197    if(0===strpos($content,'namespace')){
 198        $content    =   preg_replace('/namespace\s(.*?);/','namespace \\1{',$content,1);
 199    }else{
 200        $content    =   'namespace {'.$content;
 201    }
 202    if ('?>' == substr($content, -2))
 203        $content    = substr($content, 0, -2);
 204    return $content.'}';
 205}
 206
 207/**
 208 * 获取模版文件 格式 资源://模块@主题/控制器/操作
 209 * @param string $name 模版资源地址
 210 * @param string $layer 视图层(目录)名称
 211 * @return string
 212 */
 213function T($template='',$layer=''){
 214
 215    // 解析模版资源地址
 216    if(false === strpos($template,'://')){
 217        $template   =   'http://'.str_replace(':', '/',$template);
 218    }
 219    $info   =   parse_url($template);
 220    $file   =   $info['host'].(isset($info['path'])?$info['path']:'');
 221    $module =   isset($info['user'])?$info['user'].'/':MODULE_NAME.'/';
 222    $extend =   $info['scheme'];
 223    $layer  =   $layer?$layer:C('DEFAULT_V_LAYER');
 224
 225    // 获取当前主题的模版路径
 226    $auto   =   C('AUTOLOAD_NAMESPACE');
 227    if($auto && isset($auto[$extend])){ // 扩展资源
 228        $baseUrl    =   $auto[$extend].$module.$layer.'/';
 229    }elseif(C('VIEW_PATH')){ 
 230        // 改变模块视图目录
 231        $baseUrl    =   C('VIEW_PATH');
 232    }elseif(defined('TMPL_PATH')){ 
 233        // 指定全局视图目录
 234        $baseUrl    =   TMPL_PATH.$module;
 235    }else{
 236        $baseUrl    =   APP_PATH.$module.$layer.'/';
 237    }
 238
 239    // 获取主题
 240    $theme  =   substr_count($file,'/')<2 ? C('DEFAULT_THEME') : '';
 241
 242    // 分析模板文件规则
 243    $depr   =   C('TMPL_FILE_DEPR');
 244    if('' == $file) {
 245        // 如果模板文件名为空 按照默认规则定位
 246        $file = CONTROLLER_NAME . $depr . ACTION_NAME;
 247    }elseif(false === strpos($file, '/')){
 248        $file = CONTROLLER_NAME . $depr . $file;
 249    }elseif('/' != $depr){
 250        $file   =   substr_count($file,'/')>1 ? substr_replace($file,$depr,strrpos($file,'/'),1) : str_replace('/', $depr, $file);
 251    }
 252    return $baseUrl.($theme?$theme.'/':'').$file.C('TMPL_TEMPLATE_SUFFIX');
 253}
 254
 255/**
 256 * 获取输入参数 支持过滤和默认值
 257 * 使用方法:
 258 * <code>
 259 * I('id',0); 获取id参数 自动判断get或者post
 260 * I('post.name','','htmlspecialchars'); 获取$_POST['name']
 261 * I('get.'); 获取$_GET
 262 * </code>
 263 * @param string $name 变量的名称 支持指定类型
 264 * @param mixed $default 不存在的时候默认值
 265 * @param mixed $filter 参数过滤方法
 266 * @param mixed $datas 要获取的额外数据源
 267 * @return mixed
 268 */
 269function I($name,$default='',$filter=null,$datas=null) {
 270    if(strpos($name,'.')) { // 指定参数来源
 271        list($method,$name) =   explode('.',$name,2);
 272    }else{ // 默认为自动判断
 273        $method =   'param';
 274    }
 275    switch(strtolower($method)) {
 276        case 'get'     :   $input =& $_GET;break;
 277        case 'post'    :   $input =& $_POST;break;
 278        case 'put'     :   parse_str(file_get_contents('php://input'), $input);break;
 279        case 'param'   :
 280            switch($_SERVER['REQUEST_METHOD']) {
 281                case 'POST':
 282                    $input  =  $_POST;
 283                    break;
 284                case 'PUT':
 285                    parse_str(file_get_contents('php://input'), $input);
 286                    break;
 287                default:
 288                    $input  =  $_GET;
 289            }
 290            break;
 291        case 'path'    :   
 292            $input  =   array();
 293            if(!empty($_SERVER['PATH_INFO'])){
 294                $depr   =   C('URL_PATHINFO_DEPR');
 295                $input  =   explode($depr,trim($_SERVER['PATH_INFO'],$depr));            
 296            }
 297            break;
 298        case 'request' :   $input =& $_REQUEST;   break;
 299        case 'session' :   $input =& $_SESSION;   break;
 300        case 'cookie'  :   $input =& $_COOKIE;    break;
 301        case 'server'  :   $input =& $_SERVER;    break;
 302        case 'globals' :   $input =& $GLOBALS;    break;
 303        case 'data'    :   $input =& $datas;      break;
 304        default:
 305            return NULL;
 306    }
 307    if(''==$name) { // 获取全部变量
 308        $data       =   $input;
 309        array_walk_recursive($data,'filter_exp');
 310        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');
 311        if($filters) {
 312            if(is_string($filters)){
 313                $filters    =   explode(',',$filters);
 314            }
 315            foreach($filters as $filter){
 316                $data   =   array_map_recursive($filter,$data); // 参数过滤
 317            }
 318        }
 319    }elseif(isset($input[$name])) { // 取值操作
 320        $data       =   $input[$name];
 321        is_array($data) && array_walk_recursive($data,'filter_exp');
 322        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');
 323        if($filters) {
 324            if(is_string($filters)){
 325                $filters    =   explode(',',$filters);
 326            }elseif(is_int($filters)){
 327                $filters    =   array($filters);
 328            }
 329            
 330            foreach($filters as $filter){
 331                if(function_exists($filter)) {
 332                    $data   =   is_array($data)?array_map_recursive($filter,$data):$filter($data); // 参数过滤
 333                }else{
 334                    $data   =   filter_var($data,is_int($filter)?$filter:filter_id($filter));
 335                    if(false === $data) {
 336                        return   isset($default)?$default:NULL;
 337                    }
 338                }
 339            }
 340        }
 341    }else{ // 变量默认值
 342        $data       =    isset($default)?$default:NULL;
 343    }
 344    return $data;
 345}
 346
 347function array_map_recursive($filter, $data) {
 348     $result = array();
 349     foreach ($data as $key => $val) {
 350         $result[$key] = is_array($val)
 351             ? array_map_recursive($filter, $val)
 352             : call_user_func($filter, $val);
 353     }
 354     return $result;
 355 }
 356
 357/**
 358 * 设置和获取统计数据
 359 * 使用方法:
 360 * <code>
 361 * N('db',1); // 记录数据库操作次数
 362 * N('read',1); // 记录读取次数
 363 * echo N('db'); // 获取当前页面数据库的所有操作次数
 364 * echo N('read'); // 获取当前页面读取次数
 365 * </code>
 366 * @param string $key 标识位置
 367 * @param integer $step 步进值
 368 * @return mixed
 369 */
 370function N($key, $step=0,$save=false) {
 371    static $_num    = array();
 372    if (!isset($_num[$key])) {
 373        $_num[$key] = (false !== $save)? S('N_'.$key) :  0;
 374    }
 375    if (empty($step))
 376        return $_num[$key];
 377    else
 378        $_num[$key] = $_num[$key] + (int) $step;
 379    if(false !== $save){ // 保存结果
 380        S('N_'.$key,$_num[$key],$save);
 381    }
 382}
 383
 384/**
 385 * 字符串命名风格转换
 386 * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
 387 * @param string $name 字符串
 388 * @param integer $type 转换类型
 389 * @return string
 390 */
 391function parse_name($name, $type=0) {
 392    if ($type) {
 393        return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match){return strtoupper($match[1]);}, $name));
 394    } else {
 395        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
 396    }
 397}
 398
 399/**
 400 * 优化的require_once
 401 * @param string $filename 文件地址
 402 * @return boolean
 403 */
 404function require_cache($filename) {
 405    static $_importFiles = array();
 406    if (!isset($_importFiles[$filename])) {
 407        if (file_exists_case($filename)) {
 408            require $filename;
 409            $_importFiles[$filename] = true;
 410        } else {
 411            $_importFiles[$filename] = false;
 412        }
 413    }
 414    return $_importFiles[$filename];
 415}
 416
 417/**
 418 * 区分大小写的文件存在判断
 419 * @param string $filename 文件地址
 420 * @return boolean
 421 */
 422function file_exists_case($filename) {
 423    if (is_file($filename)) {
 424        if (IS_WIN && APP_DEBUG) {
 425            if (basename(realpath($filename)) != basename($filename))
 426                return false;
 427        }
 428        return true;
 429    }
 430    return false;
 431}
 432
 433/**
 434 * 导入所需的类库 同java的Import 本函数有缓存功能
 435 * @param string $class 类库命名空间字符串
 436 * @param string $baseUrl 起始路径
 437 * @param string $ext 导入的文件扩展名
 438 * @return boolean
 439 */
 440function import($class, $baseUrl = '', $ext=EXT) {
 441    static $_file = array();
 442    $class = str_replace(array('.', '#'), array('/', '.'), $class);
 443    if (isset($_file[$class . $baseUrl]))
 444        return true;
 445    else
 446        $_file[$class . $baseUrl] = true;
 447    $class_strut     = explode('/', $class);
 448    if (empty($baseUrl)) {
 449        if ('@' == $class_strut[0] || MODULE_NAME == $class_strut[0]) {
 450            //加载当前模块的类库
 451            $baseUrl = MODULE_PATH;
 452            $class   = substr_replace($class, '', 0, strlen($class_strut[0]) + 1);
 453        }elseif (in_array($class_strut[0],array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$class_strut[0])) {
 454            // 系统类库包和第三方类库包
 455            $baseUrl = LIB_PATH;
 456        }else { // 加载其他模块的类库
 457            $baseUrl = APP_PATH;
 458        }
 459    }
 460    if (substr($baseUrl, -1) != '/')
 461        $baseUrl    .= '/';
 462    $classfile       = $baseUrl . $class . $ext;
 463    if (!class_exists(basename($class),false)) {
 464        // 如果类不存在 则导入类库文件
 465        return require_cache($classfile);
 466    }
 467}
 468
 469/**
 470 * 基于命名空间方式导入函数库
 471 * load('@.Util.Array')
 472 * @param string $name 函数库命名空间字符串
 473 * @param string $baseUrl 起始路径
 474 * @param string $ext 导入的文件扩展名
 475 * @return void
 476 */
 477function load($name, $baseUrl='', $ext='.php') {
 478    $name = str_replace(array('.', '#'), array('/', '.'), $name);
 479    if (empty($baseUrl)) {
 480        if (0 === strpos($name, '@/')) {//加载当前模块函数库
 481            $baseUrl    =   MODULE_PATH.'Common/';
 482            $name       =   substr($name, 2);
 483        } else { //加载其他模块函数库
 484            $array      =   explode('/', $name);
 485            $baseUrl    =   APP_PATH . array_shift($array).'/Common/';
 486            $name       =   implode('/',$array);
 487        }
 488    }
 489    if (substr($baseUrl, -1) != '/')
 490        $baseUrl       .= '/';
 491    require_cache($baseUrl . $name . $ext);
 492}
 493
 494/**
 495 * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
 496 * @param string $class 类库
 497 * @param string $baseUrl 基础目录
 498 * @param string $ext 类库后缀
 499 * @return boolean
 500 */
 501function vendor($class, $baseUrl = '', $ext='.php') {
 502    if (empty($baseUrl))
 503        $baseUrl = VENDOR_PATH;
 504    return import($class, $baseUrl, $ext);
 505}
 506
 507/**
 508 * 实例化模型类 格式 [资源://][模块/]模型
 509 * @param string $name 资源地址
 510 * @param string $layer 模型层名称
 511 * @return Model
 512 */
 513function D($name='',$layer='') {
 514    if(empty($name)) return new Think\Model;
 515    static $_model  =   array();
 516    $layer          =   $layer? : C('DEFAULT_M_LAYER');
 517    if(isset($_model[$name.$layer]))
 518        return $_model[$name.$layer];
 519    $class          =   parse_res_name($name,$layer);
 520    if(class_exists($class)) {
 521        $model      =   new $class(basename($name));
 522    }elseif(false === strpos($name,'/')){
 523        // 自动加载公共模块下面的模型
 524        if(!C('APP_USE_NAMESPACE')){
 525            import('Common/'.$layer.'/'.$class);
 526        }else{
 527            $class      =   '\\Common\\'.$layer.'\\'.$name.$layer;
 528        }
 529        $model      =   class_exists($class)? new $class($name) : new Think\Model($name);
 530    }else {
 531        Think\Log::record('D方法实例化没找到模型类'.$class,Think\Log::NOTICE);
 532        $model      =   new Think\Model(basename($name));
 533    }
 534    $_model[$name.$layer]  =  $model;
 535    return $model;
 536}
 537
 538/**
 539 * 实例化一个没有模型文件的Model
 540 * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User
 541 * @param string $tablePrefix 表前缀
 542 * @param mixed $connection 数据库连接信息
 543 * @return Model
 544 */
 545function M($name='', $tablePrefix='',$connection='') {
 546    static $_model  = array();
 547    if(strpos($name,':')) {
 548        list($class,$name)    =  explode(':',$name);
 549    }else{
 550        $class      =   'Think\\Model';
 551    }
 552    $guid           =   (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
 553    if (!isset($_model[$guid]))
 554        $_model[$guid] = new $class($name,$tablePrefix,$connection);
 555    return $_model[$guid];
 556}
 557
 558/**
 559 * 解析资源地址并导入类库文件
 560 * 例如 module/controller addon://module/behavior
 561 * @param string $name 资源地址 格式:[扩展://][模块/]资源名
 562 * @param string $layer 分层名称
 563 * @return string
 564 */
 565function parse_res_name($name,$layer,$level=1){
 566    if(strpos($name,'://')) {// 指定扩展资源
 567        list($extend,$name)  =   explode('://',$name);
 568    }else{
 569        $extend  =   '';
 570    }
 571    if(strpos($name,'/') && substr_count($name, '/')>=$level){ // 指定模块
 572        list($module,$name) =  explode('/',$name,2);
 573    }else{
 574        $module =   MODULE_NAME;
 575    }
 576    $array  =   explode('/',$name);
 577    if(!C('APP_USE_NAMESPACE')){
 578        $class  =   parse_name($name, 1);
 579        import($module.'/'.$layer.'/'.$class.$layer);
 580    }else{
 581        $class  =   $module.'\\'.$layer;
 582        foreach($array as $name){
 583            $class  .=   '\\'.parse_name($name, 1);
 584        }
 585        // 导入资源类库
 586        if($extend){ // 扩展资源
 587            $class      =   $extend.'\\'.$class;
 588        }
 589    }
 590    return $class.$layer;
 591}
 592
 593/**
 594 * 用于实例化访问控制器
 595 * @param string $name 控制器名
 596 * @param string $path 控制器命名空间(路径)
 597 * @return Controller|false
 598 */
 599function controller($name,$path=''){
 600    $layer  =   C('DEFAULT_C_LAYER');
 601    if(!C('APP_USE_NAMESPACE')){
 602        $class  =   parse_name($name, 1).$layer;
 603        import(MODULE_NAME.'/'.$layer.'/'.$class);
 604    }else{
 605        $class  =   MODULE_NAME.'\\'.($path?$path.'\\':'').$layer;
 606        $array  =   explode('/',$name);
 607        foreach($array as $name){
 608            $class  .=   '\\'.parse_name($name, 1);
 609        }
 610        $class .=   $layer;
 611    }
 612    if(class_exists($class)) {
 613        return new $class();
 614    }else {
 615        return false;
 616    }
 617}
 618
 619/**
 620 * 实例化多层控制器 格式:[资源://][模块/]控制器
 621 * @param string $name 资源地址
 622 * @param string $layer 控制层名称
 623 * @param integer $level 控制器层次
 624 * @return Controller|false
 625 */
 626function A($name,$layer='',$level='') {
 627    static $_action = array();
 628    $layer  =   $layer? : C('DEFAULT_C_LAYER');
 629    $level  =   $level? : ($layer == C('DEFAULT_C_LAYER')?C('CONTROLLER_LEVEL'):1);
 630    if(isset($_action[$name.$layer]))
 631        return $_action[$name.$layer];
 632    
 633    $class  =   parse_res_name($name,$layer,$level);
 634    if(class_exists($class)) {
 635        $action             =   new $class();
 636        $_action[$name.$layer]     =   $action;
 637        return $action;
 638    }else {
 639        return false;
 640    }
 641}
 642
 643/**
 644 * 远程调用控制器的操作方法 URL 参数格式 [资源://][模块/]控制器/操作
 645 * @param string $url 调用地址
 646 * @param string|array $vars 调用参数 支持字符串和数组
 647 * @param string $layer 要调用的控制层名称
 648 * @return mixed
 649 */
 650function R($url,$vars=array(),$layer='') {
 651    $info   =   pathinfo($url);
 652    $action =   $info['basename'];
 653    $module =   $info['dirname'];
 654    $class  =   A($module,$layer);
 655    if($class){
 656        if(is_string($vars)) {
 657            parse_str($vars,$vars);
 658        }
 659        return call_user_func_array(array(&$class,$action.C('ACTION_SUFFIX')),$vars);
 660    }else{
 661        return false;
 662    }
 663}
 664
 665/**
 666 * 处理标签扩展
 667 * @param string $tag 标签名称
 668 * @param mixed $params 传入参数
 669 * @return mixed
 670 */
 671function tag($tag, &$params=NULL) {
 672    return \Think\Hook::listen($tag,$params);
 673}
 674
 675/**
 676 * 执行某个行为
 677 * @param string $name 行为名称
 678 * @param string $tag 标签名称(行为类无需传入) 
 679 * @param Mixed $params 传入的参数
 680 * @return void
 681 */
 682function B($name, $tag='',&$params=NULL) {
 683    if(''==$tag){
 684        $name   .=  'Behavior';
 685    }
 686    return \Think\Hook::exec($name,$tag,$params);
 687}
 688
 689/**
 690 * 去除代码中的空白和注释
 691 * @param string $content 代码内容
 692 * @return string
 693 */
 694function strip_whitespace($content) {
 695    $stripStr   = '';
 696    //分析php源码
 697    $tokens     = token_get_all($content);
 698    $last_space = false;
 699    for ($i = 0, $j = count($tokens); $i < $j; $i++) {
 700        if (is_string($tokens[$i])) {
 701            $last_space = false;
 702            $stripStr  .= $tokens[$i];
 703        } else {
 704            switch ($tokens[$i][0]) {
 705                //过滤各种PHP注释
 706                case T_COMMENT:
 707                case T_DOC_COMMENT:
 708                    break;
 709                //过滤空格
 710                case T_WHITESPACE:
 711                    if (!$last_space) {
 712                        $stripStr  .= ' ';
 713                        $last_space = true;
 714                    }
 715                    break;
 716                case T_START_HEREDOC:
 717                    $stripStr .= "<<<THINK\n";
 718                    break;
 719                case T_END_HEREDOC:
 720                    $stripStr .= "THINK;\n";
 721                    for($k = $i+1; $k < $j; $k++) {
 722                        if(is_string($tokens[$k]) && $tokens[$k] == ';') {
 723                            $i = $k;
 724                            break;
 725                        } else if($tokens[$k][0] == T_CLOSE_TAG) {
 726                            break;
 727                        }
 728                    }
 729                    break;
 730                default:
 731                    $last_space = false;
 732                    $stripStr  .= $tokens[$i][1];
 733            }
 734        }
 735    }
 736    return $stripStr;
 737}
 738
 739/**
 740 * 自定义异常处理
 741 * @param string $msg 异常消息
 742 * @param string $type 异常类型 默认为Think\Exception
 743 * @param integer $code 异常代码 默认为0
 744 * @return void
 745 */
 746function throw_exception($msg, $type='Think\\Exception', $code=0) {
 747    Think\Log::record('建议使用E方法替代throw_exception',Think\Log::NOTICE);
 748    if (class_exists($type, false))
 749        throw new $type($msg, $code);
 750    else
 751        Think\Think::halt($msg);        // 异常类型不存在则输出错误信息字串
 752}
 753
 754/**
 755 * 浏览器友好的变量输出
 756 * @param mixed $var 变量
 757 * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
 758 * @param string $label 标签 默认为空
 759 * @param boolean $strict 是否严谨 默认为true
 760 * @return void|string
 761 */
 762function dump($var, $echo=true, $label=null, $strict=true) {
 763    $label = ($label === null) ? '' : rtrim($label) . ' ';
 764    if (!$strict) {
 765        if (ini_get('html_errors')) {
 766            $output = print_r($var, true);
 767            $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
 768        } else {
 769            $output = $label . print_r($var, true);
 770        }
 771    } else {
 772        ob_start();
 773        var_dump($var);
 774        $output = ob_get_clean();
 775        if (!extension_loaded('xdebug')) {
 776            $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
 777            $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
 778        }
 779    }
 780    if ($echo) {
 781        echo($output);
 782        return null;
 783    }else
 784        return $output;
 785}
 786
 787/**
 788 * 设置当前页面的布局
 789 * @param string|false $layout 布局名称 为false的时候表示关闭布局
 790 * @return void
 791 */
 792function layout($layout) {
 793    if(false !== $layout) {
 794        // 开启布局
 795        C('LAYOUT_ON',true);
 796        if(is_string($layout)) { // 设置新的布局模板
 797            C('LAYOUT_NAME',$layout);
 798        }
 799    }else{// 临时关闭布局
 800        C('LAYOUT_ON',false);
 801    }
 802}
 803
 804/**
 805 * URL组装 支持不同URL模式
 806 * @param string $url URL表达式,格式:'[模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2...'
 807 * @param string|array $vars 传入的参数,支持数组和字符串
 808 * @param string $suffix 伪静态后缀,默认为true表示获取配置值
 809 * @param boolean $domain 是否显示域名
 810 * @return string
 811 */
 812function U($url='',$vars='',$suffix=true,$domain=false) {
 813    // 解析URL
 814    $info   =  parse_url($url);
 815    $url    =  !empty($info['path'])?$info['path']:ACTION_NAME;
 816    if(isset($info['fragment'])) { // 解析锚点
 817        $anchor =   $info['fragment'];
 818        if(false !== strpos($anchor,'?')) { // 解析参数
 819            list($anchor,$info['query']) = explode('?',$anchor,2);
 820        }        
 821        if(false !== strpos($anchor,'@')) { // 解析域名
 822            list($anchor,$host)    =   explode('@',$anchor, 2);
 823        }
 824    }elseif(false !== strpos($url,'@')) { // 解析域名
 825        list($url,$host)    =   explode('@',$info['path'], 2);
 826    }
 827    // 解析子域名
 828    if(isset($host)) {
 829        $domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.'));
 830    }elseif($domain===true){
 831        $domain = $_SERVER['HTTP_HOST'];
 832        if(C('APP_SUB_DOMAIN_DEPLOY') ) { // 开启子域名部署
 833            $domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.');
 834            // '子域名'=>array('模块[/控制器]');
 835            foreach (C('APP_SUB_DOMAIN_RULES') as $key => $rule) {
 836                $rule   =   is_array($rule)?$rule[0]:$rule;
 837                if(false === strpos($key,'*') && 0=== strpos($url,$rule)) {
 838                    $domain = $key.strstr($domain,'.'); // 生成对应子域名
 839                    $url    =  substr_replace($url,'',0,strlen($rule));
 840                    break;
 841                }
 842            }
 843        }
 844    }
 845
 846    // 解析参数
 847    if(is_string($vars)) { // aaa=1&bbb=2 转换成数组
 848        parse_str($vars,$vars);
 849    }elseif(!is_array($vars)){
 850        $vars = array();
 851    }
 852    if(isset($info['query'])) { // 解析地址里面参数 合并到vars
 853        parse_str($info['query'],$params);
 854        $vars = array_merge($params,$vars);
 855    }
 856    
 857    // URL组装
 858    $depr       =   C('URL_PATHINFO_DEPR');
 859    $urlCase    =   C('URL_CASE_INSENSITIVE');
 860    if($url) {
 861        if(0=== strpos($url,'/')) {// 定义路由
 862            $route      =   true;
 863            $url        =   substr($url,1);
 864            if('/' != $depr) {
 865                $url    =   str_replace('/',$depr,$url);
 866            }
 867        }else{
 868            if('/' != $depr) { // 安全替换
 869                $url    =   str_replace('/',$depr,$url);
 870            }
 871            // 解析模块、控制器和操作
 872            $url        =   trim($url,$depr);
 873            $path       =   explode($depr,$url);
 874            $var        =   array();
 875            $varModule      =   C('VAR_MODULE');
 876            $varController  =   C('VAR_CONTROLLER');
 877            $varAction      =   C('VAR_ACTION');
 878            $var[$varAction]       =   !empty($path)?array_pop($path):ACTION_NAME;
 879            $var[$varController]   =   !empty($path)?array_pop($path):CONTROLLER_NAME;
 880            if($maps = C('URL_ACTION_MAP')) {
 881                if(isset($maps[strtolower($var[$varController])])) {
 882                    $maps    =   $maps[strtolower($var[$varController])];
 883                    if($action = array_search(strtolower($var[$varAction]),$maps)){
 884                        $var[$varAction] = $action;
 885                    }
 886                }
 887            }
 888            if($maps = C('URL_CONTROLLER_MAP')) {
 889                if($controller = array_search(strtolower($var[$varController]),$maps)){
 890                    $var[$varController] = $controller;
 891                }
 892            }
 893            if($urlCase) {
 894                $var[$varController]   =   parse_name($var[$varController]);
 895            }
 896            $module =   '';
 897            
 898            if(!empty($path)) {
 899                $var[$varModule]    =   implode($depr,$path);
 900            }else{
 901                if(C('MULTI_MODULE')) {
 902                    if(MODULE_NAME != C('DEFAULT_MODULE') || !C('MODULE_ALLOW_LIST')){
 903                        $var[$varModule]=   MODULE_NAME;
 904                    }
 905                }
 906            }
 907            if($maps = C('URL_MODULE_MAP')) {
 908                if($_module = array_search(strtolower($var[$varModule]),$maps)){
 909                    $var[$varModule] = $_module;
 910                }
 911            }
 912            if(isset($var[$varModule])){
 913                $module =   $var[$varModule];
 914                unset($var[$varModule]);
 915            }
 916            
 917        }
 918    }
 919
 920    if(C('URL_MODEL') == 0) { // 普通模式URL转换
 921        $url        =   __APP__.'?'.C('VAR_MODULE')."={$module}&".http_build_query(array_reverse($var));
 922        if($urlCase){
 923            $url    =   strtolower($url);
 924        }        
 925        if(!empty($vars)) {
 926            $vars   =   http_build_query($vars);
 927            $url   .=   '&'.$vars;
 928        }
 929    }else{ // PATHINFO模式或者兼容URL模式
 930        if(isset($route)) {
 931            $url    =   __APP__.'/'.rtrim($url,$depr);
 932        }else{
 933            $module =   (defined('BIND_MODULE') && BIND_MODULE==$module )? '' : $module;
 934            $url    =   __APP__.'/'.($module?$module.MODULE_PATHINFO_DEPR:'').implode($depr,array_reverse($var));
 935        }
 936        if($urlCase){
 937            $url    =   strtolower($url);
 938        }
 939        if(!empty($vars)) { // 添加参数
 940            foreach ($vars as $var => $val){
 941                if('' !== trim($val))   $url .= $depr . $var . $depr . urlencode($val);
 942            }                
 943        }
 944        if($suffix) {
 945            $suffix   =  $suffix===true?C('URL_HTML_SUFFIX'):$suffix;
 946            if($pos = strpos($suffix, '|')){
 947                $suffix = substr($suffix, 0, $pos);
 948            }
 949            if($suffix && '/' != substr($url,-1)){
 950                $url  .=  '.'.ltrim($suffix,'.');
 951            }
 952        }
 953    }
 954    if(isset($anchor)){
 955        $url  .= '#'.$anchor;
 956    }
 957    if($domain) {
 958        $url   =  (is_ssl()?'https://':'http://').$domain.$url;
 959    }
 960    return $url;
 961}
 962
 963/**
 964 * 渲染输出Widget
 965 * @param string $name Widget名称
 966 * @param array $data 传入的参数
 967 * @return void
 968 */
 969function W($name, $data=array()) {
 970    return R($name,$data,'Widget');
 971}
 972
 973/**
 974 * 判断是否SSL协议
 975 * @return boolean
 976 */
 977function is_ssl() {
 978    if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){
 979        return true;
 980    }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
 981        return true;
 982    }
 983    return false;
 984}
 985
 986/**
 987 * URL重定向
 988 * @param string $url 重定向的URL地址
 989 * @param integer $time 重定向的等待时间(秒)
 990 * @param string $msg 重定向前的提示信息
 991 * @return void
 992 */
 993function redirect($url, $time=0, $msg='') {
 994    //多行URL地址支持
 995    $url        = str_replace(array("\n", "\r"), '', $url);
 996    if (empty($msg))
 997        $msg    = "系统将在{$time}秒之后自动跳转到{$url}";
 998    if (!headers_sent()) {
 999        // redirect
1000        if (0 === $time) {
1001            header('Location: ' . $url);
1002        } else {
1003            header("refresh:{$time};url={$url}");
1004            echo($msg);
1005        }
1006        exit();
1007    } else {
1008        $str    = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
1009        if ($time != 0)
1010            $str .= $msg;
1011        exit($str);
1012    }
1013}
1014
1015/**
1016 * 缓存管理
1017 * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
1018 * @param mixed $value 缓存值
1019 * @param mixed $options 缓存参数
1020 * @return mixed
1021 */
1022function S($name,$value='',$options=null) {
1023    static $cache   =   '';
1024    if(is_array($options) && empty($cache)){
1025        // 缓存操作的同时初始化
1026        $type       =   isset($options['type'])?$options['type']:'';
1027        $cache      =   Think\Cache::getInstance($type,$options);
1028    }elseif(is_array($name)) { // 缓存初始化
1029        $type       =   isset($name['type'])?$name['type']:'';
1030        $cache      =   Think\Cache::getInstance($type,$name);
1031        return $cache;
1032    }elseif(empty($cache)) { // 自动初始化
1033        $cache      =   Think\Cache::getInstance();
1034    }
1035    if(''=== $value){ // 获取缓存
1036        return $cache->get($name);
1037    }elseif(is_null($value)) { // 删除缓存
1038        return $cache->rm($name);
1039    }else { // 缓存数据
1040        if(is_array($options)) {
1041            $expire     =   isset($options['expire'])?$options['expire']:NULL;
1042        }else{
1043            $expire     =   is_numeric($options)?$options:NULL;
1044        }
1045        return $cache->set($name, $value, $expire);
1046    }
1047}
1048
1049/**
1050 * 快速文件数据读取和保存 针对简单类型数据 字符串、数组
1051 * @param string $name 缓存名称
1052 * @param mixed $value 缓存值
1053 * @param string $path 缓存路径
1054 * @return mixed
1055 */
1056function F($name, $value='', $path=DATA_PATH) {
1057    static $_cache  =   array();
1058    $filename       =   $path . $name . '.php';
1059    if ('' !== $value) {
1060        if (is_null($value)) {
1061            // 删除缓存
1062            if(false !== strpos($name,'*')){
1063                return false; // TODO 
1064            }else{
1065                unset($_cache[$name]);
1066                return Think\Storage::unlink($filename,'F');
1067            }
1068        } else {
1069            Think\Storage::put($filename,serialize($value),'F');
1070            // 缓存数据
1071            $_cache[$name]  =   $value;
1072            return ;
1073        }
1074    }
1075    // 获取缓存数据
1076    if (isset($_cache[$name]))
1077        return $_cache[$name];
1078    if (Think\Storage::has($filename,'F')){
1079        $value      =   unserialize(Think\Storage::read($filename,'F'));
1080        $_cache[$name]  =   $value;
1081    } else {
1082        $value          =   false;
1083    }
1084    return $value;
1085}
1086
1087/**
1088 * 根据PHP各种类型变量生成唯一标识号
1089 * @param mixed $mix 变量
1090 * @return string
1091 */
1092function to_guid_string($mix) {
1093    if (is_object($mix)) {
1094        return spl_object_hash($mix);
1095    } elseif (is_resource($mix)) {
1096        $mix = get_resource_type($mix) . strval($mix);
1097    } else {
1098        $mix = serialize($mix);
1099    }
1100    return md5($mix);
1101}
1102
1103/**
1104 * XML编码
1105 * @param mixed $data 数据
1106 * @param string $root 根节点名
1107 * @param string $item 数字索引的子节点名
1108 * @param string $attr 根节点属性
1109 * @param string $id   数字索引子节点key转换的属性名
1110 * @param string $encoding 数据编码
1111 * @return string
1112 */
1113function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
1114    if(is_array($attr)){
1115        $_attr = array();
1116        foreach ($attr as $key => $value) {
1117            $_attr[] = "{$key}=\"{$value}\"";
1118        }
1119        $attr = implode(' ', $_attr);
1120    }
1121    $attr   = trim($attr);
1122    $attr   = empty($attr) ? '' : " {$attr}";
1123    $xml    = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
1124    $xml   .= "<{$root}{$attr}>";
1125    $xml   .= data_to_xml($data, $item, $id);
1126    $xml   .= "</{$root}>";
1127    return $xml;
1128}
1129
1130/**
1131 * 数据XML编码
1132 * @param mixed  $data 数据
1133 * @param string $item 数字索引时的节点名称
1134 * @param string $id   数字索引key转换为的属性名
1135 * @return string
1136 */
1137function data_to_xml($data, $item='item', $id='id') {
1138    $xml = $attr = '';
1139    foreach ($data as $key => $val) {
1140        if(is_numeric($key)){
1141            $id && $attr = " {$id}=\"{$key}\"";
1142            $key  = $item;
1143        }
1144        $xml    .=  "<{$key}{$attr}>";
1145        $xml    .=  (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
1146        $xml    .=  "</{$key}>";
1147    }
1148    return $xml;
1149}
1150
1151/**
1152 * session管理函数
1153 * @param string|array $name session名称 如果为数组则表示进行session设置
1154 * @param mixed $value session值
1155 * @return mixed
1156 */
1157function session($name='',$value='') {
1158    $prefix   =  C('SESSION_PREFIX');
1159    if(is_array($name)) { // session初始化 在session_start 之前调用
1160        if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
1161        if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
1162            session_id($_REQUEST[C('VAR_SESSION_ID')]);
1163        }elseif(isset($name['id'])) {
1164            session_id($name['id']);
1165        }
1166        if('common' != APP_MODE){ // 其它模式可能不支持
1167            ini_set('session.auto_start', 0);
1168        }
1169        if(isset($name['name']))            session_name($name['name']);
1170        if(isset($name['path']))            session_save_path($name['path']);
1171        if(isset($name['domain']))          ini_set('session.cookie_domain', $name['domain']);
1172        if(isset($name['expire']))          ini_set('session.gc_maxlifetime', $name['expire']);
1173        if(isset($name['use_trans_sid']))   ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
1174        if(isset($name['use_cookies']))     ini_set('session.use_cookies', $name['use_cookies']?1:0);
1175        if(isset($name['cache_limiter']))   session_cache_limiter($name['cache_limiter']);
1176        if(isset($name['cache_expire']))    session_cache_expire($name['cache_expire']);
1177        if(isset($name['type']))            C('SESSION_TYPE',$name['type']);
1178        if(C('SESSION_TYPE')) { // 读取session驱动
1179            $type   =   C('SESSION_TYPE');
1180            $class  =   strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
1181            $hander =   new $class();
1182            session_set_save_handler(
1183                array(&$hander,"open"), 
1184                array(&$hander,"close"), 
1185                array(&$hander,"read"), 
1186                array(&$hander,"write"), 
1187                array(&$hander,"destroy"), 
1188                array(&$hander,"gc")); 
1189        }
1190        // 启动session
1191        if(C('SESSION_AUTO_START'))  session_start();
1192    }elseif('' === $value){ 
1193        if(''===$name){
1194            // 获取全部的session
1195            return $prefix ? $_SESSION[$prefix] : $_SESSION;
1196        }elseif(0===strpos($name,'[')) { // session 操作
1197            if('[pause]'==$name){ // 暂停session
1198                session_write_close();
1199            }elseif('[start]'==$name){ // 启动session
1200                session_start();
1201            }elseif('[destroy]'==$name){ // 销毁session
1202                $_SESSION =  array();
1203                session_unset();
1204                session_destroy();
1205            }elseif('[regenerate]'==$name){ // 重新生成id
1206                session_regenerate_id();
1207            }
1208        }elseif(0===strpos($name,'?')){ // 检查session
1209            $name   =  substr($name,1);
1210            if(strpos($name,'.')){ // 支持数组
1211                list($name1,$name2) =   explode('.',$name);
1212                return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
1213            }else{
1214                return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
1215            }
1216        }elseif(is_null($name)){ // 清空session
1217            if($prefix) {
1218                unset($_SESSION[$prefix]);
1219            }else{
1220                $_SESSION = array();
1221            }
1222        }elseif($prefix){ // 获取session
1223            if(strpos($name,'.')){
1224                list($name1,$name2) =   explode('.',$name);
1225                return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;  
1226            }else{
1227                return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;                
1228            }            
1229        }else{
1230            if(strpos($name,'.')){
1231                list($name1,$name2) =   explode('.',$name);
1232                return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;  
1233            }else{
1234                return isset($_SESSION[$name])?$_SESSION[$name]:null;
1235            }            
1236        }
1237    }elseif(is_null($value)){ // 删除session
1238        if($prefix){
1239            unset($_SESSION[$prefix][$name]);
1240        }else{
1241            unset($_SESSION[$name]);
1242        }
1243    }else{ // 设置session
1244        if($prefix){
1245            if (!isset($_SESSION[$prefix])) {
1246                $_SESSION[$prefix] = array();
1247            }
1248            $_SESSION[$prefix][$name]   =  $value;
1249        }else{
1250            $_SESSION[$name]  =  $value;
1251        }
1252    }
1253}
1254
1255/**
1256 * Cookie 设置、获取、删除
1257 * @param string $name cookie名称
1258 * @param mixed $value cookie值
1259 * @param mixed $options cookie参数
1260 * @return mixed
1261 */
1262function cookie($name='', $value='', $option=null) {
1263    // 默认设置
1264    $config = array(
1265        'prefix'    =>  C('COOKIE_PREFIX'), // cookie 名称前缀
1266        'expire'    =>  C('COOKIE_EXPIRE'), // cookie 保存时间
1267        'path'      =>  C('COOKIE_PATH'), // cookie 保存路径
1268        'domain'    =>  C('COOKIE_DOMAIN'), // cookie 有效域名
1269        'httponly'  =>  C('COOKIE_HTTPONLY'), // httponly设置
1270    );
1271    // 参数设置(会覆盖黙认设置)
1272    if (!is_null($option)) {
1273        if (is_numeric($option))
1274            $option = array('expire' => $option);
1275        elseif (is_string($option))
1276            parse_str($option, $option);
1277        $config     = array_merge($config, array_change_key_case($option));
1278    }
1279    if(!empty($config['httponly'])){
1280        ini_set("session.cookie_httponly", 1);
1281    }
1282    // 清除指定前缀的所有cookie
1283    if (is_null($name)) {
1284        if (empty($_COOKIE))
1285            return;
1286        // 要删除的cookie前缀,不指定则删除config设置的指定前缀
1287        $prefix = empty($value) ? $config['prefix'] : $value;
1288        if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
1289            foreach ($_COOKIE as $key => $val) {
1290                if (0 === stripos($key, $prefix)) {
1291                    setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
1292                    unset($_COOKIE[$key]);
1293                }
1294            }
1295        }
1296        return;
1297    }elseif('' === $name){
1298        // 获取全部的cookie
1299        return $_COOKIE;
1300    }
1301    $name = $config['prefix'] . str_replace('.', '_', $name);
1302    if ('' === $value) {
1303        if(isset($_COOKIE[$name])){
1304            $value =    $_COOKIE[$name];
1305            if(0===strpos($value,'think:')){
1306                $value  =   substr($value,6);
1307                return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
1308            }else{
1309                return $value;
1310            }
1311        }else{
1312            return null;
1313        }
1314    } else {
1315        if (is_null($value)) {
1316            setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
1317            unset($_COOKIE[$name]); // 删除指定cookie
1318        } else {
1319            // 设置cookie
1320            if(is_array($value)){
1321                $value  = 'think:'.json_encode(array_map('urlencode',$value));
1322            }
1323            $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
1324            setcookie($name, $value, $expire, $config['path'], $config['domain']);
1325            $_COOKIE[$name] = $value;
1326        }
1327    }
1328}
1329
1330/**
1331 * 加载动态扩展文件
1332 * @return void
1333 */
1334function load_ext_file($path) {
1335    // 加载自定义外部文件
1336    if($files = C('LOAD_EXT_FILE')) {
1337        $files      =  explode(',',$files);
1338        foreach ($files as $file){
1339            $file   = $path.'Common/'.$file.'.php';
1340            if(is_file($file)) include $file;
1341        }
1342    }
1343    // 加载自定义的动态配置文件
1344    if($configs = C('LOAD_EXT_CONFIG')) {
1345        if(is_string($configs)) $configs =  explode(',',$configs);
1346        foreach ($configs as $key=>$config){
1347            $file   = $path.'Conf/'.$config.CONF_EXT;
1348            if(is_file($file)) {
1349                is_numeric($key)?C(load_config($file)):C($key,load_config($file));
1350            }
1351        }
1352    }
1353}
1354
1355/**
1356 * 获取客户端IP地址
1357 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
1358 * @param boolean $adv 是否进行高级模式获取(有可能被伪装) 
1359 * @return mixed
1360 */
1361function get_client_ip($type = 0,$adv=false) {
1362    $type       =  $type ? 1 : 0;
1363    static $ip  =   NULL;
1364    if ($ip !== NULL) return $ip[$type];
1365    if($adv){
1366        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1367            $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
1368            $pos    =   array_search('unknown',$arr);
1369            if(false !== $pos) unset($arr[$pos]);
1370            $ip     =   trim($arr[0]);
1371        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
1372            $ip     =   $_SERVER['HTTP_CLIENT_IP'];
1373        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
1374            $ip     =   $_SERVER['REMOTE_ADDR'];
1375        }
1376    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
1377        $ip     =   $_SERVER['REMOTE_ADDR'];
1378    }
1379    // IP地址合法验证
1380    $long = sprintf("%u",ip2long($ip));
1381    $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
1382    return $ip[$type];
1383}
1384
1385/**
1386 * 发送HTTP状态
1387 * @param integer $code 状态码
1388 * @return void
1389 */
1390function send_http_status($code) {
1391    static $_status = array(
1392            // Informational 1xx
1393            100 => 'Continue',
1394            101 => 'Switching Protocols',
1395            // Success 2xx
1396            200 => 'OK',
1397            201 => 'Created',
1398            202 => 'Accepted',
1399            203 => 'Non-Authoritative Information',
1400            204 => 'No Content',
1401            205 => 'Reset Content',
1402            206 => 'Partial Content',
1403            // Redirection 3xx
1404            300 => 'Multiple Choices',
1405            301 => 'Moved Permanently',
1406            302 => 'Moved Temporarily ',  // 1.1
1407            303 => 'See Other',
1408            304 => 'Not Modified',
1409            305 => 'Use Proxy',
1410            // 306 is deprecated but reserved
1411            307 => 'Temporary Redirect',
1412            // Client Error 4xx
1413            400 => 'Bad Request',
1414            401 => 'Unauthorized',
1415            402 => 'Payment Required',
1416            403 => 'Forbidden',
1417            404 => 'Not Found',
1418            405 => 'Method Not Allowed',
1419            406 => 'Not Acceptable',
1420            407 => 'Proxy Authentication Required',
1421            408 => 'Request Timeout',
1422            409 => 'Conflict',
1423            410 => 'Gone',
1424            411 => 'Length Required',
1425            412 => 'Precondition Failed',
1426            413 => 'Request Entity Too L…

Large files files are truncated, but you can click here to view the full file