PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/ThinkPHP/ThinkPHP/Mode/Api/functions.php

https://github.com/guodont/easycart
PHP | 1037 lines | 857 code | 20 blank | 160 comment | 64 complexity | fe31e40e87a94f1735f0dc9624f5a1ef MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  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 API模式函数库
  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 = strtolower($name);
  31. if (is_null($value))
  32. return isset($_config[$name]) ? $_config[$name] : $default;
  33. $_config[$name] = $value;
  34. return;
  35. }
  36. // 二维数组设置和获取支持
  37. $name = explode('.', $name);
  38. $name[0] = strtolower($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;
  43. }
  44. // 批量设置
  45. if (is_array($name)){
  46. $_config = array_merge($_config, array_change_key_case($name));
  47. return;
  48. }
  49. return null; // 避免非法参数
  50. }
  51. /**
  52. * 抛出异常处理
  53. * @param string $msg 异常消息
  54. * @param integer $code 异常代码 默认为0
  55. * @return void
  56. */
  57. function E($msg, $code=0) {
  58. throw new Think\Exception($msg, $code);
  59. }
  60. /**
  61. * 记录和统计时间(微秒)和内存使用情况
  62. * 使用方法:
  63. * <code>
  64. * G('begin'); // 记录开始标记位
  65. * // ... 区间运行代码
  66. * G('end'); // 记录结束标签位
  67. * echo G('begin','end',6); // 统计区间运行时间 精确到小数后6位
  68. * echo G('begin','end','m'); // 统计区间内存使用情况
  69. * 如果end标记位没有定义,则会自动以当前作为标记位
  70. * 其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
  71. * </code>
  72. * @param string $start 开始标签
  73. * @param string $end 结束标签
  74. * @param integer|string $dec 小数位或者m
  75. * @return mixed
  76. */
  77. function G($start,$end='',$dec=4) {
  78. static $_info = array();
  79. static $_mem = array();
  80. if(is_float($end)) { // 记录时间
  81. $_info[$start] = $end;
  82. }elseif(!empty($end)){ // 统计时间和内存使用
  83. if(!isset($_info[$end])) $_info[$end] = microtime(TRUE);
  84. if(MEMORY_LIMIT_ON && $dec=='m'){
  85. if(!isset($_mem[$end])) $_mem[$end] = memory_get_usage();
  86. return number_format(($_mem[$end]-$_mem[$start])/1024);
  87. }else{
  88. return number_format(($_info[$end]-$_info[$start]),$dec);
  89. }
  90. }else{ // 记录时间和内存使用
  91. $_info[$start] = microtime(TRUE);
  92. if(MEMORY_LIMIT_ON) $_mem[$start] = memory_get_usage();
  93. }
  94. }
  95. /**
  96. * 获取和设置语言定义(不区分大小写)
  97. * @param string|array $name 语言变量
  98. * @param string $value 语言值
  99. * @return mixed
  100. */
  101. function L($name=null, $value=null) {
  102. static $_lang = array();
  103. // 空参数返回所有定义
  104. if (empty($name))
  105. return $_lang;
  106. // 判断语言获取(或设置)
  107. // 若不存在,直接返回全大写$name
  108. if (is_string($name)) {
  109. $name = strtoupper($name);
  110. if (is_null($value))
  111. return isset($_lang[$name]) ? $_lang[$name] : $name;
  112. $_lang[$name] = $value; // 语言定义
  113. return;
  114. }
  115. // 批量定义
  116. if (is_array($name))
  117. $_lang = array_merge($_lang, array_change_key_case($name, CASE_UPPER));
  118. return;
  119. }
  120. /**
  121. * 添加和获取页面Trace记录
  122. * @param string $value 变量
  123. * @param string $label 标签
  124. * @param string $level 日志级别
  125. * @param boolean $record 是否记录日志
  126. * @return void
  127. */
  128. function trace($value='[think]',$label='',$level='DEBUG',$record=false) {
  129. return Think\Think::trace($value,$label,$level,$record);
  130. }
  131. /**
  132. * 编译文件
  133. * @param string $filename 文件名
  134. * @return string
  135. */
  136. function compile($filename) {
  137. $content = php_strip_whitespace($filename);
  138. $content = trim(substr($content, 5));
  139. // 替换预编译指令
  140. $content = preg_replace('/\/\/\[RUNTIME\](.*?)\/\/\[\/RUNTIME\]/s', '', $content);
  141. if(0===strpos($content,'namespace')){
  142. $content = preg_replace('/namespace\s(.*?);/','namespace \\1{',$content,1);
  143. }else{
  144. $content = 'namespace {'.$content;
  145. }
  146. if ('?>' == substr($content, -2))
  147. $content = substr($content, 0, -2);
  148. return $content.'}';
  149. }
  150. /**
  151. * 获取输入参数 支持过滤和默认值
  152. * 使用方法:
  153. * <code>
  154. * I('id',0); 获取id参数 自动判断get或者post
  155. * I('post.name','','htmlspecialchars'); 获取$_POST['name']
  156. * I('get.'); 获取$_GET
  157. * </code>
  158. * @param string $name 变量的名称 支持指定类型
  159. * @param mixed $default 不存在的时候默认值
  160. * @param mixed $filter 参数过滤方法
  161. * @return mixed
  162. */
  163. function I($name,$default='',$filter=null) {
  164. if(strpos($name,'.')) { // 指定参数来源
  165. list($method,$name) = explode('.',$name,2);
  166. }else{ // 默认为自动判断
  167. $method = 'param';
  168. }
  169. switch(strtolower($method)) {
  170. case 'get' : $input =& $_GET;break;
  171. case 'post' : $input =& $_POST;break;
  172. case 'put' : parse_str(file_get_contents('php://input'), $input);break;
  173. case 'param' :
  174. switch($_SERVER['REQUEST_METHOD']) {
  175. case 'POST':
  176. $input = $_POST;
  177. break;
  178. case 'PUT':
  179. parse_str(file_get_contents('php://input'), $input);
  180. break;
  181. default:
  182. $input = $_GET;
  183. }
  184. break;
  185. case 'request' : $input =& $_REQUEST; break;
  186. case 'session' : $input =& $_SESSION; break;
  187. case 'cookie' : $input =& $_COOKIE; break;
  188. case 'server' : $input =& $_SERVER; break;
  189. case 'globals' : $input =& $GLOBALS; break;
  190. default:
  191. return NULL;
  192. }
  193. if(empty($name)) { // 获取全部变量
  194. $data = $input;
  195. array_walk_recursive($data,'filter_exp');
  196. $filters = isset($filter)?$filter:C('DEFAULT_FILTER');
  197. if($filters) {
  198. $filters = explode(',',$filters);
  199. foreach($filters as $filter){
  200. $data = array_map_recursive($filter,$data); // 参数过滤
  201. }
  202. }
  203. }elseif(isset($input[$name])) { // 取值操作
  204. $data = $input[$name];
  205. is_array($data) && array_walk_recursive($data,'filter_exp');
  206. $filters = isset($filter)?$filter:C('DEFAULT_FILTER');
  207. if($filters) {
  208. $filters = explode(',',$filters);
  209. foreach($filters as $filter){
  210. if(function_exists($filter)) {
  211. $data = is_array($data)?array_map_recursive($filter,$data):$filter($data); // 参数过滤
  212. }else{
  213. $data = filter_var($data,is_int($filter)?$filter:filter_id($filter));
  214. if(false === $data) {
  215. return isset($default)?$default:NULL;
  216. }
  217. }
  218. }
  219. }
  220. }else{ // 变量默认值
  221. $data = isset($default)?$default:NULL;
  222. }
  223. return $data;
  224. }
  225. function array_map_recursive($filter, $data) {
  226. $result = array();
  227. foreach ($data as $key => $val) {
  228. $result[$key] = is_array($val)
  229. ? array_map_recursive($filter, $val)
  230. : call_user_func($filter, $val);
  231. }
  232. return $result;
  233. }
  234. /**
  235. * 设置和获取统计数据
  236. * 使用方法:
  237. * <code>
  238. * N('db',1); // 记录数据库操作次数
  239. * N('read',1); // 记录读取次数
  240. * echo N('db'); // 获取当前页面数据库的所有操作次数
  241. * echo N('read'); // 获取当前页面读取次数
  242. * </code>
  243. * @param string $key 标识位置
  244. * @param integer $step 步进值
  245. * @return mixed
  246. */
  247. function N($key, $step=0,$save=false) {
  248. static $_num = array();
  249. if (!isset($_num[$key])) {
  250. $_num[$key] = (false !== $save)? S('N_'.$key) : 0;
  251. }
  252. if (empty($step))
  253. return $_num[$key];
  254. else
  255. $_num[$key] = $_num[$key] + (int) $step;
  256. if(false !== $save){ // 保存结果
  257. S('N_'.$key,$_num[$key],$save);
  258. }
  259. }
  260. /**
  261. * 字符串命名风格转换
  262. * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
  263. * @param string $name 字符串
  264. * @param integer $type 转换类型
  265. * @return string
  266. */
  267. function parse_name($name, $type=0) {
  268. if ($type) {
  269. return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match){return strtoupper($match[1]);}, $name));
  270. } else {
  271. return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
  272. }
  273. }
  274. /**
  275. * 优化的require_once
  276. * @param string $filename 文件地址
  277. * @return boolean
  278. */
  279. function require_cache($filename) {
  280. static $_importFiles = array();
  281. if (!isset($_importFiles[$filename])) {
  282. if (file_exists_case($filename)) {
  283. require $filename;
  284. $_importFiles[$filename] = true;
  285. } else {
  286. $_importFiles[$filename] = false;
  287. }
  288. }
  289. return $_importFiles[$filename];
  290. }
  291. /**
  292. * 区分大小写的文件存在判断
  293. * @param string $filename 文件地址
  294. * @return boolean
  295. */
  296. function file_exists_case($filename) {
  297. if (is_file($filename)) {
  298. if (IS_WIN && APP_DEBUG) {
  299. if (basename(realpath($filename)) != basename($filename))
  300. return false;
  301. }
  302. return true;
  303. }
  304. return false;
  305. }
  306. /**
  307. * 导入所需的类库 同java的Import 本函数有缓存功能
  308. * @param string $class 类库命名空间字符串
  309. * @param string $baseUrl 起始路径
  310. * @param string $ext 导入的文件扩展名
  311. * @return boolean
  312. */
  313. function import($class, $baseUrl = '', $ext=EXT) {
  314. static $_file = array();
  315. $class = str_replace(array('.', '#'), array('/', '.'), $class);
  316. if (isset($_file[$class . $baseUrl]))
  317. return true;
  318. else
  319. $_file[$class . $baseUrl] = true;
  320. $class_strut = explode('/', $class);
  321. if (empty($baseUrl)) {
  322. if ('@' == $class_strut[0] || MODULE_NAME == $class_strut[0]) {
  323. //加载当前模块的类库
  324. $baseUrl = MODULE_PATH;
  325. $class = substr_replace($class, '', 0, strlen($class_strut[0]) + 1);
  326. }elseif (in_array($class_strut[0],array('Think','Org','Behavior','Com','Vendor')) || is_dir(LIB_PATH.$class_strut[0])) {
  327. // 系统类库包和第三方类库包
  328. $baseUrl = LIB_PATH;
  329. }else { // 加载其他模块的类库
  330. $baseUrl = APP_PATH;
  331. }
  332. }
  333. if (substr($baseUrl, -1) != '/')
  334. $baseUrl .= '/';
  335. $classfile = $baseUrl . $class . $ext;
  336. if (!class_exists(basename($class),false)) {
  337. // 如果类不存在 则导入类库文件
  338. return require_cache($classfile);
  339. }
  340. }
  341. /**
  342. * 基于命名空间方式导入函数库
  343. * load('@.Util.Array')
  344. * @param string $name 函数库命名空间字符串
  345. * @param string $baseUrl 起始路径
  346. * @param string $ext 导入的文件扩展名
  347. * @return void
  348. */
  349. function load($name, $baseUrl='', $ext='.php') {
  350. $name = str_replace(array('.', '#'), array('/', '.'), $name);
  351. if (empty($baseUrl)) {
  352. if (0 === strpos($name, '@/')) {//加载当前模块函数库
  353. $baseUrl = MODULE_PATH.'Common/';
  354. $name = substr($name, 2);
  355. } else { //加载其他模块函数库
  356. $array = explode('/', $name);
  357. $baseUrl = APP_PATH . array_shift($array).'/Common/';
  358. $name = implode('/',$array);
  359. }
  360. }
  361. if (substr($baseUrl, -1) != '/')
  362. $baseUrl .= '/';
  363. require_cache($baseUrl . $name . $ext);
  364. }
  365. /**
  366. * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
  367. * @param string $class 类库
  368. * @param string $baseUrl 基础目录
  369. * @param string $ext 类库后缀
  370. * @return boolean
  371. */
  372. function vendor($class, $baseUrl = '', $ext='.php') {
  373. if (empty($baseUrl))
  374. $baseUrl = VENDOR_PATH;
  375. return import($class, $baseUrl, $ext);
  376. }
  377. /**
  378. * D函数用于实例化模型类 格式 [资源://][模块/]模型
  379. * @param string $name 资源地址
  380. * @param string $layer 模型层名称
  381. * @return Model
  382. */
  383. function D($name='',$layer='') {
  384. if(empty($name)) return new Think\Model;
  385. static $_model = array();
  386. $layer = $layer? : C('DEFAULT_M_LAYER');
  387. if(isset($_model[$name.$layer]))
  388. return $_model[$name.$layer];
  389. $class = parse_res_name($name,$layer);
  390. if(class_exists($class)) {
  391. $model = new $class(basename($name));
  392. }elseif(false === strpos($name,'/')){
  393. // 自动加载公共模块下面的模型
  394. $class = '\\Common\\'.$layer.'\\'.$name.$layer;
  395. $model = class_exists($class)? new $class($name) : new Think\Model($name);
  396. }else {
  397. Think\Log::record('D方法实例化没找到模型类'.$class,Think\Log::NOTICE);
  398. $model = new Think\Model(basename($name));
  399. }
  400. $_model[$name.$layer] = $model;
  401. return $model;
  402. }
  403. /**
  404. * M函数用于实例化一个没有模型文件的Model
  405. * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User
  406. * @param string $tablePrefix 表前缀
  407. * @param mixed $connection 数据库连接信息
  408. * @return Model
  409. */
  410. function M($name='', $tablePrefix='',$connection='') {
  411. static $_model = array();
  412. if(strpos($name,':')) {
  413. list($class,$name) = explode(':',$name);
  414. }else{
  415. $class = 'Think\\Model';
  416. }
  417. $guid = (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
  418. if (!isset($_model[$guid]))
  419. $_model[$guid] = new $class($name,$tablePrefix,$connection);
  420. return $_model[$guid];
  421. }
  422. /**
  423. * 解析资源地址并导入类库文件
  424. * 例如 module/controller addon://module/behavior
  425. * @param string $name 资源地址 格式:[扩展://][模块/]资源名
  426. * @param string $layer 分层名称
  427. * @return string
  428. */
  429. function parse_res_name($name,$layer,$level=1){
  430. if(strpos($name,'://')) {// 指定扩展资源
  431. list($extend,$name) = explode('://',$name);
  432. }else{
  433. $extend = '';
  434. }
  435. if(strpos($name,'/') && substr_count($name, '/')>=$level){ // 指定模块
  436. list($module,$name) = explode('/',$name,2);
  437. }else{
  438. $module = MODULE_NAME;
  439. }
  440. $array = explode('/',$name);
  441. $class = $module.'\\'.$layer;
  442. foreach($array as $name){
  443. $class .= '\\'.parse_name($name, 1);
  444. }
  445. // 导入资源类库
  446. if($extend){ // 扩展资源
  447. $class = $extend.'\\'.$class;
  448. }
  449. return $class.$layer;
  450. }
  451. /**
  452. * A函数用于实例化控制器 格式:[资源://][模块/]控制器
  453. * @param string $name 资源地址
  454. * @param string $layer 控制层名称
  455. * @param integer $level 控制器层次
  456. * @return Controller|false
  457. */
  458. function A($name,$layer='',$level='') {
  459. static $_action = array();
  460. $layer = $layer? : C('DEFAULT_C_LAYER');
  461. $level = $level? : ($layer == C('DEFAULT_C_LAYER')?C('CONTROLLER_LEVEL'):1);
  462. if(isset($_action[$name.$layer]))
  463. return $_action[$name.$layer];
  464. $class = parse_res_name($name,$layer,$level);
  465. if(class_exists($class)) {
  466. $action = new $class();
  467. $_action[$name.$layer] = $action;
  468. return $action;
  469. }else {
  470. return false;
  471. }
  472. }
  473. /**
  474. * 远程调用控制器的操作方法 URL 参数格式 [资源://][模块/]控制器/操作
  475. * @param string $url 调用地址
  476. * @param string|array $vars 调用参数 支持字符串和数组
  477. * @param string $layer 要调用的控制层名称
  478. * @return mixed
  479. */
  480. function R($url,$vars=array(),$layer='') {
  481. $info = pathinfo($url);
  482. $action = $info['basename'];
  483. $module = $info['dirname'];
  484. $class = A($module,$layer);
  485. if($class){
  486. if(is_string($vars)) {
  487. parse_str($vars,$vars);
  488. }
  489. return call_user_func_array(array(&$class,$action.C('ACTION_SUFFIX')),$vars);
  490. }else{
  491. return false;
  492. }
  493. }
  494. /**
  495. * 执行某个行为
  496. * @param string $name 行为名称
  497. * @param Mixed $params 传入的参数
  498. * @return void
  499. */
  500. function B($name, &$params=NULL) {
  501. if(strpos($name,'/')){
  502. list($name,$tag) = explode('/',$name);
  503. }else{
  504. $tag = 'run';
  505. }
  506. return \Think\Hook::exec($name,$tag,$params);
  507. }
  508. /**
  509. * 去除代码中的空白和注释
  510. * @param string $content 代码内容
  511. * @return string
  512. */
  513. function strip_whitespace($content) {
  514. $stripStr = '';
  515. //分析php源码
  516. $tokens = token_get_all($content);
  517. $last_space = false;
  518. for ($i = 0, $j = count($tokens); $i < $j; $i++) {
  519. if (is_string($tokens[$i])) {
  520. $last_space = false;
  521. $stripStr .= $tokens[$i];
  522. } else {
  523. switch ($tokens[$i][0]) {
  524. //过滤各种PHP注释
  525. case T_COMMENT:
  526. case T_DOC_COMMENT:
  527. break;
  528. //过滤空格
  529. case T_WHITESPACE:
  530. if (!$last_space) {
  531. $stripStr .= ' ';
  532. $last_space = true;
  533. }
  534. break;
  535. case T_START_HEREDOC:
  536. $stripStr .= "<<<THINK\n";
  537. break;
  538. case T_END_HEREDOC:
  539. $stripStr .= "THINK;\n";
  540. for($k = $i+1; $k < $j; $k++) {
  541. if(is_string($tokens[$k]) && $tokens[$k] == ';') {
  542. $i = $k;
  543. break;
  544. } else if($tokens[$k][0] == T_CLOSE_TAG) {
  545. break;
  546. }
  547. }
  548. break;
  549. default:
  550. $last_space = false;
  551. $stripStr .= $tokens[$i][1];
  552. }
  553. }
  554. }
  555. return $stripStr;
  556. }
  557. /**
  558. * 浏览器友好的变量输出
  559. * @param mixed $var 变量
  560. * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
  561. * @param string $label 标签 默认为空
  562. * @param boolean $strict 是否严谨 默认为true
  563. * @return void|string
  564. */
  565. function dump($var, $echo=true, $label=null, $strict=true) {
  566. $label = ($label === null) ? '' : rtrim($label) . ' ';
  567. if (!$strict) {
  568. if (ini_get('html_errors')) {
  569. $output = print_r($var, true);
  570. $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
  571. } else {
  572. $output = $label . print_r($var, true);
  573. }
  574. } else {
  575. ob_start();
  576. var_dump($var);
  577. $output = ob_get_clean();
  578. if (!extension_loaded('xdebug')) {
  579. $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
  580. $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
  581. }
  582. }
  583. if ($echo) {
  584. echo($output);
  585. return null;
  586. }else
  587. return $output;
  588. }
  589. /**
  590. * URL重定向
  591. * @param string $url 重定向的URL地址
  592. * @param integer $time 重定向的等待时间(秒)
  593. * @param string $msg 重定向前的提示信息
  594. * @return void
  595. */
  596. function redirect($url, $time=0, $msg='') {
  597. //多行URL地址支持
  598. $url = str_replace(array("\n", "\r"), '', $url);
  599. if (empty($msg))
  600. $msg = "系统将在{$time}秒之后自动跳转到{$url}!";
  601. if (!headers_sent()) {
  602. // redirect
  603. if (0 === $time) {
  604. header('Location: ' . $url);
  605. } else {
  606. header("refresh:{$time};url={$url}");
  607. echo($msg);
  608. }
  609. exit();
  610. } else {
  611. $str = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
  612. if ($time != 0)
  613. $str .= $msg;
  614. exit($str);
  615. }
  616. }
  617. /**
  618. * 缓存管理
  619. * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
  620. * @param mixed $value 缓存值
  621. * @param mixed $options 缓存参数
  622. * @return mixed
  623. */
  624. function S($name,$value='',$options=null) {
  625. static $cache = '';
  626. if(is_array($options) && empty($cache)){
  627. // 缓存操作的同时初始化
  628. $type = isset($options['type'])?$options['type']:'';
  629. $cache = Think\Cache::getInstance($type,$options);
  630. }elseif(is_array($name)) { // 缓存初始化
  631. $type = isset($name['type'])?$name['type']:'';
  632. $cache = Think\Cache::getInstance($type,$name);
  633. return $cache;
  634. }elseif(empty($cache)) { // 自动初始化
  635. $cache = Think\Cache::getInstance();
  636. }
  637. if(''=== $value){ // 获取缓存
  638. return $cache->get($name);
  639. }elseif(is_null($value)) { // 删除缓存
  640. return $cache->rm($name);
  641. }else { // 缓存数据
  642. if(is_array($options)) {
  643. $expire = isset($options['expire'])?$options['expire']:NULL;
  644. }else{
  645. $expire = is_numeric($options)?$options:NULL;
  646. }
  647. return $cache->set($name, $value, $expire);
  648. }
  649. }
  650. /**
  651. * 快速文件数据读取和保存 针对简单类型数据 字符串、数组
  652. * @param string $name 缓存名称
  653. * @param mixed $value 缓存值
  654. * @param string $path 缓存路径
  655. * @return mixed
  656. */
  657. function F($name, $value='', $path=DATA_PATH) {
  658. static $_cache = array();
  659. $filename = $path . $name . '.php';
  660. if ('' !== $value) {
  661. if (is_null($value)) {
  662. // 删除缓存
  663. if(false !== strpos($name,'*')){
  664. return false; // TODO
  665. }else{
  666. unset($_cache[$name]);
  667. return Think\Storage::unlink($filename,'F');
  668. }
  669. } else {
  670. Think\Storage::put($filename,serialize($value),'F');
  671. // 缓存数据
  672. $_cache[$name] = $value;
  673. return ;
  674. }
  675. }
  676. // 获取缓存数据
  677. if (isset($_cache[$name]))
  678. return $_cache[$name];
  679. if (Think\Storage::has($filename,'F')){
  680. $value = unserialize(Think\Storage::read($filename,'F'));
  681. $_cache[$name] = $value;
  682. } else {
  683. $value = false;
  684. }
  685. return $value;
  686. }
  687. /**
  688. * 根据PHP各种类型变量生成唯一标识号
  689. * @param mixed $mix 变量
  690. * @return string
  691. */
  692. function to_guid_string($mix) {
  693. if (is_object($mix)) {
  694. return spl_object_hash($mix);
  695. } elseif (is_resource($mix)) {
  696. $mix = get_resource_type($mix) . strval($mix);
  697. } else {
  698. $mix = serialize($mix);
  699. }
  700. return md5($mix);
  701. }
  702. /**
  703. * XML编码
  704. * @param mixed $data 数据
  705. * @param string $root 根节点名
  706. * @param string $item 数字索引的子节点名
  707. * @param string $attr 根节点属性
  708. * @param string $id 数字索引子节点key转换的属性名
  709. * @param string $encoding 数据编码
  710. * @return string
  711. */
  712. function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
  713. if(is_array($attr)){
  714. $_attr = array();
  715. foreach ($attr as $key => $value) {
  716. $_attr[] = "{$key}=\"{$value}\"";
  717. }
  718. $attr = implode(' ', $_attr);
  719. }
  720. $attr = trim($attr);
  721. $attr = empty($attr) ? '' : " {$attr}";
  722. $xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
  723. $xml .= "<{$root}{$attr}>";
  724. $xml .= data_to_xml($data, $item, $id);
  725. $xml .= "</{$root}>";
  726. return $xml;
  727. }
  728. /**
  729. * 数据XML编码
  730. * @param mixed $data 数据
  731. * @param string $item 数字索引时的节点名称
  732. * @param string $id 数字索引key转换为的属性名
  733. * @return string
  734. */
  735. function data_to_xml($data, $item='item', $id='id') {
  736. $xml = $attr = '';
  737. foreach ($data as $key => $val) {
  738. if(is_numeric($key)){
  739. $id && $attr = " {$id}=\"{$key}\"";
  740. $key = $item;
  741. }
  742. $xml .= "<{$key}{$attr}>";
  743. $xml .= (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
  744. $xml .= "</{$key}>";
  745. }
  746. return $xml;
  747. }
  748. /**
  749. * session管理函数
  750. * @param string|array $name session名称 如果为数组则表示进行session设置
  751. * @param mixed $value session值
  752. * @return mixed
  753. */
  754. function session($name,$value='') {
  755. $prefix = C('SESSION_PREFIX');
  756. if(is_array($name)) { // session初始化 在session_start 之前调用
  757. if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
  758. if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
  759. session_id($_REQUEST[C('VAR_SESSION_ID')]);
  760. }elseif(isset($name['id'])) {
  761. session_id($name['id']);
  762. }
  763. if('common' != APP_MODE){ // 其它模式可能不支持
  764. ini_set('session.auto_start', 0);
  765. }
  766. if(isset($name['name'])) session_name($name['name']);
  767. if(isset($name['path'])) session_save_path($name['path']);
  768. if(isset($name['domain'])) ini_set('session.cookie_domain', $name['domain']);
  769. if(isset($name['expire'])) ini_set('session.gc_maxlifetime', $name['expire']);
  770. if(isset($name['use_trans_sid'])) ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
  771. if(isset($name['use_cookies'])) ini_set('session.use_cookies', $name['use_cookies']?1:0);
  772. if(isset($name['cache_limiter'])) session_cache_limiter($name['cache_limiter']);
  773. if(isset($name['cache_expire'])) session_cache_expire($name['cache_expire']);
  774. if(isset($name['type'])) C('SESSION_TYPE',$name['type']);
  775. if(C('SESSION_TYPE')) { // 读取session驱动
  776. $type = C('SESSION_TYPE');
  777. $class = strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
  778. $hander = new $class();
  779. session_set_save_handler(
  780. array(&$hander,"open"),
  781. array(&$hander,"close"),
  782. array(&$hander,"read"),
  783. array(&$hander,"write"),
  784. array(&$hander,"destroy"),
  785. array(&$hander,"gc"));
  786. }
  787. // 启动session
  788. if(C('SESSION_AUTO_START')) session_start();
  789. }elseif('' === $value){
  790. if(0===strpos($name,'[')) { // session 操作
  791. if('[pause]'==$name){ // 暂停session
  792. session_write_close();
  793. }elseif('[start]'==$name){ // 启动session
  794. session_start();
  795. }elseif('[destroy]'==$name){ // 销毁session
  796. $_SESSION = array();
  797. session_unset();
  798. session_destroy();
  799. }elseif('[regenerate]'==$name){ // 重新生成id
  800. session_regenerate_id();
  801. }
  802. }elseif(0===strpos($name,'?')){ // 检查session
  803. $name = substr($name,1);
  804. if(strpos($name,'.')){ // 支持数组
  805. list($name1,$name2) = explode('.',$name);
  806. return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
  807. }else{
  808. return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
  809. }
  810. }elseif(is_null($name)){ // 清空session
  811. if($prefix) {
  812. unset($_SESSION[$prefix]);
  813. }else{
  814. $_SESSION = array();
  815. }
  816. }elseif($prefix){ // 获取session
  817. if(strpos($name,'.')){
  818. list($name1,$name2) = explode('.',$name);
  819. return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;
  820. }else{
  821. return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;
  822. }
  823. }else{
  824. if(strpos($name,'.')){
  825. list($name1,$name2) = explode('.',$name);
  826. return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;
  827. }else{
  828. return isset($_SESSION[$name])?$_SESSION[$name]:null;
  829. }
  830. }
  831. }elseif(is_null($value)){ // 删除session
  832. if($prefix){
  833. unset($_SESSION[$prefix][$name]);
  834. }else{
  835. unset($_SESSION[$name]);
  836. }
  837. }else{ // 设置session
  838. if($prefix){
  839. if (!is_array($_SESSION[$prefix])) {
  840. $_SESSION[$prefix] = array();
  841. }
  842. $_SESSION[$prefix][$name] = $value;
  843. }else{
  844. $_SESSION[$name] = $value;
  845. }
  846. }
  847. }
  848. /**
  849. * Cookie 设置、获取、删除
  850. * @param string $name cookie名称
  851. * @param mixed $value cookie值
  852. * @param mixed $options cookie参数
  853. * @return mixed
  854. */
  855. function cookie($name, $value='', $option=null) {
  856. // 默认设置
  857. $config = array(
  858. 'prefix' => C('COOKIE_PREFIX'), // cookie 名称前缀
  859. 'expire' => C('COOKIE_EXPIRE'), // cookie 保存时间
  860. 'path' => C('COOKIE_PATH'), // cookie 保存路径
  861. 'domain' => C('COOKIE_DOMAIN'), // cookie 有效域名
  862. );
  863. // 参数设置(会覆盖黙认设置)
  864. if (!is_null($option)) {
  865. if (is_numeric($option))
  866. $option = array('expire' => $option);
  867. elseif (is_string($option))
  868. parse_str($option, $option);
  869. $config = array_merge($config, array_change_key_case($option));
  870. }
  871. // 清除指定前缀的所有cookie
  872. if (is_null($name)) {
  873. if (empty($_COOKIE))
  874. return;
  875. // 要删除的cookie前缀,不指定则删除config设置的指定前缀
  876. $prefix = empty($value) ? $config['prefix'] : $value;
  877. if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
  878. foreach ($_COOKIE as $key => $val) {
  879. if (0 === stripos($key, $prefix)) {
  880. setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
  881. unset($_COOKIE[$key]);
  882. }
  883. }
  884. }
  885. return;
  886. }
  887. $name = $config['prefix'] . $name;
  888. if ('' === $value) {
  889. if(isset($_COOKIE[$name])){
  890. $value = $_COOKIE[$name];
  891. if(0===strpos($value,'think:')){
  892. $value = substr($value,6);
  893. return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
  894. }else{
  895. return $value;
  896. }
  897. }else{
  898. return null;
  899. }
  900. } else {
  901. if (is_null($value)) {
  902. setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
  903. unset($_COOKIE[$name]); // 删除指定cookie
  904. } else {
  905. // 设置cookie
  906. if(is_array($value)){
  907. $value = 'think:'.json_encode(array_map('urlencode',$value));
  908. }
  909. $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
  910. setcookie($name, $value, $expire, $config['path'], $config['domain']);
  911. $_COOKIE[$name] = $value;
  912. }
  913. }
  914. }
  915. /**
  916. * 加载动态扩展文件
  917. * @return void
  918. */
  919. function load_ext_file($path) {
  920. // 加载自定义外部文件
  921. if(C('LOAD_EXT_FILE')) {
  922. $files = explode(',',C('LOAD_EXT_FILE'));
  923. foreach ($files as $file){
  924. $file = $path.'Common/'.$file.'.php';
  925. if(is_file($file)) include $file;
  926. }
  927. }
  928. // 加载自定义的动态配置文件
  929. if(C('LOAD_EXT_CONFIG')) {
  930. $configs = C('LOAD_EXT_CONFIG');
  931. if(is_string($configs)) $configs = explode(',',$configs);
  932. foreach ($configs as $key=>$config){
  933. $file = $path.'Conf/'.$config.'.php';
  934. if(is_file($file)) {
  935. is_numeric($key)?C(include $file):C($key,include $file);
  936. }
  937. }
  938. }
  939. }
  940. /**
  941. * 获取客户端IP地址
  942. * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
  943. * @return mixed
  944. */
  945. function get_client_ip($type = 0) {
  946. $type = $type ? 1 : 0;
  947. static $ip = NULL;
  948. if ($ip !== NULL) return $ip[$type];
  949. if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  950. $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  951. $pos = array_search('unknown',$arr);
  952. if(false !== $pos) unset($arr[$pos]);
  953. $ip = trim($arr[0]);
  954. }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
  955. $ip = $_SERVER['HTTP_CLIENT_IP'];
  956. }elseif (isset($_SERVER['REMOTE_ADDR'])) {
  957. $ip = $_SERVER['REMOTE_ADDR'];
  958. }
  959. // IP地址合法验证
  960. $long = sprintf("%u",ip2long($ip));
  961. $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
  962. return $ip[$type];
  963. }
  964. /**
  965. * 发送HTTP状态
  966. * @param integer $code 状态码
  967. * @return void
  968. */
  969. function send_http_status($code) {
  970. static $_status = array(
  971. // Success 2xx
  972. 200 => 'OK',
  973. // Redirection 3xx
  974. 301 => 'Moved Permanently',
  975. 302 => 'Moved Temporarily ', // 1.1
  976. // Client Error 4xx
  977. 400 => 'Bad Request',
  978. 403 => 'Forbidden',
  979. 404 => 'Not Found',
  980. // Server Error 5xx
  981. 500 => 'Internal Server Error',
  982. 503 => 'Service Unavailable',
  983. );
  984. if(isset($_status[$code])) {
  985. header('HTTP/1.1 '.$code.' '.$_status[$code]);
  986. // 确保FastCGI模式下正常
  987. header('Status:'.$code.' '.$_status[$code]);
  988. }
  989. }
  990. // 过滤表单中的表达式
  991. function filter_exp(&$value){
  992. if (in_array(strtolower($value),array('exp','or'))){
  993. $value .= ' ';
  994. }
  995. }
  996. // 不区分大小写的in_array实现
  997. function in_array_case($value,$array){
  998. return in_array(strtolower($value),array_map('strtolower',$array));
  999. }