functions.php 46 KB

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