ѡ̳

 找回密码
 ע
搜索
查看: 211|回复: 0
打印 上一主题 下一主题

thinkphp系统的公共函数functions.php

[复制链接]

789

主题

1158

帖子

4197

积分

Ա

Rank: 9Rank: 9Rank: 9

积分
4197
跳转到指定楼层
¥
发表于 2017-11-12 17:14:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


源码
  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. * Think 系统函数库
  13. */

  14. /**
  15. * 获取和设置配置参数 支持批量定义
  16. * @param string|array $name 配置变量
  17. * @param mixed $value 配置值
  18. * @param mixed $default 默认值
  19. * @return mixed
  20. */
  21. function C($name=null, $value=null,$default=null) {
  22.     static $_config = array();
  23.     // 无参数时获取所有
  24.     if (empty($name)) {
  25.         return $_config;
  26.     }
  27.     // 优先执行设置获取或赋值
  28.     if (is_string($name)) {
  29.         if (!strpos($name, '.')) {
  30.             $name = strtoupper($name);
  31.             if (is_null($value))
  32.                 return isset($_config[$name]) ? $_config[$name] : $default;
  33.             $_config[$name] = $value;
  34.             return null;
  35.         }
  36.         // 二维数组设置和获取支持
  37.         $name = explode('.', $name);
  38.         $name[0]   =  strtoupper($name[0]);
  39.         if (is_null($value))
  40.             return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : $default;
  41.         $_config[$name[0]][$name[1]] = $value;
  42.         return null;
  43.     }
  44.     // 批量设置
  45.     if (is_array($name)){
  46.         $_config = array_merge($_config, array_change_key_case($name,CASE_UPPER));
  47.         return null;
  48.     }
  49.     return null; // 避免非法参数
  50. }

  51. /**
  52. * 加载配置文件 支持格式转换 仅支持一级配置
  53. * @param string $file 配置文件名
  54. * @param string $parse 配置解析方法 有些格式需要用户自己解析
  55. * @return array
  56. */
  57. function load_config($file,$parse=CONF_PARSE){
  58.     $ext  = pathinfo($file,PATHINFO_EXTENSION);
  59.     switch($ext){
  60.         case 'php':
  61.             return include $file;
  62.         case 'ini':
  63.             return parse_ini_file($file);
  64.         case 'yaml':
  65.             return yaml_parse_file($file);
  66.         case 'xml':
  67.             return (array)simplexml_load_file($file);
  68.         case 'json':
  69.             return json_decode(file_get_contents($file), true);
  70.         default:
  71.             if(function_exists($parse)){
  72.                 return $parse($file);
  73.             }else{
  74.                 E(L('_NOT_SUPPORT_').':'.$ext);
  75.             }
  76.     }
  77. }

  78. /**
  79. * 解析yaml文件返回一个数组
  80. * @param string $file 配置文件名
  81. * @return array
  82. */
  83. if (!function_exists('yaml_parse_file')) {
  84.     function yaml_parse_file($file) {
  85.         vendor('spyc.Spyc');
  86.         return Spyc::YAMLLoad($file);
  87.     }
  88. }

  89. /**
  90. * 抛出异常处理
  91. * @param string $msg 异常消息
  92. * @param integer $code 异常代码 默认为0
  93. * @throws Think\Exception
  94. * @return void
  95. */
  96. function E($msg, $code=0) {
  97.     throw new Think\Exception($msg, $code);
  98. }

  99. /**
  100. * 记录和统计时间(微秒)和内存使用情况
  101. * 使用方法:
  102. * <code>
  103. * G('begin'); // 记录开始标记位
  104. * // ... 区间运行代码
  105. * G('end'); // 记录结束标签位
  106. * echo G('begin','end',6); // 统计区间运行时间 精确到小数后6位
  107. * echo G('begin','end','m'); // 统计区间内存使用情况
  108. * 如果end标记位没有定义,则会自动以当前作为标记位
  109. * 其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
  110. * </code>
  111. * @param string $start 开始标签
  112. * @param string $end 结束标签
  113. * @param integer|string $dec 小数位或者m
  114. * @return mixed
  115. */
  116. function G($start,$end='',$dec=4) {
  117.     static $_info       =   array();
  118.     static $_mem        =   array();
  119.     if(is_float($end)) { // 记录时间
  120.         $_info[$start]  =   $end;
  121.     }elseif(!empty($end)){ // 统计时间和内存使用
  122.         if(!isset($_info[$end])) $_info[$end]       =  microtime(TRUE);
  123.         if(MEMORY_LIMIT_ON && $dec=='m'){
  124.             if(!isset($_mem[$end])) $_mem[$end]     =  memory_get_usage();
  125.             return number_format(($_mem[$end]-$_mem[$start])/1024);
  126.         }else{
  127.             return number_format(($_info[$end]-$_info[$start]),$dec);
  128.         }

  129.     }else{ // 记录时间和内存使用
  130.         $_info[$start]  =  microtime(TRUE);
  131.         if(MEMORY_LIMIT_ON) $_mem[$start]           =  memory_get_usage();
  132.     }
  133.     return null;
  134. }

  135. /**
  136. * 获取和设置语言定义(不区分大小写)
  137. * @param string|array $name 语言变量
  138. * @param mixed $value 语言值或者变量
  139. * @return mixed
  140. */
  141. function L($name=null, $value=null) {
  142.     static $_lang = array();
  143.     // 空参数返回所有定义
  144.     if (empty($name))
  145.         return $_lang;
  146.     // 判断语言获取(或设置)
  147.     // 若不存在,直接返回全大写$name
  148.     if (is_string($name)) {
  149.         $name   =   strtoupper($name);
  150.         if (is_null($value)){
  151.             return isset($_lang[$name]) ? $_lang[$name] : $name;
  152.         }elseif(is_array($value)){
  153.             // 支持变量
  154.             $replace = array_keys($value);
  155.             foreach($replace as &$v){
  156.                 $v = '{

  157. .$v.'}';
  158.             }
  159.             return str_replace($replace,$value,isset($_lang[$name]) ? $_lang[$name] : $name);        
  160.         }
  161.         $_lang[$name] = $value; // 语言定义
  162.         return null;
  163.     }
  164.     // 批量定义
  165.     if (is_array($name))
  166.         $_lang = array_merge($_lang, array_change_key_case($name, CASE_UPPER));
  167.     return null;
  168. }

  169. /**
  170. * 添加和获取页面Trace记录
  171. * @param string $value 变量
  172. * @param string $label 标签
  173. * @param string $level 日志级别
  174. * @param boolean $record 是否记录日志
  175. * @return void|array
  176. */
  177. function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
  178.     return Think\Think::trace($value,$label,$level,$record);
  179. }

  180. /**
  181. * 编译文件
  182. * @param string $filename 文件名
  183. * @return string
  184. */
  185. function compile($filename) {
  186.     $content    =   php_strip_whitespace($filename);
  187.     $content    =   trim(substr($content, 5));
  188.     // 替换预编译指令
  189.     $content    =   preg_replace('/\/\/\[RUNTIME\](.*?)\/\/\[\/RUNTIME\]/s', '', $content);
  190.     if(0===strpos($content,'namespace')){
  191.         $content    =   preg_replace('/namespace\s(.*?);/','namespace \\1{',$content,1);
  192.     }else{
  193.         $content    =   'namespace {'.$content;
  194.     }
  195.     if ('?>' == substr($content, -2))
  196.         $content    = substr($content, 0, -2);
  197.     return $content.'}';
  198. }

  199. /**
  200. * 获取模版文件 格式 资源://模块@主题/控制器/操作
  201. * @param string $template 模版资源地址
  202. * @param string $layer 视图层(目录)名称
  203. * @return string
  204. */
  205. function T($template='',$layer=''){

  206.     // 解析模版资源地址
  207.     if(false === strpos($template,'://')){
  208.         $template   =   'http://'.str_replace(':', '/',$template);
  209.     }
  210.     $info   =   parse_url($template);
  211.     $file   =   $info['host'].(isset($info['path'])?$info['path']:'');
  212.     $module =   isset($info['user'])?$info['user'].'/':MODULE_NAME.'/';
  213.     $extend =   $info['scheme'];
  214.     $layer  =   $layer?$layer:C('DEFAULT_V_LAYER');

  215.     // 获取当前主题的模版路径
  216.     $auto   =   C('AUTOLOAD_NAMESPACE');
  217.     if($auto && isset($auto[$extend])){ // 扩展资源
  218.         $baseUrl    =   $auto[$extend].$module.$layer.'/';
  219.     }elseif(C('VIEW_PATH')){
  220.         // 改变模块视图目录
  221.         $baseUrl    =   C('VIEW_PATH');
  222.     }elseif(defined('TMPL_PATH')){
  223.         // 指定全局视图目录
  224.         $baseUrl    =   TMPL_PATH.$module;
  225.     }else{
  226.         $baseUrl    =   APP_PATH.$module.$layer.'/';
  227.     }

  228.     // 获取主题
  229.     $theme  =   substr_count($file,'/')<2 ? C('DEFAULT_THEME') : '';

  230.     // 分析模板文件规则
  231.     $depr   =   C('TMPL_FILE_DEPR');
  232.     if('' == $file) {
  233.         // 如果模板文件名为空 按照默认规则定位
  234.         $file = CONTROLLER_NAME . $depr . ACTION_NAME;
  235.     }elseif(false === strpos($file, '/')){
  236.         $file = CONTROLLER_NAME . $depr . $file;
  237.     }elseif('/' != $depr){
  238.         $file   =   substr_count($file,'/')>1 ? substr_replace($file,$depr,strrpos($file,'/'),1) : str_replace('/', $depr, $file);
  239.     }
  240.     return $baseUrl.($theme?$theme.'/':'').$file.C('TMPL_TEMPLATE_SUFFIX');
  241. }

  242. /**
  243. * 获取输入参数 支持过滤和默认值
  244. * 使用方法:
  245. * <code>
  246. * I('id',0); 获取id参数 自动判断get或者post
  247. * I('post.name','','htmlspecialchars'); 获取$_POST['name']
  248. * I('get.'); 获取$_GET
  249. * </code>
  250. * @param string $name 变量的名称 支持指定类型
  251. * @param mixed $default 不存在的时候默认值
  252. * @param mixed $filter 参数过滤方法
  253. * @param mixed $datas 要获取的额外数据源
  254. * @return mixed
  255. */
  256. function I($name,$default='',$filter=null,$datas=null) {
  257.     if(strpos($name,'.')) { // 指定参数来源
  258.         list($method,$name) =   explode('.',$name,2);
  259.     }else{ // 默认为自动判断
  260.         $method =   'param';
  261.     }
  262.     switch(strtolower($method)) {
  263.         case 'get'     :   $input =& $_GET;break;
  264.         case 'post'    :   $input =& $_POST;break;
  265.         case 'put'     :   parse_str(file_get_contents('php://input'), $input);break;
  266.         case 'param'   :
  267.             switch($_SERVER['REQUEST_METHOD']) {
  268.                 case 'POST':
  269.                     $input  =  $_POST;
  270.                     break;
  271.                 case 'PUT':
  272.                     parse_str(file_get_contents('php://input'), $input);
  273.                     break;
  274.                 default:
  275.                     $input  =  $_GET;
  276.             }
  277.             break;
  278.         case 'path'    :   
  279.             $input  =   array();
  280.             if(!empty($_SERVER['PATH_INFO'])){
  281.                 $depr   =   C('URL_PATHINFO_DEPR');
  282.                 $input  =   explode($depr,trim($_SERVER['PATH_INFO'],$depr));            
  283.             }
  284.             break;
  285.         case 'request' :   $input =& $_REQUEST;   break;
  286.         case 'session' :   $input =& $_SESSION;   break;
  287.         case 'cookie'  :   $input =& $_COOKIE;    break;
  288.         case 'server'  :   $input =& $_SERVER;    break;
  289.         case 'globals' :   $input =& $GLOBALS;    break;
  290.         case 'data'    :   $input =& $datas;      break;
  291.         default:
  292.             return NULL;
  293.     }
  294.     if(''==$name) { // 获取全部变量
  295.         $data       =   $input;
  296.         $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');
  297.         if($filters) {
  298.             if(is_string($filters)){
  299.                 $filters    =   explode(',',$filters);
  300.             }
  301.             foreach($filters as $filter){
  302.                 $data   =   array_map_recursive($filter,$data); // 参数过滤
  303.             }
  304.         }
  305.     }elseif(isset($input[$name])) { // 取值操作
  306.         $data       =   $input[$name];
  307.         $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');
  308.         if($filters) {
  309.             if(is_string($filters)){
  310.                 $filters    =   explode(',',$filters);
  311.             }elseif(is_int($filters)){
  312.                 $filters    =   array($filters);
  313.             }
  314.             
  315.             foreach($filters as $filter){
  316.                 if(function_exists($filter)) {
  317.                     $data   =   is_array($data)?array_map_recursive($filter,$data):$filter($data); // 参数过滤
  318.                 }else{
  319.                     $data   =   filter_var($data,is_int($filter)?$filter:filter_id($filter));
  320.                     if(false === $data) {
  321.                         return   isset($default)?$default:NULL;
  322.                     }
  323.                 }
  324.             }
  325.         }
  326.     }else{ // 变量默认值
  327.         $data       =    isset($default)?$default:NULL;
  328.     }
  329.     is_array($data) && array_walk_recursive($data,'think_filter');
  330.     return $data;
  331. }

  332. function array_map_recursive($filter, $data) {
  333.     $result = array();
  334.     foreach ($data as $key => $val) {
  335.         $result[$key] = is_array($val)
  336.          ? array_map_recursive($filter, $val)
  337.          : call_user_func($filter, $val);
  338.     }
  339.     return $result;
  340. }

  341. /**
  342. * 设置和获取统计数据
  343. * 使用方法:
  344. * <code>
  345. * N('db',1); // 记录数据库操作次数
  346. * N('read',1); // 记录读取次数
  347. * echo N('db'); // 获取当前页面数据库的所有操作次数
  348. * echo N('read'); // 获取当前页面读取次数
  349. * </code>
  350. * @param string $key 标识位置
  351. * @param integer $step 步进值
  352. * @param boolean $save 是否保存结果
  353. * @return mixed
  354. */
  355. function N($key, $step=0,$save=false) {
  356.     static $_num    = array();
  357.     if (!isset($_num[$key])) {
  358.         $_num[$key] = (false !== $save)? S('N_'.$key) :  0;
  359.     }
  360.     if (empty($step)){
  361.         return $_num[$key];
  362.     }else{
  363.         $_num[$key] = $_num[$key] + (int)$step;
  364.     }
  365.     if(false !== $save){ // 保存结果
  366.         S('N_'.$key,$_num[$key],$save);
  367.     }
  368.     return null;
  369. }

  370. /**
  371. * 字符串命名风格转换
  372. * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
  373. * @param string $name 字符串
  374. * @param integer $type 转换类型
  375. * @return string
  376. */
  377. function parse_name($name, $type=0) {
  378.     if ($type) {
  379.         return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match){return strtoupper($match[1]);}, $name));
  380.     } else {
  381.         return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
  382.     }
  383. }

  384. /**
  385. * 优化的require_once
  386. * @param string $filename 文件地址
  387. * @return boolean
  388. */
  389. function require_cache($filename) {
  390.     static $_importFiles = array();
  391.     if (!isset($_importFiles[$filename])) {
  392.         if (file_exists_case($filename)) {
  393.             require $filename;
  394.             $_importFiles[$filename] = true;
  395.         } else {
  396.             $_importFiles[$filename] = false;
  397.         }
  398.     }
  399.     return $_importFiles[$filename];
  400. }

  401. /**
  402. * 区分大小写的文件存在判断
  403. * @param string $filename 文件地址
  404. * @return boolean
  405. */
  406. function file_exists_case($filename) {
  407.     if (is_file($filename)) {
  408.         if (IS_WIN && APP_DEBUG) {
  409.             if (basename(realpath($filename)) != basename($filename))
  410.                 return false;
  411.         }
  412.         return true;
  413.     }
  414.     return false;
  415. }

  416. /**
  417. * 导入所需的类库 同java的Import 本函数有缓存功能
  418. * @param string $class 类库命名空间字符串
  419. * @param string $baseUrl 起始路径
  420. * @param string $ext 导入的文件扩展名
  421. * @return boolean
  422. */
  423. function import($class, $baseUrl = '', $ext=EXT) {
  424.     static $_file = array();
  425.     $class = str_replace(array('.', '#'), array('/', '.'), $class);
  426.     if (isset($_file[$class . $baseUrl]))
  427.         return true;
  428.     else
  429.         $_file[$class . $baseUrl] = true;
  430.     $class_strut     = explode('/', $class);
  431.     if (empty($baseUrl)) {
  432.         if ('@' == $class_strut[0] || MODULE_NAME == $class_strut[0]) {
  433.             //加载当前模块的类库
  434.             $baseUrl = MODULE_PATH;
  435.             $class   = substr_replace($class, '', 0, strlen($class_strut[0]) + 1);
  436.         }elseif ('Common' == $class_strut[0]) {
  437.             //加载公共模块的类库
  438.             $baseUrl = COMMON_PATH;
  439.             $class   = substr($class, 7);
  440.         }elseif (in_array($class_strut[0],array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$class_strut[0])) {
  441.             // 系统类库包和第三方类库包
  442.             $baseUrl = LIB_PATH;
  443.         }else { // 加载其他模块的类库
  444.             $baseUrl = APP_PATH;
  445.         }
  446.     }
  447.     if (substr($baseUrl, -1) != '/')
  448.         $baseUrl    .= '/';
  449.     $classfile       = $baseUrl . $class . $ext;
  450.     if (!class_exists(basename($class),false)) {
  451.         // 如果类不存在 则导入类库文件
  452.         return require_cache($classfile);
  453.     }
  454.     return null;
  455. }

  456. /**
  457. * 基于命名空间方式导入函数库
  458. * load('@.Util.Array')
  459. * @param string $name 函数库命名空间字符串
  460. * @param string $baseUrl 起始路径
  461. * @param string $ext 导入的文件扩展名
  462. * @return void
  463. */
  464. function load($name, $baseUrl='', $ext='.php') {
  465.     $name = str_replace(array('.', '#'), array('/', '.'), $name);
  466.     if (empty($baseUrl)) {
  467.         if (0 === strpos($name, '@/')) {//加载当前模块函数库
  468.             $baseUrl    =   MODULE_PATH.'Common/';
  469.             $name       =   substr($name, 2);
  470.         } else { //加载其他模块函数库
  471.             $array      =   explode('/', $name);
  472.             $baseUrl    =   APP_PATH . array_shift($array).'/Common/';
  473.             $name       =   implode('/',$array);
  474.         }
  475.     }
  476.     if (substr($baseUrl, -1) != '/')
  477.         $baseUrl       .= '/';
  478.     require_cache($baseUrl . $name . $ext);
  479. }

  480. /**
  481. * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
  482. * @param string $class 类库
  483. * @param string $baseUrl 基础目录
  484. * @param string $ext 类库后缀
  485. * @return boolean
  486. */
  487. function vendor($class, $baseUrl = '', $ext='.php') {
  488.     if (empty($baseUrl))
  489.         $baseUrl = VENDOR_PATH;
  490.     return import($class, $baseUrl, $ext);
  491. }

  492. /**
  493. * 实例化模型类 格式 [资源://][模块/]模型
  494. * @param string $name 资源地址
  495. * @param string $layer 模型层名称
  496. * @return Think\Model
  497. */
  498. function D($name='',$layer='') {
  499.     if(empty($name)) return new Think\Model;
  500.     static $_model  =   array();
  501.     $layer          =   $layer? : C('DEFAULT_M_LAYER');
  502.     if(isset($_model[$name.$layer]))
  503.         return $_model[$name.$layer];
  504.     $class          =   parse_res_name($name,$layer);
  505.     if(class_exists($class)) {
  506.         $model      =   new $class(basename($name));
  507.     }elseif(false === strpos($name,'/')){
  508.         // 自动加载公共模块下面的模型
  509.         if(!C('APP_USE_NAMESPACE')){
  510.             import('Common/'.$layer.'/'.$class);
  511.         }else{
  512.             $class      =   '\\Common\\'.$layer.'\\'.$name.$layer;
  513.         }
  514.         $model      =   class_exists($class)? new $class($name) : new Think\Model($name);
  515.     }else {
  516.         Think\Log::record('D方法实例化没找到模型类'.$class,Think\Log::NOTICE);
  517.         $model      =   new Think\Model(basename($name));
  518.     }
  519.     $_model[$name.$layer]  =  $model;
  520.     return $model;
  521. }

  522. /**
  523. * 实例化一个没有模型文件的Model
  524. * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User
  525. * @param string $tablePrefix 表前缀
  526. * @param mixed $connection 数据库连接信息
  527. * @return Think\Model
  528. */
  529. function M($name='', $tablePrefix='',$connection='') {
  530.     static $_model  = array();
  531.     if(strpos($name,':')) {
  532.         list($class,$name)    =  explode(':',$name);
  533.     }else{
  534.         $class      =   'Think\\Model';
  535.     }
  536.     $guid           =   (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
  537.     if (!isset($_model[$guid]))
  538.         $_model[$guid] = new $class($name,$tablePrefix,$connection);
  539.     return $_model[$guid];
  540. }

  541. /**
  542. * 解析资源地址并导入类库文件
  543. * 例如 module/controller addon://module/behavior
  544. * @param string $name 资源地址 格式:[扩展://][模块/]资源名
  545. * @param string $layer 分层名称
  546. * @param integer $level 控制器层次
  547. * @return string
  548. */
  549. function parse_res_name($name,$layer,$level=1){
  550.     if(strpos($name,'://')) {// 指定扩展资源
  551.         list($extend,$name)  =   explode('://',$name);
  552.     }else{
  553.         $extend  =   '';
  554.     }
  555.     if(strpos($name,'/') && substr_count($name, '/')>=$level){ // 指定模块
  556.         list($module,$name) =  explode('/',$name,2);
  557.     }else{
  558.         $module =   defined('MODULE_NAME') ? MODULE_NAME : '' ;
  559.     }
  560.     $array  =   explode('/',$name);
  561.     if(!C('APP_USE_NAMESPACE')){
  562.         $class  =   parse_name($name, 1);
  563.         import($module.'/'.$layer.'/'.$class.$layer);
  564.     }else{
  565.         $class  =   $module.'\\'.$layer;
  566.         foreach($array as $name){
  567.             $class  .=   '\\'.parse_name($name, 1);
  568.         }
  569.         // 导入资源类库
  570.         if($extend){ // 扩展资源
  571.             $class      =   $extend.'\\'.$class;
  572.         }
  573.     }
  574.     return $class.$layer;
  575. }

  576. /**
  577. * 用于实例化访问控制器
  578. * @param string $name 控制器名
  579. * @param string $path 控制器命名空间(路径)
  580. * @return Think\Controller|false
  581. */
  582. function controller($name,$path=''){
  583.     $layer  =   C('DEFAULT_C_LAYER');
  584.     if(!C('APP_USE_NAMESPACE')){
  585.         $class  =   parse_name($name, 1).$layer;
  586.         import(MODULE_NAME.'/'.$layer.'/'.$class);
  587.     }else{
  588.         $class  =   ( $path ? basename(ADDON_PATH).'\\'.$path : MODULE_NAME ).'\\'.$layer;
  589.         $array  =   explode('/',$name);
  590.         foreach($array as $name){
  591.             $class  .=   '\\'.parse_name($name, 1);
  592.         }
  593.         $class .=   $layer;
  594.     }
  595.     if(class_exists($class)) {
  596.         return new $class();
  597.     }else {
  598.         return false;
  599.     }
  600. }

  601. /**
  602. * 实例化多层控制器 格式:[资源://][模块/]控制器
  603. * @param string $name 资源地址
  604. * @param string $layer 控制层名称
  605. * @param integer $level 控制器层次
  606. * @return Think\Controller|false
  607. */
  608. function A($name,$layer='',$level=0) {
  609.     static $_action = array();
  610.     $layer  =   $layer? : C('DEFAULT_C_LAYER');
  611.     $level  =   $level? : ($layer == C('DEFAULT_C_LAYER')?C('CONTROLLER_LEVEL'):1);
  612.     if(isset($_action[$name.$layer]))
  613.         return $_action[$name.$layer];
  614.    
  615.     $class  =   parse_res_name($name,$layer,$level);
  616.     if(class_exists($class)) {
  617.         $action             =   new $class();
  618.         $_action[$name.$layer]     =   $action;
  619.         return $action;
  620.     }else {
  621.         return false;
  622.     }
  623. }


  624. /**
  625. * 远程调用控制器的操作方法 URL 参数格式 [资源://][模块/]控制器/操作
  626. * @param string $url 调用地址
  627. * @param string|array $vars 调用参数 支持字符串和数组
  628. * @param string $layer 要调用的控制层名称
  629. * @return mixed
  630. */
  631. function R($url,$vars=array(),$layer='') {
  632.     $info   =   pathinfo($url);
  633.     $action =   $info['basename'];
  634.     $module =   $info['dirname'];
  635.     $class  =   A($module,$layer);
  636.     if($class){
  637.         if(is_string($vars)) {
  638.             parse_str($vars,$vars);
  639.         }
  640.         return call_user_func_array(array(&$class,$action.C('ACTION_SUFFIX')),$vars);
  641.     }else{
  642.         return false;
  643.     }
  644. }

  645. /**
  646. * 处理标签扩展
  647. * @param string $tag 标签名称
  648. * @param mixed $params 传入参数
  649. * @return void
  650. */
  651. function tag($tag, &$params=NULL) {
  652.     \Think\Hook::listen($tag,$params);
  653. }

  654. /**
  655. * 执行某个行为
  656. * @param string $name 行为名称
  657. * @param string $tag 标签名称(行为类无需传入)
  658. * @param Mixed $params 传入的参数
  659. * @return void
  660. */
  661. function B($name, $tag='',&$params=NULL) {
  662.     if(''==$tag){
  663.         $name   .=  'Behavior';
  664.     }
  665.     \Think\Hook::exec($name,$tag,$params);
  666. }

  667. /**
  668. * 去除代码中的空白和注释
  669. * @param string $content 代码内容
  670. * @return string
  671. */
  672. function strip_whitespace($content) {
  673.     $stripStr   = '';
  674.     //分析php源码
  675.     $tokens     = token_get_all($content);
  676.     $last_space = false;
  677.     for ($i = 0, $j = count($tokens); $i < $j; $i++) {
  678.         if (is_string($tokens[$i])) {
  679.             $last_space = false;
  680.             $stripStr  .= $tokens[$i];
  681.         } else {
  682.             switch ($tokens[$i][0]) {
  683.                 //过滤各种PHP注释
  684.                 case T_COMMENT:
  685.                 case T_DOC_COMMENT:
  686.                     break;
  687.                 //过滤空格
  688.                 case T_WHITESPACE:
  689.                     if (!$last_space) {
  690.                         $stripStr  .= ' ';
  691.                         $last_space = true;
  692.                     }
  693.                     break;
  694.                 case T_START_HEREDOC:
  695.                     $stripStr .= "<<<THINK\n";
  696.                     break;
  697.                 case T_END_HEREDOC:
  698.                     $stripStr .= "THINK;\n";
  699.                     for($k = $i+1; $k < $j; $k++) {
  700.                         if(is_string($tokens[$k]) && $tokens[$k] == ';') {
  701.                             $i = $k;
  702.                             break;
  703.                         } else if($tokens[$k][0] == T_CLOSE_TAG) {
  704.                             break;
  705.                         }
  706.                     }
  707.                     break;
  708.                 default:
  709.                     $last_space = false;
  710.                     $stripStr  .= $tokens[$i][1];
  711.             }
  712.         }
  713.     }
  714.     return $stripStr;
  715. }

  716. /**
  717. * 自定义异常处理
  718. * @param string $msg 异常消息
  719. * @param string $type 异常类型 默认为Think\Exception
  720. * @param integer $code 异常代码 默认为0
  721. * @return void
  722. */
  723. function throw_exception($msg, $type='Think\\Exception', $code=0) {
  724.     Think\Log::record('建议使用E方法替代throw_exception',Think\Log::NOTICE);
  725.     if (class_exists($type, false))
  726.         throw new $type($msg, $code);
  727.     else
  728.         Think\Think::halt($msg);        // 异常类型不存在则输出错误信息字串
  729. }

  730. /**
  731. * 浏览器友好的变量输出
  732. * @param mixed $var 变量
  733. * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
  734. * @param string $label 标签 默认为空
  735. * @param boolean $strict 是否严谨 默认为true
  736. * @return void|string
  737. */
  738. function dump($var, $echo=true, $label=null, $strict=true) {
  739.     $label = ($label === null) ? '' : rtrim($label) . ' ';
  740.     if (!$strict) {
  741.         if (ini_get('html_errors')) {
  742.             $output = print_r($var, true);
  743.             $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
  744.         } else {
  745.             $output = $label . print_r($var, true);
  746.         }
  747.     } else {
  748.         ob_start();
  749.         var_dump($var);
  750.         $output = ob_get_clean();
  751.         if (!extension_loaded('xdebug')) {
  752.             $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
  753.             $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
  754.         }
  755.     }
  756.     if ($echo) {
  757.         echo($output);
  758.         return null;
  759.     }else
  760.         return $output;
  761. }

  762. /**
  763. * 设置当前页面的布局
  764. * @param string|false $layout 布局名称 为false的时候表示关闭布局
  765. * @return void
  766. */
  767. function layout($layout) {
  768.     if(false !== $layout) {
  769.         // 开启布局
  770.         C('LAYOUT_ON',true);
  771.         if(is_string($layout)) { // 设置新的布局模板
  772.             C('LAYOUT_NAME',$layout);
  773.         }
  774.     }else{// 临时关闭布局
  775.         C('LAYOUT_ON',false);
  776.     }
  777. }

  778. /**
  779. * URL组装 支持不同URL模式
  780. * @param string $url URL表达式,格式:'[模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2...'
  781. * @param string|array $vars 传入的参数,支持数组和字符串
  782. * @param string|boolean $suffix 伪静态后缀,默认为true表示获取配置值
  783. * @param boolean $domain 是否显示域名
  784. * @return string
  785. */
  786. function U($url='',$vars='',$suffix=true,$domain=false) {
  787.     // 解析URL
  788.     $info   =  parse_url($url);
  789.     $url    =  !empty($info['path'])?$info['path']:ACTION_NAME;
  790.     if(isset($info['fragment'])) { // 解析锚点
  791.         $anchor =   $info['fragment'];
  792.         if(false !== strpos($anchor,'?')) { // 解析参数
  793.             list($anchor,$info['query']) = explode('?',$anchor,2);
  794.         }        
  795.         if(false !== strpos($anchor,'@')) { // 解析域名
  796.             list($anchor,$host)    =   explode('@',$anchor, 2);
  797.         }
  798.     }elseif(false !== strpos($url,'@')) { // 解析域名
  799.         list($url,$host)    =   explode('@',$info['path'], 2);
  800.     }
  801.     // 解析子域名
  802.     if(isset($host)) {
  803.         $domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.'));
  804.     }elseif($domain===true){
  805.         $domain = $_SERVER['HTTP_HOST'];
  806.         if(C('APP_SUB_DOMAIN_DEPLOY') ) { // 开启子域名部署
  807.             $domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.');
  808.             // '子域名'=>array('模块[/控制器]');
  809.             foreach (C('APP_SUB_DOMAIN_RULES') as $key => $rule) {
  810.                 $rule   =   is_array($rule)?$rule[0]:$rule;
  811.                 if(false === strpos($key,'*') && 0=== strpos($url,$rule)) {
  812.                     $domain = $key.strstr($domain,'.'); // 生成对应子域名
  813.                     $url    =  substr_replace($url,'',0,strlen($rule));
  814.                     break;
  815.                 }
  816.             }
  817.         }
  818.     }

  819.     // 解析参数
  820.     if(is_string($vars)) { // aaa=1&bbb=2 转换成数组
  821.         parse_str($vars,$vars);
  822.     }elseif(!is_array($vars)){
  823.         $vars = array();
  824.     }
  825.     if(isset($info['query'])) { // 解析地址里面参数 合并到vars
  826.         parse_str($info['query'],$params);
  827.         $vars = array_merge($params,$vars);
  828.     }
  829.    
  830.     // URL组装
  831.     $depr       =   C('URL_PATHINFO_DEPR');
  832.     $urlCase    =   C('URL_CASE_INSENSITIVE');
  833.     if($url) {
  834.         if(0=== strpos($url,'/')) {// 定义路由
  835.             $route      =   true;
  836.             $url        =   substr($url,1);
  837.             if('/' != $depr) {
  838.                 $url    =   str_replace('/',$depr,$url);
  839.             }
  840.         }else{
  841.             if('/' != $depr) { // 安全替换
  842.                 $url    =   str_replace('/',$depr,$url);
  843.             }
  844.             // 解析模块、控制器和操作
  845.             $url        =   trim($url,$depr);
  846.             $path       =   explode($depr,$url);
  847.             $var        =   array();
  848.             $varModule      =   C('VAR_MODULE');
  849.             $varController  =   C('VAR_CONTROLLER');
  850.             $varAction      =   C('VAR_ACTION');
  851.             $var[$varAction]       =   !empty($path)?array_pop($path):ACTION_NAME;
  852.             $var[$varController]   =   !empty($path)?array_pop($path):CONTROLLER_NAME;
  853.             if($maps = C('URL_ACTION_MAP')) {
  854.                 if(isset($maps[strtolower($var[$varController])])) {
  855.                     $maps    =   $maps[strtolower($var[$varController])];
  856.                     if($action = array_search(strtolower($var[$varAction]),$maps)){
  857.                         $var[$varAction] = $action;
  858.                     }
  859.                 }
  860.             }
  861.             if($maps = C('URL_CONTROLLER_MAP')) {
  862.                 if($controller = array_search(strtolower($var[$varController]),$maps)){
  863.                     $var[$varController] = $controller;
  864.                 }
  865.             }
  866.             if($urlCase) {
  867.                 $var[$varController]   =   parse_name($var[$varController]);
  868.             }
  869.             $module =   '';
  870.             
  871.             if(!empty($path)) {
  872.                 $var[$varModule]    =   implode($depr,$path);
  873.             }else{
  874.                 if(C('MULTI_MODULE')) {
  875.                     if(MODULE_NAME != C('DEFAULT_MODULE') || !C('MODULE_ALLOW_LIST')){
  876.                         $var[$varModule]=   MODULE_NAME;
  877.                     }
  878.                 }
  879.             }
  880.             if($maps = C('URL_MODULE_MAP')) {
  881.                 if($_module = array_search(strtolower($var[$varModule]),$maps)){
  882.                     $var[$varModule] = $_module;
  883.                 }
  884.             }
  885.             if(isset($var[$varModule])){
  886.                 $module =   $var[$varModule];
  887.                 unset($var[$varModule]);
  888.             }
  889.             
  890.         }
  891.     }

  892.     if(C('URL_MODEL') == 0) { // 普通模式URL转换
  893.         $url        =   __APP__.'?'.C('VAR_MODULE')."={$module}&".http_build_query(array_reverse($var));
  894.         if($urlCase){
  895.             $url    =   strtolower($url);
  896.         }        
  897.         if(!empty($vars)) {
  898.             $vars   =   http_build_query($vars);
  899.             $url   .=   '&'.$vars;
  900.         }
  901.     }else{ // PATHINFO模式或者兼容URL模式
  902.         if(isset($route)) {
  903.             $url    =   __APP__.'/'.rtrim($url,$depr);
  904.         }else{
  905.             $module =   (defined('BIND_MODULE') && BIND_MODULE==$module )? '' : $module;
  906.             $url    =   __APP__.'/'.($module?$module.MODULE_PATHINFO_DEPR:'').implode($depr,array_reverse($var));
  907.         }
  908.         if($urlCase){
  909.             $url    =   strtolower($url);
  910.         }
  911.         if(!empty($vars)) { // 添加参数
  912.             foreach ($vars as $var => $val){
  913.                 if('' !== trim($val))   $url .= $depr . $var . $depr . urlencode($val);
  914.             }               
  915.         }
  916.         if($suffix) {
  917.             $suffix   =  $suffix===true?C('URL_HTML_SUFFIX'):$suffix;
  918.             if($pos = strpos($suffix, '|')){
  919.                 $suffix = substr($suffix, 0, $pos);
  920.             }
  921.             if($suffix && '/' != substr($url,-1)){
  922.                 $url  .=  '.'.ltrim($suffix,'.');
  923.             }
  924.         }
  925.     }
  926.     if(isset($anchor)){
  927.         $url  .= '#'.$anchor;
  928.     }
  929.     if($domain) {
  930.         $url   =  (is_ssl()?'https://':'http://').$domain.$url;
  931.     }
  932.     return $url;
  933. }

  934. /**
  935. * 渲染输出Widget
  936. * @param string $name Widget名称
  937. * @param array $data 传入的参数
  938. * @return void
  939. */
  940. function W($name, $data=array()) {
  941.     R($name,$data,'Widget');
  942. }

  943. /**
  944. * 判断是否SSL协议
  945. * @return boolean
  946. */
  947. function is_ssl() {
  948.     if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){
  949.         return true;
  950.     }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
  951.         return true;
  952.     }
  953.     return false;
  954. }

  955. /**
  956. * URL重定向
  957. * @param string $url 重定向的URL地址
  958. * @param integer $time 重定向的等待时间(秒)
  959. * @param string $msg 重定向前的提示信息
  960. * @return void
  961. */
  962. function redirect($url, $time=0, $msg='') {
  963.     //多行URL地址支持
  964.     $url        = str_replace(array("\n", "\r"), '', $url);
  965.     if (empty($msg))
  966.         $msg    = "系统将在{$time}秒之后自动跳转到{$url}!";
  967.     if (!headers_sent()) {
  968.         // redirect
  969.         if (0 === $time) {
  970.             header('Location: ' . $url);
  971.         } else {
  972.             header("refresh:{$time};url={$url}");
  973.             echo($msg);
  974.         }
  975.         exit();
  976.     } else {
  977.         $str    = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
  978.         if ($time != 0)
  979.             $str .= $msg;
  980.         exit($str);
  981.     }
  982. }

  983. /**
  984. * 缓存管理
  985. * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
  986. * @param mixed $value 缓存值
  987. * @param mixed $options 缓存参数
  988. * @return mixed
  989. */
  990. function S($name,$value='',$options=null) {
  991.     static $cache   =   '';
  992.     if(is_array($options) && empty($cache)){
  993.         // 缓存操作的同时初始化
  994.         $type       =   isset($options['type'])?$options['type']:'';
  995.         $cache      =   Think\Cache::getInstance($type,$options);
  996.     }elseif(is_array($name)) { // 缓存初始化
  997.         $type       =   isset($name['type'])?$name['type']:'';
  998.         $cache      =   Think\Cache::getInstance($type,$name);
  999.         return $cache;
  1000.     }elseif(empty($cache)) { // 自动初始化
  1001.         $cache      =   Think\Cache::getInstance();
  1002.     }
  1003.     if(''=== $value){ // 获取缓存
  1004.         return $cache->get($name);
  1005.     }elseif(is_null($value)) { // 删除缓存
  1006.         return $cache->rm($name);
  1007.     }else { // 缓存数据
  1008.         if(is_array($options)) {
  1009.             $expire     =   isset($options['expire'])?$options['expire']:NULL;
  1010.         }else{
  1011.             $expire     =   is_numeric($options)?$options:NULL;
  1012.         }
  1013.         return $cache->set($name, $value, $expire);
  1014.     }
  1015. }

  1016. /**
  1017. * 快速文件数据读取和保存 针对简单类型数据 字符串、数组
  1018. * @param string $name 缓存名称
  1019. * @param mixed $value 缓存值
  1020. * @param string $path 缓存路径
  1021. * @return mixed
  1022. */
  1023. function F($name, $value='', $path=DATA_PATH) {
  1024.     static $_cache  =   array();
  1025.     $filename       =   $path . $name . '.php';
  1026.     if ('' !== $value) {
  1027.         if (is_null($value)) {
  1028.             // 删除缓存
  1029.             if(false !== strpos($name,'*')){
  1030.                 return false; // TODO
  1031.             }else{
  1032.                 unset($_cache[$name]);
  1033.                 return Think\Storage::unlink($filename,'F');
  1034.             }
  1035.         } else {
  1036.             Think\Storage::put($filename,serialize($value),'F');
  1037.             // 缓存数据
  1038.             $_cache[$name]  =   $value;
  1039.             return null;
  1040.         }
  1041.     }
  1042.     // 获取缓存数据
  1043.     if (isset($_cache[$name]))
  1044.         return $_cache[$name];
  1045.     if (Think\Storage::has($filename,'F')){
  1046.         $value      =   unserialize(Think\Storage::read($filename,'F'));
  1047.         $_cache[$name]  =   $value;
  1048.     } else {
  1049.         $value          =   false;
  1050.     }
  1051.     return $value;
  1052. }

  1053. /**
  1054. * 根据PHP各种类型变量生成唯一标识号
  1055. * @param mixed $mix 变量
  1056. * @return string
  1057. */
  1058. function to_guid_string($mix) {
  1059.     if (is_object($mix)) {
  1060.         return spl_object_hash($mix);
  1061.     } elseif (is_resource($mix)) {
  1062.         $mix = get_resource_type($mix) . strval($mix);
  1063.     } else {
  1064.         $mix = serialize($mix);
  1065.     }
  1066.     return md5($mix);
  1067. }

  1068. /**
  1069. * XML编码
  1070. * @param mixed $data 数据
  1071. * @param string $root 根节点名
  1072. * @param string $item 数字索引的子节点名
  1073. * @param string $attr 根节点属性
  1074. * @param string $id   数字索引子节点key转换的属性名
  1075. * @param string $encoding 数据编码
  1076. * @return string
  1077. */
  1078. function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
  1079.     if(is_array($attr)){
  1080.         $_attr = array();
  1081.         foreach ($attr as $key => $value) {
  1082.             $_attr[] = "{$key}="{$value}"";
  1083.         }
  1084.         $attr = implode(' ', $_attr);
  1085.     }
  1086.     $attr   = trim($attr);
  1087.     $attr   = empty($attr) ? '' : " {$attr}";
  1088.     $xml    = "<?xml version="1.0" encoding="{$encoding}"?>";
  1089.     $xml   .= "<{$root}{$attr}>";
  1090.     $xml   .= data_to_xml($data, $item, $id);
  1091.     $xml   .= "</{$root}>";
  1092.     return $xml;
  1093. }

  1094. /**
  1095. * 数据XML编码
  1096. * @param mixed  $data 数据
  1097. * @param string $item 数字索引时的节点名称
  1098. * @param string $id   数字索引key转换为的属性名
  1099. * @return string
  1100. */
  1101. function data_to_xml($data, $item='item', $id='id') {
  1102.     $xml = $attr = '';
  1103.     foreach ($data as $key => $val) {
  1104.         if(is_numeric($key)){
  1105.             $id && $attr = " {$id}="{$key}"";
  1106.             $key  = $item;
  1107.         }
  1108.         $xml    .=  "<{$key}{$attr}>";
  1109.         $xml    .=  (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
  1110.         $xml    .=  "</{$key}>";
  1111.     }
  1112.     return $xml;
  1113. }

  1114. /**
  1115. * session管理函数
  1116. * @param string|array $name session名称 如果为数组则表示进行session设置
  1117. * @param mixed $value session值
  1118. * @return mixed
  1119. */
  1120. function session($name='',$value='') {
  1121.     $prefix   =  C('SESSION_PREFIX');
  1122.     if(is_array($name)) { // session初始化 在session_start 之前调用
  1123.         if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
  1124.         if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
  1125.             session_id($_REQUEST[C('VAR_SESSION_ID')]);
  1126.         }elseif(isset($name['id'])) {
  1127.             session_id($name['id']);
  1128.         }
  1129.         if('common' != APP_MODE){ // 其它模式可能不支持
  1130.             ini_set('session.auto_start', 0);
  1131.         }
  1132.         if(isset($name['name']))            session_name($name['name']);
  1133.         if(isset($name['path']))            session_save_path($name['path']);
  1134.         if(isset($name['domain']))          ini_set('session.cookie_domain', $name['domain']);
  1135.         if(isset($name['expire']))          ini_set('session.gc_maxlifetime', $name['expire']);
  1136.         if(isset($name['use_trans_sid']))   ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
  1137.         if(isset($name['use_cookies']))     ini_set('session.use_cookies', $name['use_cookies']?1:0);
  1138.         if(isset($name['cache_limiter']))   session_cache_limiter($name['cache_limiter']);
  1139.         if(isset($name['cache_expire']))    session_cache_expire($name['cache_expire']);
  1140.         if(isset($name['type']))            C('SESSION_TYPE',$name['type']);
  1141.         if(C('SESSION_TYPE')) { // 读取session驱动
  1142.             $type   =   C('SESSION_TYPE');
  1143.             $class  =   strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
  1144.             $hander =   new $class();
  1145.             session_set_save_handler(
  1146.                 array(&$hander,"open"),
  1147.                 array(&$hander,"close"),
  1148.                 array(&$hander,"read"),
  1149.                 array(&$hander,"write"),
  1150.                 array(&$hander,"destroy"),
  1151.                 array(&$hander,"gc"));
  1152.         }
  1153.         // 启动session
  1154.         if(C('SESSION_AUTO_START'))  session_start();
  1155.     }elseif('' === $value){
  1156.         if(''===$name){
  1157.             // 获取全部的session
  1158.             return $prefix ? $_SESSION[$prefix] : $_SESSION;
  1159.         }elseif(0===strpos($name,'[')) { // session 操作
  1160.             if('[pause]'==$name){ // 暂停session
  1161.                 session_write_close();
  1162.             }elseif('[start]'==$name){ // 启动session
  1163.                 session_start();
  1164.             }elseif('[destroy]'==$name){ // 销毁session
  1165.                 $_SESSION =  array();
  1166.                 session_unset();
  1167.                 session_destroy();
  1168.             }elseif('[regenerate]'==$name){ // 重新生成id
  1169.                 session_regenerate_id();
  1170.             }
  1171.         }elseif(0===strpos($name,'?')){ // 检查session
  1172.             $name   =  substr($name,1);
  1173.             if(strpos($name,'.')){ // 支持数组
  1174.                 list($name1,$name2) =   explode('.',$name);
  1175.                 return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
  1176.             }else{
  1177.                 return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
  1178.             }
  1179.         }elseif(is_null($name)){ // 清空session
  1180.             if($prefix) {
  1181.                 unset($_SESSION[$prefix]);
  1182.             }else{
  1183.                 $_SESSION = array();
  1184.             }
  1185.         }elseif($prefix){ // 获取session
  1186.             if(strpos($name,'.')){
  1187.                 list($name1,$name2) =   explode('.',$name);
  1188.                 return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;  
  1189.             }else{
  1190.                 return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;               
  1191.             }            
  1192.         }else{
  1193.             if(strpos($name,'.')){
  1194.                 list($name1,$name2) =   explode('.',$name);
  1195.                 return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;  
  1196.             }else{
  1197.                 return isset($_SESSION[$name])?$_SESSION[$name]:null;
  1198.             }            
  1199.         }
  1200.     }elseif(is_null($value)){ // 删除session
  1201.         if(strpos($name,'.')){
  1202.             list($name1,$name2) =   explode('.',$name);
  1203.             if($prefix){
  1204.                 unset($_SESSION[$prefix][$name1][$name2]);
  1205.             }else{
  1206.                 unset($_SESSION[$name1][$name2]);
  1207.             }
  1208.         }else{
  1209.             if($prefix){
  1210.                 unset($_SESSION[$prefix][$name]);
  1211.             }else{
  1212.                 unset($_SESSION[$name]);
  1213.             }
  1214.         }
  1215.     }else{ // 设置session
  1216.         if($prefix){
  1217.             if (!isset($_SESSION[$prefix])) {
  1218.                 $_SESSION[$prefix] = array();
  1219.             }
  1220.             $_SESSION[$prefix][$name]   =  $value;
  1221.         }else{
  1222.             $_SESSION[$name]  =  $value;
  1223.         }
  1224.     }
  1225.     return null;
  1226. }

  1227. /**
  1228. * Cookie 设置、获取、删除
  1229. * @param string $name cookie名称
  1230. * @param mixed $value cookie值
  1231. * @param mixed $option cookie参数
  1232. * @return mixed
  1233. */
  1234. function cookie($name='', $value='', $option=null) {
  1235.     // 默认设置
  1236.     $config = array(
  1237.         'prefix'    =>  C('COOKIE_PREFIX'), // cookie 名称前缀
  1238.         'expire'    =>  C('COOKIE_EXPIRE'), // cookie 保存时间
  1239.         'path'      =>  C('COOKIE_PATH'), // cookie 保存路径
  1240.         'domain'    =>  C('COOKIE_DOMAIN'), // cookie 有效域名
  1241.         'secure'    =>  C('COOKIE_SECURE'), //  cookie 启用安全传输
  1242.         'httponly'  =>  C('COOKIE_HTTPONLY'), // httponly设置
  1243.     );
  1244.     // 参数设置(会覆盖黙认设置)
  1245.     if (!is_null($option)) {
  1246.         if (is_numeric($option))
  1247.             $option = array('expire' => $option);
  1248.         elseif (is_string($option))
  1249.             parse_str($option, $option);
  1250.         $config     = array_merge($config, array_change_key_case($option));
  1251.     }
  1252.     if(!empty($config['httponly'])){
  1253.         ini_set("session.cookie_httponly", 1);
  1254.     }
  1255.     // 清除指定前缀的所有cookie
  1256.     if (is_null($name)) {
  1257.         if (empty($_COOKIE))
  1258.             return null;
  1259.         // 要删除的cookie前缀,不指定则删除config设置的指定前缀
  1260.         $prefix = empty($value) ? $config['prefix'] : $value;
  1261.         if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
  1262.             foreach ($_COOKIE as $key => $val) {
  1263.                 if (0 === stripos($key, $prefix)) {
  1264.                     setcookie($key, '', time() - 3600, $config['path'], $config['domain'],$config['secure'],$config['httponly']);
  1265.                     unset($_COOKIE[$key]);
  1266.                 }
  1267.             }
  1268.         }
  1269.         return null;
  1270.     }elseif('' === $name){
  1271.         // 获取全部的cookie
  1272.         return $_COOKIE;
  1273.     }
  1274.     $name = $config['prefix'] . str_replace('.', '_', $name);
  1275.     if ('' === $value) {
  1276.         if(isset($_COOKIE[$name])){
  1277.             $value =    $_COOKIE[$name];
  1278.             if(0===strpos($value,'think:')){
  1279.                 $value  =   substr($value,6);
  1280.                 return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
  1281.             }else{
  1282.                 return $value;
  1283.             }
  1284.         }else{
  1285.             return null;
  1286.         }
  1287.     } else {
  1288.         if (is_null($value)) {
  1289.             setcookie($name, '', time() - 3600, $config['path'], $config['domain'],$config['secure'],$config['httponly']);
  1290.             unset($_COOKIE[$name]); // 删除指定cookie
  1291.         } else {
  1292.             // 设置cookie
  1293.             if(is_array($value)){
  1294.                 $value  = 'think:'.json_encode(array_map('urlencode',$value));
  1295.             }
  1296.             $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
  1297.             setcookie($name, $value, $expire, $config['path'], $config['domain'],$config['secure'],$config['httponly']);
  1298.             $_COOKIE[$name] = $value;
  1299.         }
  1300.     }
  1301.     return null;
  1302. }

  1303. /**
  1304. * 加载动态扩展文件
  1305. * @var string $path 文件路径
  1306. * @return void
  1307. */
  1308. function load_ext_file($path) {
  1309.     // 加载自定义外部文件
  1310.     if($files = C('LOAD_EXT_FILE')) {
  1311.         $files      =  explode(',',$files);
  1312.         foreach ($files as $file){
  1313.             $file   = $path.'Common/'.$file.'.php';
  1314.             if(is_file($file)) include $file;
  1315.         }
  1316.     }
  1317.     // 加载自定义的动态配置文件
  1318.     if($configs = C('LOAD_EXT_CONFIG')) {
  1319.         if(is_string($configs)) $configs =  explode(',',$configs);
  1320.         foreach ($configs as $key=>$config){
  1321.             $file   = is_file($config)? $config : $path.'Conf/'.$config.CONF_EXT;
  1322.             if(is_file($file)) {
  1323.                 is_numeric($key)?C(load_config($file)):C($key,load_config($file));
  1324.             }
  1325.         }
  1326.     }
  1327. }

  1328. /**
  1329. * 获取客户端IP地址
  1330. * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
  1331. * @param boolean $adv 是否进行高级模式获取(有可能被伪装)
  1332. * @return mixed
  1333. */
  1334. function get_client_ip($type = 0,$adv=false) {
  1335.     $type       =  $type ? 1 : 0;
  1336.     static $ip  =   NULL;
  1337.     if ($ip !== NULL) return $ip[$type];
  1338.     if($adv){
  1339.         if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  1340.             $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  1341.             $pos    =   array_search('unknown',$arr);
  1342.             if(false !== $pos) unset($arr[$pos]);
  1343.             $ip     =   trim($arr[0]);
  1344.         }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
  1345.             $ip     =   $_SERVER['HTTP_CLIENT_IP'];
  1346.         }elseif (isset($_SERVER['REMOTE_ADDR'])) {
  1347.             $ip     =   $_SERVER['REMOTE_ADDR'];
  1348.         }
  1349.     }elseif (isset($_SERVER['REMOTE_ADDR'])) {
  1350.         $ip     =   $_SERVER['REMOTE_ADDR'];
  1351.     }
  1352.     // IP地址合法验证
  1353.     $long = sprintf("%u",ip2long($ip));
  1354.     $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
  1355.     return $ip[$type];
  1356. }

  1357. /**
  1358. * 发送HTTP状态
  1359. * @param integer $code 状态码
  1360. * @return void
  1361. */
  1362. function send_http_status($code) {
  1363.     static $_status = array(
  1364.             // Informational 1xx
  1365.             100 => 'Continue',
  1366.             101 => 'Switching Protocols',
  1367.             // Success 2xx
  1368.             200 => 'OK',
  1369.             201 => 'Created',
  1370.             202 => 'Accepted',
  1371.             203 => 'Non-Authoritative Information',
  1372.             204 => 'No Content',
  1373.             205 => 'Reset Content',
  1374.             206 => 'Partial Content',
  1375.             // Redirection 3xx
  1376.             300 => 'Multiple Choices',
  1377.             301 => 'Moved Permanently',
  1378.             302 => 'Moved Temporarily ',  // 1.1
  1379.             303 => 'See Other',
  1380.             304 => 'Not Modified',
  1381.             305 => 'Use Proxy',
  1382.             // 306 is deprecated but reserved
  1383.             307 => 'Temporary Redirect',
  1384.             // Client Error 4xx
  1385.             400 => 'Bad Request',
  1386.             401 => 'Unauthorized',
  1387.             402 => 'Payment Required',
  1388.             403 => 'Forbidden',
  1389.             404 => 'Not Found',
  1390.             405 => 'Method Not Allowed',
  1391.             406 => 'Not Acceptable',
  1392.             407 => 'Proxy Authentication Required',
  1393.             408 => 'Request Timeout',
  1394.             409 => 'Conflict',
  1395.             410 => 'Gone',
  1396.             411 => 'Length Required',
  1397.             412 => 'Precondition Failed',
  1398.             413 => 'Request Entity Too Large',
  1399.             414 => 'Request-URI Too Long',
  1400.             415 => 'Unsupported Media Type',
  1401.             416 => 'Requested Range Not Satisfiable',
  1402.             417 => 'Expectation Failed',
  1403.             // Server Error 5xx
  1404.             500 => 'Internal Server Error',
  1405.             501 => 'Not Implemented',
  1406.             502 => 'Bad Gateway',
  1407.             503 => 'Service Unavailable',
  1408.             504 => 'Gateway Timeout',
  1409.             505 => 'HTTP Version Not Supported',
  1410.             509 => 'Bandwidth Limit Exceeded'
  1411.     );
  1412.     if(isset($_status[$code])) {
  1413.         header('HTTP/1.1 '.$code.' '.$_status[$code]);
  1414.         // 确保FastCGI模式下正常
  1415.         header('Status:'.$code.' '.$_status[$code]);
  1416.     }
  1417. }

  1418. // 不区分大小写的in_array实现
  1419. function in_array_case($value,$array){
  1420.     return in_array(strtolower($value),array_map('strtolower',$array));
  1421. }

  1422. function think_filter(&$value){
  1423.     // TODO 其他安全过滤

  1424.     // 过滤查询特殊字符
  1425.     if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|LIKE|NOTLIKE|BETWEEN|IN)$/i',$value)){
  1426.         $value .= ' ';
  1427.     }
  1428. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | ע

本版积分规则

QQ|Archiver|ֻ|С|ѡ̳

GMT+8, 2026-5-2 04:39 , Processed in 0.089893 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表
0.1031s