├── screenshot ├── .keep ├── p1.png ├── p2.png ├── p3.png ├── p4.png ├── p5.png └── p6.png ├── statics ├── js │ └── site.js └── css │ └── site.css ├── app ├── Lib │ └── Action │ │ ├── indexAction.class.php │ │ ├── baseAction.class.php │ │ ├── datalistAction.class.php │ │ ├── checkAction.class.php │ │ └── toolsAction.class.php └── Tpl │ ├── index │ └── index.html │ ├── tools │ ├── index.html │ ├── hongdie.html │ ├── gnball.html │ ├── gongnengbi.html │ └── baota.html │ ├── public │ ├── foot.html │ └── head.html │ ├── datalist │ └── index.html │ └── check │ └── test.html ├── index.php ├── data └── config │ └── config.php ├── framework ├── Tpl │ ├── default_index.tpl │ ├── dispatch_jump.tpl │ ├── think_exception.tpl │ └── page_trace.tpl ├── Conf │ ├── alias.php │ ├── debug.php │ ├── tags.php │ └── convention.php ├── Lib │ ├── Behavior │ │ ├── WriteHtmlCacheBehavior.class.php │ │ ├── ContentReplaceBehavior.class.php │ │ ├── LocationTemplateBehavior.class.php │ │ ├── TokenBuildBehavior.class.php │ │ ├── ShowRuntimeBehavior.class.php │ │ ├── ParseTemplateBehavior.class.php │ │ ├── ReadHtmlCacheBehavior.class.php │ │ ├── ShowPageTraceBehavior.class.php │ │ └── CheckRouteBehavior.class.php │ ├── Core │ │ ├── Behavior.class.php │ │ ├── ThinkException.class.php │ │ ├── Cache.class.php │ │ ├── Widget.class.php │ │ ├── View.class.php │ │ ├── Log.class.php │ │ ├── Dispatcher.class.php │ │ ├── Think.class.php │ │ ├── App.class.php │ │ └── Action.class.php │ ├── Driver │ │ ├── Cache │ │ │ └── CacheFile.class.php │ │ └── Db │ │ │ ├── DbMysqli.class.php │ │ │ └── DbMysql.class.php │ └── Template │ │ └── TagLib.class.php ├── run.php ├── Lang │ └── zh-cn.php └── Common │ └── runtime.php └── README.md /screenshot/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /statics/js/site.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /statics/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | min-height: 2000px; 3 | padding-top: 70px; 4 | } -------------------------------------------------------------------------------- /screenshot/p1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruffood/foodnutrition/HEAD/screenshot/p1.png -------------------------------------------------------------------------------- /screenshot/p2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruffood/foodnutrition/HEAD/screenshot/p2.png -------------------------------------------------------------------------------- /screenshot/p3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruffood/foodnutrition/HEAD/screenshot/p3.png -------------------------------------------------------------------------------- /screenshot/p4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruffood/foodnutrition/HEAD/screenshot/p4.png -------------------------------------------------------------------------------- /screenshot/p5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruffood/foodnutrition/HEAD/screenshot/p5.png -------------------------------------------------------------------------------- /screenshot/p6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruffood/foodnutrition/HEAD/screenshot/p6.png -------------------------------------------------------------------------------- /app/Lib/Action/indexAction.class.php: -------------------------------------------------------------------------------- 1 | display(); 6 | } 7 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 'localhost', 5 | 'DB_NAME' => 'nutrition', 6 | 'DB_USER' => 'root', 7 | 'DB_PWD' => 'q1w2e3', 8 | 'DB_PORT' => '3306', 9 | 'DB_PREFIX' => 'yk_', 10 | 11 | 'DEFAULT_MODULE' => 'index', //默认控制器 12 | 13 | 'TMPL_PARSE_STRING'=>array( 14 | '__STATICS__'=>__ROOT__.'/statics', 15 | '__UPLOAD__'=>__ROOT__.'/data/upload', 16 | ), 17 | ); 18 | -------------------------------------------------------------------------------- /app/Tpl/index/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |
7 |

本站是开源的

8 |

9 |

  • 准备继续完善各种细节功能
  • 10 |

    11 |

    12 | 查看食物大全 13 |

    14 |
    15 | 16 |
    17 | 18 | 19 | -------------------------------------------------------------------------------- /app/Tpl/tools/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |

    已完成

    6 |
  • 单一食物供能比筛选
  • 7 | 8 |
  • 供能比汇总
  • 9 | 10 |
  • 宏量营养素叠加图
  • 11 | 12 |
  • 膳食宝塔实例
  • 13 | 14 | 15 |

    TODO

    16 | 17 | 18 | 19 | 20 | 21 |
  • 供能比速算
  • 22 | 23 | 24 |
    25 | 26 | 27 | -------------------------------------------------------------------------------- /framework/Tpl/default_index.tpl: -------------------------------------------------------------------------------- 1 | show('

    :)

    欢迎使用 ThinkPHP

    ','utf-8'); 6 | } 7 | } -------------------------------------------------------------------------------- /app/Tpl/public/foot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |


    8 |
    9 |
    10 |
    11 | Powered by 若饭 12 |
    13 |
    14 |
    15 | 16 | 17 | -------------------------------------------------------------------------------- /app/Lib/Action/baseAction.class.php: -------------------------------------------------------------------------------- 1 | find($id); 19 | if($info) 20 | return $info; 21 | else 22 | return false; 23 | } 24 | } -------------------------------------------------------------------------------- /app/Lib/Action/datalistAction.class.php: -------------------------------------------------------------------------------- 1 | display(); 8 | } 9 | 10 | public function getdata(){ 11 | 12 | $pageSize=$this->_request('pageSize','intval'); 13 | 14 | $offset=$this->_request('offset','intval'); 15 | $offset=$offset?$offset:0; 16 | 17 | $sort=$this->_request('sort','trim'); 18 | $sortOrder=$this->_request('sortOrder','trim'); 19 | 20 | $dmod=M('foodnutrition'); 21 | $data['total']=$dmod->count(); 22 | 23 | $list=$dmod->order($sort.' '.$sortOrder)->limit($offset*$pageSize,$pageSize)->select(); 24 | 25 | 26 | $data['rows']=$list; 27 | echo json_encode($data); 28 | } 29 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 食物营养数据分析 2 | 3 | #### 项目介绍 4 | 基于已知的1284种食物进行营养数据分析 5 | 6 | 感谢 ThinkPHP、Bootstrap、ECharts、PHPExcel; 7 | 8 | #### 使用说明 9 | 10 | 1. 基于bootstrap table搭建数据列表页面 11 | 2. 查看各食物营养成分梯度分布 12 | 3. 小工具频道陆续开发系列数据管理功能 13 | 14 | #### 环境要求 15 | 1. PHP 5.3及以上 16 | 2. MySQL 17 | 3. Nginx / Apache 18 | 19 | 20 | #### 安装说明 21 | 1. 下载本项目代码 22 | 2. 导入data/sql文件夹里的数据库文件 23 | 3. 修改data/config/db.php种的数据库配置即可 24 | 25 | #### 界面截图 26 | ![输入图片说明](https://gitee.com/sanool/foodnutrition/raw/master/screenshot/p6.png "在这里输入图片标题") 27 | 28 | ![输入图片说明](https://gitee.com/sanool/foodnutrition/raw/master/screenshot/p5.png "在这里输入图片标题") 29 | 30 | ![输入图片说明](https://gitee.com/sanool/foodnutrition/raw/master/screenshot/p4.png "在这里输入图片标题") 31 | 32 | ![输入图片说明](https://gitee.com/sanool/foodnutrition/raw/master/screenshot/p3.png "在这里输入图片标题") 33 | 34 | ![输入图片说明](https://gitee.com/sanool/foodnutrition/raw/master/screenshot/p2.png "在这里输入图片标题") 35 | 36 | ![输入图片说明](https://gitee.com/sanool/foodnutrition/raw/master/screenshot/p1.png "在这里输入图片标题") 37 | 38 | -------------------------------------------------------------------------------- /framework/Conf/alias.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | // 系统别名定义文件 14 | return array( 15 | 'Model' => CORE_PATH.'Core/Model.class.php', 16 | 'Db' => CORE_PATH.'Core/Db.class.php', 17 | 'Log' => CORE_PATH.'Core/Log.class.php', 18 | 'ThinkTemplate' => CORE_PATH.'Template/ThinkTemplate.class.php', 19 | 'TagLib' => CORE_PATH.'Template/TagLib.class.php', 20 | 'Cache' => CORE_PATH.'Core/Cache.class.php', 21 | 'Widget' => CORE_PATH.'Core/Widget.class.php', 22 | 'TagLibCx' => CORE_PATH.'Driver/TagLib/TagLibCx.class.php', 23 | ); -------------------------------------------------------------------------------- /framework/Lib/Behavior/WriteHtmlCacheBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:静态缓存写入 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class WriteHtmlCacheBehavior extends Behavior { 21 | 22 | // 行为扩展的执行入口必须是run 23 | public function run(&$content){ 24 | if(C('HTML_CACHE_ON') && defined('HTML_FILE_NAME')) { 25 | //静态文件写入 26 | // 如果开启HTML功能 检查并重写HTML文件 27 | // 没有模版的操作不生成静态文件 28 | if(!is_dir(dirname(HTML_FILE_NAME))) 29 | mkdir(dirname(HTML_FILE_NAME),0777,true); 30 | if( false === file_put_contents( HTML_FILE_NAME , $content )) 31 | throw_exception(L('_CACHE_WRITE_ERROR_').':'.HTML_FILE_NAME); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /framework/Conf/debug.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP 默认的调试模式配置文件 14 | * 如果项目有定义自己的调试模式配置文件,本文件无效 15 | * @category Think 16 | * @package Common 17 | * @author liu21st 18 | * @version $Id: debug.php 3071 2012-07-15 07:59:23Z liu21st@gmail.com $ 19 | */ 20 | defined('THINK_PATH') or exit(); 21 | // 调试模式下面默认设置 可以在项目配置目录下重新定义 debug.php 覆盖 22 | return array( 23 | 'LOG_RECORD' => true, // 进行日志记录 24 | 'LOG_EXCEPTION_RECORD' => true, // 是否记录异常信息日志 25 | 'LOG_LEVEL' => 'EMERG,ALERT,CRIT,ERR,WARN,NOTIC,INFO,DEBUG,SQL', // 允许记录的日志级别 26 | 'DB_FIELDS_CACHE' => false, // 字段缓存信息 27 | 'DB_SQL_LOG' => true, // 记录SQL信息 28 | 'APP_FILE_CASE' => true, // 是否检查文件的大小写 对Windows平台有效 29 | 'TMPL_CACHE_ON' => false, // 是否开启模板编译缓存,设为false则每次都会重新编译 30 | 'TMPL_STRIP_SPACE' => false, // 是否去除模板文件里面的html空格与换行 31 | 'SHOW_ERROR_MSG' => true, // 显示错误信息 32 | ); -------------------------------------------------------------------------------- /framework/Conf/tags.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // 系统默认的核心行为扩展列表文件 13 | return array( 14 | 'app_init' => array( 15 | ), 16 | 'app_begin' => array( 17 | 'ReadHtmlCache', // 读取静态缓存 18 | ), 19 | 'route_check' => array( 20 | 'CheckRoute', // 路由检测 21 | ), 22 | 'app_end' => array(), 23 | 'path_info' => array(), 24 | 'action_begin' => array(), 25 | 'action_end' => array(), 26 | 'view_begin' => array(), 27 | 'view_template' => array( 28 | 'LocationTemplate', // 自动定位模板文件 29 | ), 30 | 'view_parse' => array( 31 | 'ParseTemplate', // 模板解析 支持PHP、内置模板引擎和第三方模板引擎 32 | ), 33 | 'view_filter' => array( 34 | 'ContentReplace', // 模板输出替换 35 | 'TokenBuild', // 表单令牌 36 | 'WriteHtmlCache', // 写入静态缓存 37 | 'ShowRuntime', // 运行时间显示 38 | ), 39 | 'view_end' => array( 40 | 'ShowPageTrace', // 页面Trace显示 41 | ), 42 | ); -------------------------------------------------------------------------------- /framework/run.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // ThinkPHP 入口文件 13 | define('VERSION', 3.1); 14 | //记录开始运行时间 15 | $GLOBALS['_beginTime'] = microtime(TRUE); 16 | // 记录内存初始使用 17 | define('MEMORY_LIMIT_ON',function_exists('memory_get_usage')); 18 | if(MEMORY_LIMIT_ON) $GLOBALS['_startUseMems'] = memory_get_usage(); 19 | defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); 20 | defined('RUNTIME_PATH') or define('RUNTIME_PATH',APP_PATH.'Runtime/'); 21 | defined('APP_DEBUG') or define('APP_DEBUG',false); // 是否调试模式 22 | $runtime = defined('MODE_NAME')?'~'.strtolower(MODE_NAME).'_runtime.php':'~runtime.php'; 23 | defined('RUNTIME_FILE') or define('RUNTIME_FILE',RUNTIME_PATH.$runtime); 24 | if(!APP_DEBUG && is_file(RUNTIME_FILE)) { 25 | // 部署模式直接载入运行缓存 26 | require RUNTIME_FILE; 27 | }else{ 28 | // 系统目录定义 29 | defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__).'/'); 30 | // 加载运行时文件 31 | require THINK_PATH.'Common/runtime.php'; 32 | } -------------------------------------------------------------------------------- /framework/Tpl/dispatch_jump.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 跳转提示 6 | 16 | 17 | 18 |
    19 | 20 |

    :)

    21 |

    22 | 23 |

    :(

    24 |

    25 |
    26 |

    27 |

    28 | 页面自动 跳转 等待时间: 29 |

    30 |
    31 | 43 | 44 | -------------------------------------------------------------------------------- /app/Tpl/tools/hongdie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |

    宏量营养素叠加图 返回

    6 |

    7 |


    8 |
    9 | 10 |
    11 | 12 |
    13 | 14 |
    15 | 16 |
    17 | 18 |
    19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /framework/Lib/Core/Behavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP Behavior基础类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | abstract class Behavior { 20 | 21 | // 行为参数 和配置参数设置相同 22 | protected $options = array(); 23 | 24 | /** 25 | * 架构函数 26 | * @access public 27 | */ 28 | public function __construct() { 29 | if(!empty($this->options)) { 30 | foreach ($this->options as $name=>$val){ 31 | if(NULL !== C($name)) { // 参数已设置 则覆盖行为参数 32 | $this->options[$name] = C($name); 33 | }else{ // 参数未设置 则传入默认值到配置 34 | C($name,$val); 35 | } 36 | } 37 | array_change_key_case($this->options); 38 | } 39 | } 40 | 41 | // 获取行为参数 42 | public function __get($name){ 43 | return $this->options[strtolower($name)]; 44 | } 45 | 46 | /** 47 | * 执行行为 run方法是Behavior唯一的接口 48 | * @access public 49 | * @param mixed $params 行为参数 50 | * @return void 51 | */ 52 | abstract public function run(&$params); 53 | 54 | } -------------------------------------------------------------------------------- /framework/Tpl/think_exception.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 系统发生错误 5 | 21 | 22 | 23 |
    24 |

    :(

    25 |

    26 |
    27 | 28 |
    29 |
    30 |

    错误位置

    31 |
    32 |
    33 |

    FILE:  LINE:

    34 |
    35 |
    36 | 37 | 38 |
    39 |
    40 |

    TRACE

    41 |
    42 |
    43 |

    44 |
    45 |
    46 | 47 |
    48 |
    49 | 52 | 53 | -------------------------------------------------------------------------------- /app/Tpl/public/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 传统食物营养分析工具 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/Tpl/tools/gnball.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |

    供能比汇总 返回

    6 |

    7 |


    8 |
    9 | 10 |
    11 | 12 |
    13 | 14 |
    15 | 16 |
    17 | 18 |
    19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /framework/Lib/Behavior/ContentReplaceBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:模板内容输出替换 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class ContentReplaceBehavior extends Behavior { 21 | // 行为参数定义 22 | protected $options = array( 23 | 'TMPL_PARSE_STRING' => array(), 24 | ); 25 | 26 | // 行为扩展的执行入口必须是run 27 | public function run(&$content){ 28 | $content = $this->templateContentReplace($content); 29 | } 30 | 31 | /** 32 | * 模板内容替换 33 | * @access protected 34 | * @param string $content 模板内容 35 | * @return string 36 | */ 37 | protected function templateContentReplace($content) { 38 | // 系统默认的特殊变量替换 39 | $replace = array( 40 | '__TMPL__' => APP_TMPL_PATH, // 项目模板目录 41 | '__ROOT__' => __ROOT__, // 当前网站地址 42 | '__APP__' => __APP__, // 当前项目地址 43 | '__GROUP__' => defined('GROUP_NAME')?__GROUP__:__APP__, 44 | '__ACTION__' => __ACTION__, // 当前操作地址 45 | '__SELF__' => __SELF__, // 当前页面地址 46 | '__URL__' => __URL__, 47 | '../Public' => APP_TMPL_PATH.'Public',// 项目公共模板目录 48 | '__PUBLIC__' => __ROOT__.'/Public',// 站点公共目录 49 | ); 50 | // 允许用户自定义模板的字符串替换 51 | if(is_array(C('TMPL_PARSE_STRING')) ) 52 | $replace = array_merge($replace,C('TMPL_PARSE_STRING')); 53 | $content = str_replace(array_keys($replace),array_values($replace),$content); 54 | return $content; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /framework/Lib/Behavior/LocationTemplateBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:定位模板文件 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class LocationTemplateBehavior extends Behavior { 21 | // 行为扩展的执行入口必须是run 22 | public function run(&$templateFile){ 23 | // 自动定位模板文件 24 | if(!file_exists_case($templateFile)) 25 | $templateFile = $this->parseTemplateFile($templateFile); 26 | } 27 | 28 | /** 29 | * 自动定位模板文件 30 | * @access private 31 | * @param string $templateFile 文件名 32 | * @return string 33 | */ 34 | private function parseTemplateFile($templateFile) { 35 | if(''==$templateFile) { 36 | // 如果模板文件名为空 按照默认规则定位 37 | $templateFile = C('TEMPLATE_NAME'); 38 | }elseif(false === strpos($templateFile,C('TMPL_TEMPLATE_SUFFIX'))){ 39 | // 解析规则为 模板主题:模块:操作 不支持 跨项目和跨分组调用 40 | $path = explode(':',$templateFile); 41 | $action = array_pop($path); 42 | $module = !empty($path)?array_pop($path):MODULE_NAME; 43 | if(!empty($path)) {// 设置模板主题 44 | $path = dirname(THEME_PATH).'/'.array_pop($path).'/'; 45 | }else{ 46 | $path = THEME_PATH; 47 | } 48 | $depr = defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/'; 49 | $templateFile = $path.$module.$depr.$action.C('TMPL_TEMPLATE_SUFFIX'); 50 | } 51 | if(!file_exists_case($templateFile)) 52 | throw_exception(L('_TEMPLATE_NOT_EXIST_').'['.$templateFile.']'); 53 | return $templateFile; 54 | } 55 | } -------------------------------------------------------------------------------- /framework/Lang/zh-cn.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP 简体中文语言包 14 | * @category Think 15 | * @package Lang 16 | * @author liu21st 17 | */ 18 | return array( 19 | // 核心 20 | '_MODULE_NOT_EXIST_' => '无法加载模块', 21 | '_ERROR_ACTION_' => '非法操作', 22 | '_LANGUAGE_NOT_LOAD_' => '无法加载语言包', 23 | '_TEMPLATE_NOT_EXIST_' => '模板不存在', 24 | '_MODULE_' => '模块', 25 | '_ACTION_' => '操作', 26 | '_ACTION_NOT_EXIST_' => '控制器不存在或者没有定义', 27 | '_MODEL_NOT_EXIST_' => '模型不存在或者没有定义', 28 | '_VALID_ACCESS_' => '没有权限', 29 | '_XML_TAG_ERROR_' => 'XML标签语法错误', 30 | '_DATA_TYPE_INVALID_' => '非法数据对象!', 31 | '_OPERATION_WRONG_' => '操作出现错误', 32 | '_NOT_LOAD_DB_' => '无法加载数据库', 33 | '_NO_DB_DRIVER_' => '无法加载数据库驱动', 34 | '_NOT_SUPPORT_DB_' => '系统暂时不支持数据库', 35 | '_NO_DB_CONFIG_' => '没有定义数据库配置', 36 | '_NOT_SUPPERT_' => '系统不支持', 37 | '_CACHE_TYPE_INVALID_' => '无法加载缓存类型', 38 | '_FILE_NOT_WRITEABLE_' => '目录(文件)不可写', 39 | '_METHOD_NOT_EXIST_' => '您所请求的方法不存在!', 40 | '_CLASS_NOT_EXIST_' => '实例化一个不存在的类!', 41 | '_CLASS_CONFLICT_' => '类名冲突', 42 | '_TEMPLATE_ERROR_' => '模板引擎错误', 43 | '_CACHE_WRITE_ERROR_' => '缓存文件写入失败!', 44 | '_TAGLIB_NOT_EXIST_' => '标签库未定义', 45 | '_OPERATION_FAIL_' => '操作失败!', 46 | '_OPERATION_SUCCESS_' => '操作成功!', 47 | '_SELECT_NOT_EXIST_' => '记录不存在!', 48 | '_EXPRESS_ERROR_' => '表达式错误', 49 | '_TOKEN_ERROR_' => '表单令牌错误', 50 | '_RECORD_HAS_UPDATE_' => '记录已经更新', 51 | '_NOT_ALLOW_PHP_' => '模板禁用PHP代码', 52 | '_PARAM_ERROR_' => '参数错误或者未定义', 53 | ); -------------------------------------------------------------------------------- /app/Tpl/tools/gongnengbi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |

    单一食物供能比筛选 返回

    6 |

    符合健康膳食要求的单一食物,即蛋白:10%-15%,脂肪:20%-30%,碳水:55%-65%

    7 |


    8 | 24 | 25 |
    26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /framework/Lib/Behavior/TokenBuildBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:表单令牌生成 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class TokenBuildBehavior extends Behavior { 21 | // 行为参数定义 22 | protected $options = array( 23 | 'TOKEN_ON' => false, // 开启令牌验证 24 | 'TOKEN_NAME' => '__hash__', // 令牌验证的表单隐藏字段名称 25 | 'TOKEN_TYPE' => 'md5', // 令牌验证哈希规则 26 | 'TOKEN_RESET' => true, // 令牌错误后是否重置 27 | ); 28 | 29 | public function run(&$content){ 30 | if(C('TOKEN_ON')) { 31 | if(strpos($content,'{__TOKEN__}')) { 32 | // 指定表单令牌隐藏域位置 33 | $content = str_replace('{__TOKEN__}',$this->buildToken(),$content); 34 | }elseif(preg_match('/<\/form(\s*)>/is',$content,$match)) { 35 | // 智能生成表单令牌隐藏域 36 | $content = str_replace($match[0],$this->buildToken().$match[0],$content); 37 | } 38 | }else{ 39 | $content = str_replace('{__TOKEN__}','',$content); 40 | } 41 | } 42 | 43 | // 创建表单令牌 44 | private function buildToken() { 45 | $tokenName = C('TOKEN_NAME'); 46 | $tokenType = C('TOKEN_TYPE'); 47 | if(!isset($_SESSION[$tokenName])) { 48 | $_SESSION[$tokenName] = array(); 49 | } 50 | // 标识当前页面唯一性 51 | $tokenKey = md5($_SERVER['REQUEST_URI']); 52 | if(isset($_SESSION[$tokenName][$tokenKey])) {// 相同页面不重复生成session 53 | $tokenValue = $_SESSION[$tokenName][$tokenKey]; 54 | }else{ 55 | $tokenValue = $tokenType(microtime(TRUE)); 56 | $_SESSION[$tokenName][$tokenKey] = $tokenValue; 57 | } 58 | $token = ''; 59 | return $token; 60 | } 61 | } -------------------------------------------------------------------------------- /app/Lib/Action/checkAction.class.php: -------------------------------------------------------------------------------- 1 | display(); 10 | } 11 | 12 | 13 | public function test(){ 14 | 15 | 16 | $this->display(); 17 | } 18 | 19 | public function jsondata1(){ 20 | 21 | $fmod = M('foodnutrition'); 22 | 23 | 24 | $list = $fmod->field('name,shibu')->where($cc)->order('shibu desc')->select(); 25 | 26 | 27 | $this->ajaxReturn(array('code'=>200,'res'=>$list)); 28 | } 29 | 30 | public function jsondata2(){ 31 | 32 | $fmod = M('foodnutrition'); 33 | 34 | 35 | $list = $fmod->field('name,danbai')->where($cc)->order('danbai desc')->select(); 36 | 37 | 38 | $this->ajaxReturn(array('code'=>200,'res'=>$list)); 39 | } 40 | 41 | public function jsondata3(){ 42 | 43 | $fmod = M('foodnutrition'); 44 | 45 | 46 | $list = $fmod->field('name,zhifang')->where($cc)->order('zhifang desc')->select(); 47 | 48 | 49 | $this->ajaxReturn(array('code'=>200,'res'=>$list)); 50 | } 51 | 52 | public function jsondata4(){ 53 | 54 | $fmod = M('foodnutrition'); 55 | 56 | 57 | $list = $fmod->field('name,tanshui')->where($cc)->order('tanshui desc')->select(); 58 | 59 | 60 | $this->ajaxReturn(array('code'=>200,'res'=>$list)); 61 | } 62 | 63 | public function jsondata5(){ 64 | 65 | $fmod = M('foodnutrition'); 66 | 67 | 68 | $list = $fmod->field('name,xianwei')->where($cc)->order('xianwei desc')->select(); 69 | 70 | 71 | $this->ajaxReturn(array('code'=>200,'res'=>$list)); 72 | } 73 | 74 | public function jsondata6(){ 75 | 76 | $fmod = M('foodnutrition'); 77 | 78 | 79 | $list = $fmod->field('name,vc')->where($cc)->order('vc desc')->select(); 80 | 81 | foreach ($list as $key => $value) { 82 | # code... 83 | if(!$value['vc']){ 84 | $list[$key]['vc']=0; 85 | } 86 | } 87 | 88 | 89 | $this->ajaxReturn(array('code'=>200,'res'=>$list)); 90 | } 91 | 92 | 93 | 94 | 95 | 96 | 97 | public function fenbu1(){ 98 | 99 | $fmod = M('foodnutrition'); 100 | 101 | $list=$fmod->query('select * from yk_foodnutrition where leixing>=10 and leixing<=19'); 102 | dump(count($list));die; 103 | foreach ($list as $key => $value) { 104 | # code... 105 | 106 | } 107 | 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /app/Tpl/tools/baota.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |

    膳食宝塔实例 返回

    5 |

    6 |


    7 |
    8 |
    9 |

    本餐食物清单

    10 | 11 |
  • {$vo['name']} x {$vo['liang']}克
  • 12 |
    13 | 14 |
    15 |
    16 | 17 |
    18 |
    19 |
    20 | 21 |
    22 |
    23 |
    24 | 25 |
    26 |
    27 |
    28 | 29 |
    30 | 31 |
    32 | 33 |
    34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /framework/Lib/Core/ThinkException.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP系统异常基类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | class ThinkException extends Exception { 20 | 21 | /** 22 | * 异常类型 23 | * @var string 24 | * @access private 25 | */ 26 | private $type; 27 | 28 | // 是否存在多余调试信息 29 | private $extra; 30 | 31 | /** 32 | * 架构函数 33 | * @access public 34 | * @param string $message 异常信息 35 | */ 36 | public function __construct($message,$code=0,$extra=false) { 37 | parent::__construct($message,$code); 38 | $this->type = get_class($this); 39 | $this->extra = $extra; 40 | } 41 | 42 | /** 43 | * 异常输出 所有异常处理类均通过__toString方法输出错误 44 | * 每次异常都会写入系统日志 45 | * 该方法可以被子类重载 46 | * @access public 47 | * @return array 48 | */ 49 | public function __toString() { 50 | $trace = $this->getTrace(); 51 | if($this->extra) 52 | // 通过throw_exception抛出的异常要去掉多余的调试信息 53 | array_shift($trace); 54 | $this->class = isset($trace[0]['class'])?$trace[0]['class']:''; 55 | $this->function = isset($trace[0]['function'])?$trace[0]['function']:''; 56 | $this->file = $trace[0]['file']; 57 | $this->line = $trace[0]['line']; 58 | $file = file($this->file); 59 | $traceInfo = ''; 60 | $time = date('y-m-d H:i:m'); 61 | foreach($trace as $t) { 62 | $traceInfo .= '['.$time.'] '.$t['file'].' ('.$t['line'].') '; 63 | $traceInfo .= $t['class'].$t['type'].$t['function'].'('; 64 | $traceInfo .= implode(', ', $t['args']); 65 | $traceInfo .=")\n"; 66 | } 67 | $error['message'] = $this->message; 68 | $error['type'] = $this->type; 69 | $error['detail'] = L('_MODULE_').'['.MODULE_NAME.'] '.L('_ACTION_').'['.ACTION_NAME.']'."\n"; 70 | $error['detail'] .= ($this->line-2).': '.$file[$this->line-3]; 71 | $error['detail'] .= ($this->line-1).': '.$file[$this->line-2]; 72 | $error['detail'] .= ''.($this->line).': '.$file[$this->line-1].''; 73 | $error['detail'] .= ($this->line+1).': '.$file[$this->line]; 74 | $error['detail'] .= ($this->line+2).': '.$file[$this->line+1]; 75 | $error['class'] = $this->class; 76 | $error['function'] = $this->function; 77 | $error['file'] = $this->file; 78 | $error['line'] = $this->line; 79 | $error['trace'] = $traceInfo; 80 | 81 | // 记录 Exception 日志 82 | if(C('LOG_EXCEPTION_RECORD')) { 83 | Log::Write('('.$this->type.') '.$this->message); 84 | } 85 | return $error ; 86 | } 87 | } -------------------------------------------------------------------------------- /app/Tpl/datalist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |
    6 | 7 |
    8 |

    食物营养成分数据列表(每100克)

    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /framework/Lib/Behavior/ShowRuntimeBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:运行时间信息显示 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class ShowRuntimeBehavior extends Behavior { 21 | // 行为参数定义 22 | protected $options = array( 23 | 'SHOW_RUN_TIME' => false, // 运行时间显示 24 | 'SHOW_ADV_TIME' => false, // 显示详细的运行时间 25 | 'SHOW_DB_TIMES' => false, // 显示数据库查询和写入次数 26 | 'SHOW_CACHE_TIMES' => false, // 显示缓存操作次数 27 | 'SHOW_USE_MEM' => false, // 显示内存开销 28 | 'SHOW_LOAD_FILE' => false, // 显示加载文件数 29 | 'SHOW_FUN_TIMES' => false , // 显示函数调用次数 30 | ); 31 | 32 | // 行为扩展的执行入口必须是run 33 | public function run(&$content){ 34 | if(C('SHOW_RUN_TIME')){ 35 | if(false !== strpos($content,'{__NORUNTIME__}')) { 36 | $content = str_replace('{__NORUNTIME__}','',$content); 37 | }else{ 38 | $runtime = $this->showTime(); 39 | if(strpos($content,'{__RUNTIME__}')) 40 | $content = str_replace('{__RUNTIME__}',$runtime,$content); 41 | else 42 | $content .= $runtime; 43 | } 44 | }else{ 45 | $content = str_replace(array('{__NORUNTIME__}','{__RUNTIME__}'),'',$content); 46 | } 47 | } 48 | 49 | /** 50 | * 显示运行时间、数据库操作、缓存次数、内存使用信息 51 | * @access private 52 | * @return string 53 | */ 54 | private function showTime() { 55 | // 显示运行时间 56 | G('beginTime',$GLOBALS['_beginTime']); 57 | G('viewEndTime'); 58 | $showTime = 'Process: '.G('beginTime','viewEndTime').'s '; 59 | if(C('SHOW_ADV_TIME')) { 60 | // 显示详细运行时间 61 | $showTime .= '( Load:'.G('beginTime','loadTime').'s Init:'.G('loadTime','initTime').'s Exec:'.G('initTime','viewStartTime').'s Template:'.G('viewStartTime','viewEndTime').'s )'; 62 | } 63 | if(C('SHOW_DB_TIMES') && class_exists('Db',false) ) { 64 | // 显示数据库操作次数 65 | $showTime .= ' | DB :'.N('db_query').' queries '.N('db_write').' writes '; 66 | } 67 | if(C('SHOW_CACHE_TIMES') && class_exists('Cache',false)) { 68 | // 显示缓存读写次数 69 | $showTime .= ' | Cache :'.N('cache_read').' gets '.N('cache_write').' writes '; 70 | } 71 | if(MEMORY_LIMIT_ON && C('SHOW_USE_MEM')) { 72 | // 显示内存开销 73 | $showTime .= ' | UseMem:'. number_format((memory_get_usage() - $GLOBALS['_startUseMems'])/1024).' kb'; 74 | } 75 | if(C('SHOW_LOAD_FILE')) { 76 | $showTime .= ' | LoadFile:'.count(get_included_files()); 77 | } 78 | if(C('SHOW_FUN_TIMES')) { 79 | $fun = get_defined_functions(); 80 | $showTime .= ' | CallFun:'.count($fun['user']).','.count($fun['internal']); 81 | } 82 | return $showTime; 83 | } 84 | } -------------------------------------------------------------------------------- /framework/Lib/Core/Cache.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * 缓存管理类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | class Cache { 20 | 21 | /** 22 | * 是否连接 23 | * @var string 24 | * @access protected 25 | */ 26 | protected $connected ; 27 | 28 | /** 29 | * 操作句柄 30 | * @var string 31 | * @access protected 32 | */ 33 | protected $handler ; 34 | 35 | /** 36 | * 缓存连接参数 37 | * @var integer 38 | * @access protected 39 | */ 40 | protected $options = array(); 41 | 42 | /** 43 | * 连接缓存 44 | * @access public 45 | * @param string $type 缓存类型 46 | * @param array $options 配置数组 47 | * @return object 48 | */ 49 | public function connect($type='',$options=array()) { 50 | if(empty($type)) $type = C('DATA_CACHE_TYPE'); 51 | $type = strtolower(trim($type)); 52 | $class = 'Cache'.ucwords($type); 53 | if(is_file(CORE_PATH.'Driver/Cache/'.$class.'.class.php')) { 54 | // 内置驱动 55 | $path = CORE_PATH; 56 | }else{ // 扩展驱动 57 | $path = EXTEND_PATH; 58 | } 59 | if(require_cache($path.'Driver/Cache/'.$class.'.class.php')) 60 | $cache = new $class($options); 61 | else 62 | throw_exception(L('_CACHE_TYPE_INVALID_').':'.$type); 63 | return $cache; 64 | } 65 | 66 | public function __get($name) { 67 | return $this->get($name); 68 | } 69 | 70 | public function __set($name,$value) { 71 | return $this->set($name,$value); 72 | } 73 | 74 | public function __unset($name) { 75 | $this->rm($name); 76 | } 77 | public function setOptions($name,$value) { 78 | $this->options[$name] = $value; 79 | } 80 | 81 | public function getOptions($name) { 82 | return $this->options[$name]; 83 | } 84 | 85 | /** 86 | * 取得缓存类实例 87 | * @static 88 | * @access public 89 | * @return mixed 90 | */ 91 | static function getInstance() { 92 | $param = func_get_args(); 93 | return get_instance_of(__CLASS__,'connect',$param); 94 | } 95 | 96 | /** 97 | * 队列缓存 98 | * @access protected 99 | * @param string $key 队列名 100 | * @return mixed 101 | */ 102 | // 103 | protected function queue($key) { 104 | static $_handler = array( 105 | 'file' => array('F','F'), 106 | 'xcache'=> array('xcache_get','xcache_set'), 107 | 'apc' => array('apc_fetch','apc_store'), 108 | ); 109 | $queue = isset($this->options['queue'])?$this->options['queue']:'file'; 110 | $fun = $_handler[$queue]; 111 | $value = $fun[0]('think_queue'); 112 | if(!$value) { 113 | $value = array(); 114 | } 115 | // 进列 116 | array_push($value,$key); 117 | if(count($value) > $this->options['length']) { 118 | // 出列 119 | $key = array_shift($value); 120 | // 删除缓存 121 | $this->rm($key); 122 | } 123 | return $fun[1]('think_queue',$value); 124 | } 125 | } -------------------------------------------------------------------------------- /framework/Lib/Core/Widget.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP Widget类 抽象类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | abstract class Widget { 20 | 21 | // 使用的模板引擎 每个Widget可以单独配置不受系统影响 22 | protected $template = ''; 23 | 24 | /** 25 | * 渲染输出 render方法是Widget唯一的接口 26 | * 使用字符串返回 不能有任何输出 27 | * @access public 28 | * @param mixed $data 要渲染的数据 29 | * @return string 30 | */ 31 | abstract public function render($data); 32 | 33 | /** 34 | * 渲染模板输出 供render方法内部调用 35 | * @access public 36 | * @param string $templateFile 模板文件 37 | * @param mixed $var 模板变量 38 | * @return string 39 | */ 40 | protected function renderFile($templateFile='',$var='') { 41 | ob_start(); 42 | ob_implicit_flush(0); 43 | if(!file_exists_case($templateFile)){ 44 | // 自动定位模板文件 45 | $name = substr(get_class($this),0,-6); 46 | $filename = empty($templateFile)?$name:$templateFile; 47 | $templateFile = LIB_PATH.'Widget/'.$name.'/'.$filename.C('TMPL_TEMPLATE_SUFFIX'); 48 | if(!file_exists_case($templateFile)) 49 | throw_exception(L('_TEMPLATE_NOT_EXIST_').'['.$templateFile.']'); 50 | } 51 | $template = strtolower($this->template?$this->template:(C('TMPL_ENGINE_TYPE')?C('TMPL_ENGINE_TYPE'):'php')); 52 | if('php' == $template) { 53 | // 使用PHP模板 54 | if(!empty($var)) extract($var, EXTR_OVERWRITE); 55 | // 直接载入PHP模板 56 | include $templateFile; 57 | }elseif('think'==$template){ // 采用Think模板引擎 58 | if($this->checkCache($templateFile)) { // 缓存有效 59 | // 分解变量并载入模板缓存 60 | extract($var, EXTR_OVERWRITE); 61 | //载入模版缓存文件 62 | include C('CACHE_PATH').md5($templateFile).C('TMPL_CACHFILE_SUFFIX'); 63 | }else{ 64 | $tpl = Think::instance('ThinkTemplate'); 65 | // 编译并加载模板文件 66 | $tpl->fetch($templateFile,$var); 67 | } 68 | }else{ 69 | $class = 'Template'.ucwords($template); 70 | if(is_file(CORE_PATH.'Driver/Template/'.$class.'.class.php')) { 71 | // 内置驱动 72 | $path = CORE_PATH; 73 | }else{ // 扩展驱动 74 | $path = EXTEND_PATH; 75 | } 76 | require_cache($path.'Driver/Template/'.$class.'.class.php'); 77 | $tpl = new $class; 78 | $tpl->fetch($templateFile,$var); 79 | } 80 | $content = ob_get_clean(); 81 | return $content; 82 | } 83 | 84 | /** 85 | * 检查缓存文件是否有效 86 | * 如果无效则需要重新编译 87 | * @access public 88 | * @param string $tmplTemplateFile 模板文件名 89 | * @return boolen 90 | */ 91 | protected function checkCache($tmplTemplateFile) { 92 | if (!C('TMPL_CACHE_ON')) // 优先对配置设定检测 93 | return false; 94 | $tmplCacheFile = C('CACHE_PATH').md5($tmplTemplateFile).C('TMPL_CACHFILE_SUFFIX'); 95 | if(!is_file($tmplCacheFile)){ 96 | return false; 97 | }elseif (filemtime($tmplTemplateFile) > filemtime($tmplCacheFile)) { 98 | // 模板文件如果有更新则缓存需要更新 99 | return false; 100 | }elseif (C('TMPL_CACHE_TIME') != 0 && time() > filemtime($tmplCacheFile)+C('TMPL_CACHE_TIME')) { 101 | // 缓存是否在有效期 102 | return false; 103 | } 104 | // 缓存有效 105 | return true; 106 | } 107 | } -------------------------------------------------------------------------------- /framework/Lib/Core/View.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP 视图类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | class View { 20 | /** 21 | * 模板输出变量 22 | * @var tVar 23 | * @access protected 24 | */ 25 | protected $tVar = array(); 26 | 27 | /** 28 | * 模板变量赋值 29 | * @access public 30 | * @param mixed $name 31 | * @param mixed $value 32 | */ 33 | public function assign($name,$value=''){ 34 | if(is_array($name)) { 35 | $this->tVar = array_merge($this->tVar,$name); 36 | }else { 37 | $this->tVar[$name] = $value; 38 | } 39 | } 40 | 41 | /** 42 | * 取得模板变量的值 43 | * @access public 44 | * @param string $name 45 | * @return mixed 46 | */ 47 | public function get($name=''){ 48 | if('' === $name) { 49 | return $this->tVar; 50 | } 51 | return isset($this->tVar[$name])?$this->tVar[$name]:false; 52 | } 53 | 54 | /** 55 | * 加载模板和页面输出 可以返回输出内容 56 | * @access public 57 | * @param string $templateFile 模板文件名 58 | * @param string $charset 模板输出字符集 59 | * @param string $contentType 输出类型 60 | * @param string $content 模板输出内容 61 | * @return mixed 62 | */ 63 | public function display($templateFile='',$charset='',$contentType='',$content='') { 64 | G('viewStartTime'); 65 | // 视图开始标签 66 | tag('view_begin',$templateFile); 67 | // 解析并获取模板内容 68 | $content = $this->fetch($templateFile,$content); 69 | // 输出模板内容 70 | $this->render($content,$charset,$contentType); 71 | // 视图结束标签 72 | tag('view_end'); 73 | } 74 | 75 | /** 76 | * 输出内容文本可以包括Html 77 | * @access private 78 | * @param string $content 输出内容 79 | * @param string $charset 模板输出字符集 80 | * @param string $contentType 输出类型 81 | * @return mixed 82 | */ 83 | private function render($content,$charset='',$contentType=''){ 84 | if(empty($charset)) $charset = C('DEFAULT_CHARSET'); 85 | if(empty($contentType)) $contentType = C('TMPL_CONTENT_TYPE'); 86 | // 网页字符编码 87 | header('Content-Type:'.$contentType.'; charset='.$charset); 88 | header('Cache-control: '.C('HTTP_CACHE_CONTROL')); // 页面缓存控制 89 | header('X-Powered-By:YouGou'); 90 | // 输出模板文件 91 | echo $content; 92 | } 93 | 94 | /** 95 | * 解析和获取模板内容 用于输出 96 | * @access public 97 | * @param string $templateFile 模板文件名 98 | * @param string $content 模板输出内容 99 | * @return string 100 | */ 101 | public function fetch($templateFile='',$content='') { 102 | if(empty($content)) { 103 | // 模板文件解析标签 104 | tag('view_template',$templateFile); 105 | // 模板文件不存在直接返回 106 | if(!is_file($templateFile)) return NULL; 107 | } 108 | // 页面缓存 109 | ob_start(); 110 | ob_implicit_flush(0); 111 | if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板 112 | // 模板阵列变量分解成为独立变量 113 | extract($this->tVar, EXTR_OVERWRITE); 114 | // 直接载入PHP模板 115 | empty($content)?include $templateFile:eval('?>'.$content); 116 | }else{ 117 | // 视图解析标签 118 | $params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content); 119 | tag('view_parse',$params); 120 | } 121 | // 获取并清空缓存 122 | $content = ob_get_clean(); 123 | // 内容过滤标签 124 | tag('view_filter',$content); 125 | // 输出模板文件 126 | return $content; 127 | } 128 | } -------------------------------------------------------------------------------- /framework/Lib/Core/Log.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * 日志处理类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | class Log { 20 | 21 | // 日志级别 从上到下,由低到高 22 | const EMERG = 'EMERG'; // 严重错误: 导致系统崩溃无法使用 23 | const ALERT = 'ALERT'; // 警戒性错误: 必须被立即修改的错误 24 | const CRIT = 'CRIT'; // 临界值错误: 超过临界值的错误,例如一天24小时,而输入的是25小时这样 25 | const ERR = 'ERR'; // 一般错误: 一般性错误 26 | const WARN = 'WARN'; // 警告性错误: 需要发出警告的错误 27 | const NOTICE = 'NOTIC'; // 通知: 程序可以运行但是还不够完美的错误 28 | const INFO = 'INFO'; // 信息: 程序输出信息 29 | const DEBUG = 'DEBUG'; // 调试: 调试信息 30 | const SQL = 'SQL'; // SQL:SQL语句 注意只在调试模式开启时有效 31 | 32 | // 日志记录方式 33 | const SYSTEM = 0; 34 | const MAIL = 1; 35 | const FILE = 3; 36 | const SAPI = 4; 37 | 38 | // 日志信息 39 | static $log = array(); 40 | 41 | // 日期格式 42 | static $format = '[ c ]'; 43 | 44 | /** 45 | * 记录日志 并且会过滤未经设置的级别 46 | * @static 47 | * @access public 48 | * @param string $message 日志信息 49 | * @param string $level 日志级别 50 | * @param boolean $record 是否强制记录 51 | * @return void 52 | */ 53 | static function record($message,$level=self::ERR,$record=false) { 54 | if($record || false !== strpos(C('LOG_LEVEL'),$level)) { 55 | self::$log[] = "{$level}: {$message}\r\n"; 56 | } 57 | } 58 | 59 | /** 60 | * 日志保存 61 | * @static 62 | * @access public 63 | * @param integer $type 日志记录方式 64 | * @param string $destination 写入目标 65 | * @param string $extra 额外参数 66 | * @return void 67 | */ 68 | static function save($type='',$destination='',$extra='') { 69 | if(empty(self::$log)) return ; 70 | $type = $type?$type:C('LOG_TYPE'); 71 | if(self::FILE == $type) { // 文件方式记录日志信息 72 | if(empty($destination)) 73 | $destination = LOG_PATH.date('y_m_d').'.log'; 74 | //检测日志文件大小,超过配置大小则备份日志文件重新生成 75 | if(is_file($destination) && floor(C('LOG_FILE_SIZE')) <= filesize($destination) ) 76 | rename($destination,dirname($destination).'/'.time().'-'.basename($destination)); 77 | }else{ 78 | $destination = $destination?$destination:C('LOG_DEST'); 79 | $extra = $extra?$extra:C('LOG_EXTRA'); 80 | } 81 | $now = date(self::$format); 82 | error_log($now.' '.get_client_ip().' '.$_SERVER['REQUEST_URI']."\r\n".implode('',self::$log)."\r\n", $type,$destination ,$extra); 83 | // 保存后清空日志缓存 84 | self::$log = array(); 85 | //clearstatcache(); 86 | } 87 | 88 | /** 89 | * 日志直接写入 90 | * @static 91 | * @access public 92 | * @param string $message 日志信息 93 | * @param string $level 日志级别 94 | * @param integer $type 日志记录方式 95 | * @param string $destination 写入目标 96 | * @param string $extra 额外参数 97 | * @return void 98 | */ 99 | static function write($message,$level=self::ERR,$type='',$destination='',$extra='') { 100 | $now = date(self::$format); 101 | $type = $type?$type:C('LOG_TYPE'); 102 | if(self::FILE == $type) { // 文件方式记录日志 103 | if(empty($destination)) 104 | $destination = LOG_PATH.date('y_m_d').'.log'; 105 | //检测日志文件大小,超过配置大小则备份日志文件重新生成 106 | if(is_file($destination) && floor(C('LOG_FILE_SIZE')) <= filesize($destination) ) 107 | rename($destination,dirname($destination).'/'.time().'-'.basename($destination)); 108 | }else{ 109 | $destination = $destination?$destination:C('LOG_DEST'); 110 | $extra = $extra?$extra:C('LOG_EXTRA'); 111 | } 112 | error_log("{$now} {$level}: {$message}\r\n", $type,$destination,$extra ); 113 | //clearstatcache(); 114 | } 115 | } -------------------------------------------------------------------------------- /framework/Lib/Behavior/ParseTemplateBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:模板解析 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class ParseTemplateBehavior extends Behavior { 21 | // 行为参数定义(默认值) 可在项目配置中覆盖 22 | protected $options = array( 23 | // 布局设置 24 | 'TMPL_ENGINE_TYPE' => 'Think', // 默认模板引擎 以下设置仅对使用Think模板引擎有效 25 | 'TMPL_CACHFILE_SUFFIX' => '.php', // 默认模板缓存后缀 26 | 'TMPL_DENY_FUNC_LIST' => 'echo,exit', // 模板引擎禁用函数 27 | 'TMPL_DENY_PHP' => false, // 默认模板引擎是否禁用PHP原生代码 28 | 'TMPL_L_DELIM' => '{', // 模板引擎普通标签开始标记 29 | 'TMPL_R_DELIM' => '}', // 模板引擎普通标签结束标记 30 | 'TMPL_VAR_IDENTIFY' => 'array', // 模板变量识别。留空自动判断,参数为'obj'则表示对象 31 | 'TMPL_STRIP_SPACE' => true, // 是否去除模板文件里面的html空格与换行 32 | 'TMPL_CACHE_ON' => true, // 是否开启模板编译缓存,设为false则每次都会重新编译 33 | 'TMPL_CACHE_TIME' => 0, // 模板缓存有效期 0 为永久,(以数字为值,单位:秒) 34 | 'TMPL_LAYOUT_ITEM' => '{__CONTENT__}', // 布局模板的内容替换标识 35 | 'LAYOUT_ON' => false, // 是否启用布局 36 | 'LAYOUT_NAME' => 'layout', // 当前布局名称 默认为layout 37 | 38 | // Think模板引擎标签库相关设定 39 | 'TAGLIB_BEGIN' => '<', // 标签库标签开始标记 40 | 'TAGLIB_END' => '>', // 标签库标签结束标记 41 | 'TAGLIB_LOAD' => true, // 是否使用内置标签库之外的其它标签库,默认自动检测 42 | 'TAGLIB_BUILD_IN' => 'cx', // 内置标签库名称(标签使用不必指定标签库名称),以逗号分隔 注意解析顺序 43 | 'TAGLIB_PRE_LOAD' => '', // 需要额外加载的标签库(须指定标签库名称),多个以逗号分隔 44 | ); 45 | 46 | // 行为扩展的执行入口必须是run 47 | public function run(&$_data){ 48 | $engine = strtolower(C('TMPL_ENGINE_TYPE')); 49 | $_content = empty($_data['content'])?$_data['file']:$_data['content']; 50 | if('think'==$engine){ // 采用Think模板引擎 51 | if(empty($_data['content']) && $this->checkCache($_data['file'])) { // 缓存有效 52 | // 分解变量并载入模板缓存 53 | extract($_data['var'], EXTR_OVERWRITE); 54 | //载入模版缓存文件 55 | include C('CACHE_PATH').md5($_data['file']).C('TMPL_CACHFILE_SUFFIX'); 56 | }else{ 57 | $tpl = Think::instance('ThinkTemplate'); 58 | // 编译并加载模板文件 59 | $tpl->fetch($_content,$_data['var']); 60 | } 61 | }else{ 62 | // 调用第三方模板引擎解析和输出 63 | $class = 'Template'.ucwords($engine); 64 | if(is_file(CORE_PATH.'Driver/Template/'.$class.'.class.php')) { 65 | // 内置驱动 66 | $path = CORE_PATH; 67 | }else{ // 扩展驱动 68 | $path = EXTEND_PATH; 69 | } 70 | if(require_cache($path.'Driver/Template/'.$class.'.class.php')) { 71 | $tpl = new $class; 72 | $tpl->fetch($_content,$_data['var']); 73 | }else { // 类没有定义 74 | throw_exception(L('_NOT_SUPPERT_').': ' . $class); 75 | } 76 | } 77 | } 78 | 79 | /** 80 | * 检查缓存文件是否有效 81 | * 如果无效则需要重新编译 82 | * @access public 83 | * @param string $tmplTemplateFile 模板文件名 84 | * @return boolen 85 | */ 86 | protected function checkCache($tmplTemplateFile) { 87 | if (!C('TMPL_CACHE_ON')) // 优先对配置设定检测 88 | return false; 89 | $tmplCacheFile = C('CACHE_PATH').md5($tmplTemplateFile).C('TMPL_CACHFILE_SUFFIX'); 90 | if(!is_file($tmplCacheFile)){ 91 | return false; 92 | }elseif (filemtime($tmplTemplateFile) > filemtime($tmplCacheFile)) { 93 | // 模板文件如果有更新则缓存需要更新 94 | return false; 95 | }elseif (C('TMPL_CACHE_TIME') != 0 && time() > filemtime($tmplCacheFile)+C('TMPL_CACHE_TIME')) { 96 | // 缓存是否在有效期 97 | return false; 98 | } 99 | // 开启布局模板 100 | if(C('LAYOUT_ON')) { 101 | $layoutFile = THEME_PATH.C('LAYOUT_NAME').C('TMPL_TEMPLATE_SUFFIX'); 102 | if(filemtime($layoutFile) > filemtime($tmplCacheFile)) { 103 | return false; 104 | } 105 | } 106 | // 缓存有效 107 | return true; 108 | } 109 | } -------------------------------------------------------------------------------- /framework/Tpl/page_trace.tpl: -------------------------------------------------------------------------------- 1 |
    2 | 24 | 25 |
    26 |
    27 | -------------------------------------------------------------------------------- /framework/Lib/Behavior/ReadHtmlCacheBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:静态缓存读取 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class ReadHtmlCacheBehavior extends Behavior { 21 | protected $options = array( 22 | 'HTML_CACHE_ON' => false, 23 | 'HTML_CACHE_TIME' => 60, 24 | 'HTML_CACHE_RULES' => array(), 25 | 'HTML_FILE_SUFFIX' => '.html', 26 | ); 27 | 28 | // 行为扩展的执行入口必须是run 29 | public function run(&$params){ 30 | // 开启静态缓存 31 | if(C('HTML_CACHE_ON')) { 32 | $cacheTime = $this->requireHtmlCache(); 33 | if( false !== $cacheTime && $this->checkHTMLCache(HTML_FILE_NAME,$cacheTime)) { //静态页面有效 34 | // 读取静态页面输出 35 | readfile(HTML_FILE_NAME); 36 | exit(); 37 | } 38 | } 39 | } 40 | 41 | // 判断是否需要静态缓存 42 | static private function requireHtmlCache() { 43 | // 分析当前的静态规则 44 | $htmls = C('HTML_CACHE_RULES'); // 读取静态规则 45 | if(!empty($htmls)) { 46 | $htmls = array_change_key_case($htmls); 47 | // 静态规则文件定义格式 actionName=>array('静态规则','缓存时间','附加规则') 48 | // 'read'=>array('{id},{name}',60,'md5') 必须保证静态规则的唯一性 和 可判断性 49 | // 检测静态规则 50 | $moduleName = strtolower(MODULE_NAME); 51 | $actionName = strtolower(ACTION_NAME); 52 | if(isset($htmls[$moduleName.':'.$actionName])) { 53 | $html = $htmls[$moduleName.':'.$actionName]; // 某个模块的操作的静态规则 54 | }elseif(isset($htmls[$moduleName.':'])){// 某个模块的静态规则 55 | $html = $htmls[$moduleName.':']; 56 | }elseif(isset($htmls[$actionName])){ 57 | $html = $htmls[$actionName]; // 所有操作的静态规则 58 | }elseif(isset($htmls['*'])){ 59 | $html = $htmls['*']; // 全局静态规则 60 | }elseif(isset($htmls['empty:index']) && !class_exists(MODULE_NAME.'Action')){ 61 | $html = $htmls['empty:index']; // 空模块静态规则 62 | }elseif(isset($htmls[$moduleName.':_empty']) && $this->isEmptyAction(MODULE_NAME,ACTION_NAME)){ 63 | $html = $htmls[$moduleName.':_empty']; // 空操作静态规则 64 | } 65 | if(!empty($html)) { 66 | // 解读静态规则 67 | $rule = $html[0]; 68 | // 以$_开头的系统变量 69 | $rule = preg_replace('/{\$(_\w+)\.(\w+)\|(\w+)}/e',"\\3(\$\\1['\\2'])",$rule); 70 | $rule = preg_replace('/{\$(_\w+)\.(\w+)}/e',"\$\\1['\\2']",$rule); 71 | // {ID|FUN} GET变量的简写 72 | $rule = preg_replace('/{(\w+)\|(\w+)}/e',"\\2(\$_GET['\\1'])",$rule); 73 | $rule = preg_replace('/{(\w+)}/e',"\$_GET['\\1']",$rule); 74 | // 特殊系统变量 75 | $rule = str_ireplace( 76 | array('{:app}','{:module}','{:action}','{:group}'), 77 | array(APP_NAME,MODULE_NAME,ACTION_NAME,defined('GROUP_NAME')?GROUP_NAME:''), 78 | $rule); 79 | // {|FUN} 单独使用函数 80 | $rule = preg_replace('/{|(\w+)}/e',"\\1()",$rule); 81 | if(!empty($html[2])) $rule = $html[2]($rule); // 应用附加函数 82 | $cacheTime = isset($html[1])?$html[1]:C('HTML_CACHE_TIME'); // 缓存有效期 83 | // 当前缓存文件 84 | define('HTML_FILE_NAME',HTML_PATH . $rule.C('HTML_FILE_SUFFIX')); 85 | return $cacheTime; 86 | } 87 | } 88 | // 无需缓存 89 | return false; 90 | } 91 | 92 | /** 93 | * 检查静态HTML文件是否有效 94 | * 如果无效需要重新更新 95 | * @access public 96 | * @param string $cacheFile 静态文件名 97 | * @param integer $cacheTime 缓存有效期 98 | * @return boolen 99 | */ 100 | static public function checkHTMLCache($cacheFile='',$cacheTime='') { 101 | if(!is_file($cacheFile)){ 102 | return false; 103 | }elseif (filemtime(C('TEMPLATE_NAME')) > filemtime($cacheFile)) { 104 | // 模板文件如果更新静态文件需要更新 105 | return false; 106 | }elseif(!is_numeric($cacheTime) && function_exists($cacheTime)){ 107 | return $cacheTime($cacheFile); 108 | }elseif ($cacheTime != 0 && NOW_TIME > filemtime($cacheFile)+$cacheTime) { 109 | // 文件是否在有效期 110 | return false; 111 | } 112 | //静态文件有效 113 | return true; 114 | } 115 | 116 | //检测是否是空操作 117 | static private function isEmptyAction($module,$action) { 118 | $className = $module.'Action'; 119 | $class = new $className; 120 | return !method_exists($class,$action); 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /framework/Lib/Behavior/ShowPageTraceBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:页面Trace显示输出 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class ShowPageTraceBehavior extends Behavior { 21 | // 行为参数定义 22 | protected $options = array( 23 | 'SHOW_PAGE_TRACE' => false, // 显示页面Trace信息 24 | 'TRACE_PAGE_TABS' => array('BASE'=>'基本','FILE'=>'文件','INFO'=>'流程','ERR|NOTIC'=>'错误','SQL'=>'SQL','DEBUG'=>'调试'), // 页面Trace可定制的选项卡 25 | 'PAGE_TRACE_SAVE' => false, 26 | ); 27 | 28 | // 行为扩展的执行入口必须是run 29 | public function run(&$params){ 30 | if(!IS_AJAX && C('SHOW_PAGE_TRACE')) { 31 | echo $this->showTrace(); 32 | } 33 | } 34 | 35 | /** 36 | * 显示页面Trace信息 37 | * @access private 38 | */ 39 | private function showTrace() { 40 | // 系统默认显示信息 41 | $files = get_included_files(); 42 | $info = array(); 43 | foreach ($files as $key=>$file){ 44 | $info[] = $file.' ( '.number_format(filesize($file)/1024,2).' KB )'; 45 | } 46 | $trace = array(); 47 | $base = array( 48 | '请求信息' => date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']).' '.$_SERVER['SERVER_PROTOCOL'].' '.$_SERVER['REQUEST_METHOD'].' : '.__SELF__, 49 | '运行时间' => $this->showTime(), 50 | '内存开销' => MEMORY_LIMIT_ON?number_format((memory_get_usage() - $GLOBALS['_startUseMems'])/1024,2).' kb':'不支持', 51 | '查询信息' => N('db_query').' queries '.N('db_write').' writes ', 52 | '文件加载' => count(get_included_files()), 53 | '缓存信息' => N('cache_read').' gets '.N('cache_write').' writes ', 54 | '配置加载' => count(c()), 55 | '会话信息' => 'SESSION_ID='.session_id(), 56 | ); 57 | // 读取项目定义的Trace文件 58 | $traceFile = CONF_PATH.'trace.php'; 59 | if(is_file($traceFile)) { 60 | $base = array_merge($base,include $traceFile); 61 | } 62 | $debug = trace(); 63 | $tabs = C('TRACE_PAGE_TABS'); 64 | foreach ($tabs as $name=>$title){ 65 | switch(strtoupper($name)) { 66 | case 'BASE':// 基本信息 67 | $trace[$title] = $base; 68 | break; 69 | case 'FILE': // 文件信息 70 | $trace[$title] = $info; 71 | break; 72 | default:// 调试信息 73 | if(strpos($name,'|')) {// 多组信息 74 | $array = explode('|',$name); 75 | $result = array(); 76 | foreach($array as $name){ 77 | $result += isset($debug[$name])?$debug[$name]:array(); 78 | } 79 | $trace[$title] = $result; 80 | }else{ 81 | $trace[$title] = isset($debug[$name])?$debug[$name]:''; 82 | } 83 | } 84 | } 85 | if($save = C('PAGE_TRACE_SAVE')) { // 保存页面Trace日志 86 | if(is_array($save)) {// 选择选项卡保存 87 | $tabs = C('TRACE_PAGE_TABS'); 88 | $array = array(); 89 | foreach ($save as $tab){ 90 | $array[] = $tabs[$tab]; 91 | } 92 | } 93 | $content = date('[ c ]').' '.get_client_ip().' '.$_SERVER['REQUEST_URI']."\r\n"; 94 | foreach ($trace as $key=>$val){ 95 | if(!isset($array) || in_array($key,$array)) { 96 | $content .= '[ '.$key." ]\r\n"; 97 | if(is_array($val)) { 98 | foreach ($val as $k=>$v){ 99 | $content .= (!is_numeric($k)?$k.':':'').print_r($v,true)."\r\n"; 100 | } 101 | }else{ 102 | $content .= print_r($val,true)."\r\n"; 103 | } 104 | $content .= "\r\n"; 105 | } 106 | } 107 | error_log(str_replace('
    ',"\r\n",$content), Log::FILE,LOG_PATH.date('y_m_d').'_trace.log'); 108 | } 109 | unset($files,$info,$log,$base); 110 | // 调用Trace页面模板 111 | ob_start(); 112 | include C('TMPL_TRACE_FILE')?C('TMPL_TRACE_FILE'):THINK_PATH.'Tpl/page_trace.tpl'; 113 | return ob_get_clean(); 114 | } 115 | 116 | /** 117 | * 获取运行时间 118 | */ 119 | private function showTime() { 120 | // 显示运行时间 121 | G('beginTime',$GLOBALS['_beginTime']); 122 | G('viewEndTime'); 123 | // 显示详细运行时间 124 | return G('beginTime','viewEndTime').'s ( Load:'.G('beginTime','loadTime').'s Init:'.G('loadTime','initTime').'s Exec:'.G('initTime','viewStartTime').'s Template:'.G('viewStartTime','viewEndTime').'s )'; 125 | } 126 | } -------------------------------------------------------------------------------- /framework/Lib/Driver/Cache/CacheFile.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 文件类型缓存类 15 | * @category Think 16 | * @package Think 17 | * @subpackage Driver.Cache 18 | * @author liu21st 19 | */ 20 | class CacheFile extends Cache { 21 | 22 | /** 23 | * 缓存存储前缀 24 | * @var string 25 | * @access protected 26 | */ 27 | protected $prefix = '~@'; 28 | 29 | /** 30 | * 架构函数 31 | * @access public 32 | */ 33 | public function __construct($options='') { 34 | if(!empty($options)) { 35 | $this->options = $options; 36 | } 37 | $this->options['temp'] = !empty($options['temp'])?$options['temp']:C('DATA_CACHE_PATH'); 38 | $this->options['expire'] = isset($options['expire'])?$options['expire']:C('DATA_CACHE_TIME'); 39 | $this->options['length'] = isset($options['length'])?$options['length']:0; 40 | if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; 41 | $this->connected = is_dir($this->options['temp']) && is_writeable($this->options['temp']); 42 | $this->init(); 43 | } 44 | 45 | /** 46 | * 初始化检查 47 | * @access private 48 | * @return boolen 49 | */ 50 | private function init() { 51 | $stat = stat($this->options['temp']); 52 | $dir_perms = $stat['mode'] & 0007777; // Get the permission bits. 53 | $file_perms = $dir_perms & 0000666; // Remove execute bits for files. 54 | 55 | // 创建项目缓存目录 56 | if (!is_dir($this->options['temp'])) { 57 | if (! mkdir($this->options['temp'])) 58 | return false; 59 | chmod($this->options['temp'], $dir_perms); 60 | } 61 | } 62 | 63 | /** 64 | * 是否连接 65 | * @access public 66 | * @return boolen 67 | */ 68 | private function isConnected() { 69 | return $this->connected; 70 | } 71 | 72 | /** 73 | * 取得变量的存储文件名 74 | * @access private 75 | * @param string $name 缓存变量名 76 | * @return string 77 | */ 78 | private function filename($name) { 79 | $name = md5($name); 80 | if(C('DATA_CACHE_SUBDIR')) { 81 | // 使用子目录 82 | $dir =''; 83 | for($i=0;$ioptions['temp'].$dir)) { 87 | mkdir($this->options['temp'].$dir,0777,true); 88 | } 89 | $filename = $dir.$this->prefix.$name.'.php'; 90 | }else{ 91 | $filename = $this->prefix.$name.'.php'; 92 | } 93 | return $this->options['temp'].$filename; 94 | } 95 | 96 | /** 97 | * 读取缓存 98 | * @access public 99 | * @param string $name 缓存变量名 100 | * @return mixed 101 | */ 102 | public function get($name) { 103 | $filename = $this->filename($name); 104 | if (!$this->isConnected() || !is_file($filename)) { 105 | return false; 106 | } 107 | N('cache_read',1); 108 | $content = file_get_contents($filename); 109 | if( false !== $content) { 110 | $expire = (int)substr($content,8, 12); 111 | if($expire != 0 && time() > filemtime($filename) + $expire) { 112 | //缓存过期删除缓存文件 113 | unlink($filename); 114 | return false; 115 | } 116 | if(C('DATA_CACHE_CHECK')) {//开启数据校验 117 | $check = substr($content,20, 32); 118 | $content = substr($content,52, -3); 119 | if($check != md5($content)) {//校验错误 120 | return false; 121 | } 122 | }else { 123 | $content = substr($content,20, -3); 124 | } 125 | if(C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) { 126 | //启用数据压缩 127 | $content = gzuncompress($content); 128 | } 129 | $content = unserialize($content); 130 | return $content; 131 | } 132 | else { 133 | return false; 134 | } 135 | } 136 | 137 | /** 138 | * 写入缓存 139 | * @access public 140 | * @param string $name 缓存变量名 141 | * @param mixed $value 存储数据 142 | * @param int $expire 有效时间 0为永久 143 | * @return boolen 144 | */ 145 | public function set($name,$value,$expire=null) { 146 | N('cache_write',1); 147 | if(is_null($expire)) { 148 | $expire = $this->options['expire']; 149 | } 150 | $filename = $this->filename($name); 151 | $data = serialize($value); 152 | if( C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) { 153 | //数据压缩 154 | $data = gzcompress($data,3); 155 | } 156 | if(C('DATA_CACHE_CHECK')) {//开启数据校验 157 | $check = md5($data); 158 | }else { 159 | $check = ''; 160 | } 161 | $data = ""; 162 | $result = file_put_contents($filename,$data); 163 | if($result) { 164 | if($this->options['length']>0) { 165 | // 记录缓存队列 166 | $this->queue($name); 167 | } 168 | clearstatcache(); 169 | return true; 170 | }else { 171 | return false; 172 | } 173 | } 174 | 175 | /** 176 | * 删除缓存 177 | * @access public 178 | * @param string $name 缓存变量名 179 | * @return boolen 180 | */ 181 | public function rm($name) { 182 | return unlink($this->filename($name)); 183 | } 184 | 185 | /** 186 | * 清除缓存 187 | * @access public 188 | * @param string $name 缓存变量名 189 | * @return boolen 190 | */ 191 | public function clear() { 192 | $path = $this->options['temp']; 193 | if ( $dir = opendir( $path ) ) { 194 | while ( $file = readdir( $dir ) ) { 195 | $check = is_dir( $file ); 196 | if ( !$check ) 197 | unlink( $path . $file ); 198 | } 199 | closedir( $dir ); 200 | return true; 201 | } 202 | } 203 | } -------------------------------------------------------------------------------- /framework/Conf/convention.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP惯例配置文件 14 | * 该文件请不要修改,如果要覆盖惯例配置的值,可在项目配置文件中设定和惯例不符的配置项 15 | * 配置名称大小写任意,系统会统一转换成小写 16 | * 所有配置参数都可以在生效前动态改变 17 | * @category Think 18 | * @package Common 19 | * @author liu21st 20 | * @version $Id: convention.php 3088 2012-07-29 09:12:19Z luofei614@gmail.com $ 21 | */ 22 | defined('THINK_PATH') or exit(); 23 | return array( 24 | /* 项目设定 */ 25 | 'APP_STATUS' => 'debug', // 应用调试模式状态 调试模式开启后有效 默认为debug 可扩展 并自动加载对应的配置文件 26 | 'APP_FILE_CASE' => false, // 是否检查文件的大小写 对Windows平台有效 27 | 'APP_AUTOLOAD_PATH' => '',// 自动加载机制的自动搜索路径,注意搜索顺序 28 | 'APP_TAGS_ON' => true, // 系统标签扩展开关 29 | 'APP_SUB_DOMAIN_DEPLOY' => false, // 是否开启子域名部署 30 | 'APP_SUB_DOMAIN_RULES' => array(), // 子域名部署规则 31 | 'APP_SUB_DOMAIN_DENY' => array(), // 子域名禁用列表 32 | 'APP_GROUP_LIST' => '', // 项目分组设定,多个组之间用逗号分隔,例如'Home,Admin' 33 | 'ACTION_SUFFIX' => '', // 操作方法后缀 34 | 35 | /* Cookie设置 */ 36 | 'COOKIE_EXPIRE' => 0, // Coodie有效期 37 | 'COOKIE_DOMAIN' => '', // Cookie有效域名 38 | 'COOKIE_PATH' => '/', // Cookie路径 39 | 'COOKIE_PREFIX' => '', // Cookie前缀 避免冲突 40 | 41 | /* 默认设定 */ 42 | 'DEFAULT_M_LAYER' => 'Model', // 默认的模型层名称 43 | 'DEFAULT_C_LAYER' => 'Action', // 默认的控制器层名称 44 | 'DEFAULT_APP' => '@', // 默认项目名称,@表示当前项目 45 | 'DEFAULT_LANG' => 'zh-cn', // 默认语言 46 | 'DEFAULT_THEME' => '', // 默认模板主题名称 47 | 'DEFAULT_GROUP' => 'Home', // 默认分组 48 | 'DEFAULT_MODULE' => 'Index', // 默认模块名称 49 | 'DEFAULT_ACTION' => 'index', // 默认操作名称 50 | 'DEFAULT_CHARSET' => 'utf-8', // 默认输出编码 51 | 'DEFAULT_TIMEZONE' => 'PRC', // 默认时区 52 | 'DEFAULT_AJAX_RETURN' => 'JSON', // 默认AJAX 数据返回格式,可选JSON XML ... 53 | 'DEFAULT_FILTER' => 'htmlspecialchars', // 默认参数过滤方法 用于 $this->_get('变量名');$this->_post('变量名')... 54 | 55 | /* 数据库设置 */ 56 | 'DB_TYPE' => 'mysql', // 数据库类型 57 | 'DB_HOST' => 'localhost', // 服务器地址 58 | 'DB_NAME' => '', // 数据库名 59 | 'DB_USER' => 'root', // 用户名 60 | 'DB_PWD' => '', // 密码 61 | 'DB_PORT' => '', // 端口 62 | 'DB_PREFIX' => 'think_', // 数据库表前缀 63 | 'DB_FIELDTYPE_CHECK' => false, // 是否进行字段类型检查 64 | 'DB_FIELDS_CACHE' => true, // 启用字段缓存 65 | 'DB_CHARSET' => 'utf8', // 数据库编码默认采用utf8 66 | 'DB_DEPLOY_TYPE' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 67 | 'DB_RW_SEPARATE' => false, // 数据库读写是否分离 主从式有效 68 | 'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量 69 | 'DB_SLAVE_NO' => '', // 指定从服务器序号 70 | 'DB_SQL_BUILD_CACHE' => false, // 数据库查询的SQL创建缓存 71 | 'DB_SQL_BUILD_QUEUE' => 'file', // SQL缓存队列的缓存方式 支持 file xcache和apc 72 | 'DB_SQL_BUILD_LENGTH' => 20, // SQL缓存的队列长度 73 | 'DB_SQL_LOG' => false, // SQL执行日志记录 74 | 75 | /* 数据缓存设置 */ 76 | 'DATA_CACHE_TIME' => 0, // 数据缓存有效期 0表示永久缓存 77 | 'DATA_CACHE_COMPRESS' => false, // 数据缓存是否压缩缓存 78 | 'DATA_CACHE_CHECK' => false, // 数据缓存是否校验缓存 79 | 'DATA_CACHE_TYPE' => 'File', // 数据缓存类型,支持:File|Db|Apc|Memcache|Shmop|Sqlite|Xcache|Apachenote|Eaccelerator 80 | 'DATA_CACHE_PATH' => TEMP_PATH,// 缓存路径设置 (仅对File方式缓存有效) 81 | 'DATA_CACHE_SUBDIR' => false, // 使用子目录缓存 (自动根据缓存标识的哈希创建子目录) 82 | 'DATA_PATH_LEVEL' => 1, // 子目录缓存级别 83 | 84 | /* 错误设置 */ 85 | 'ERROR_MESSAGE' => '页面错误!请稍后再试~',//错误显示信息,非调试模式有效 86 | 'ERROR_PAGE' => '', // 错误定向页面 87 | 'SHOW_ERROR_MSG' => false, // 显示错误信息 88 | 89 | /* 日志设置 */ 90 | 'LOG_RECORD' => false, // 默认不记录日志 91 | 'LOG_TYPE' => 3, // 日志记录类型 0 系统 1 邮件 3 文件 4 SAPI 默认为文件方式 92 | 'LOG_DEST' => '', // 日志记录目标 93 | 'LOG_EXTRA' => '', // 日志记录额外信息 94 | 'LOG_LEVEL' => 'EMERG,ALERT,CRIT,ERR',// 允许记录的日志级别 95 | 'LOG_FILE_SIZE' => 2097152, // 日志文件大小限制 96 | 'LOG_EXCEPTION_RECORD' => false, // 是否记录异常信息日志 97 | 98 | /* SESSION设置 */ 99 | 'SESSION_AUTO_START' => true, // 是否自动开启Session 100 | 'SESSION_OPTIONS' => array(), // session 配置数组 支持type name id path expire domian 等参数 101 | 'SESSION_TYPE' => '', // session hander类型 默认无需设置 除非扩展了session hander驱动 102 | 'SESSION_PREFIX' => '', // session 前缀 103 | //'VAR_SESSION_ID' => 'session_id', //sessionID的提交变量 104 | 105 | /* 模板引擎设置 */ 106 | 'TMPL_CONTENT_TYPE' => 'text/html', // 默认模板输出类型 107 | 'TMPL_ACTION_ERROR' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认错误跳转对应的模板文件 108 | 'TMPL_ACTION_SUCCESS' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认成功跳转对应的模板文件 109 | 'TMPL_EXCEPTION_FILE' => THINK_PATH.'Tpl/think_exception.tpl',// 异常页面的模板文件 110 | 'TMPL_DETECT_THEME' => false, // 自动侦测模板主题 111 | 'TMPL_TEMPLATE_SUFFIX' => '.html', // 默认模板文件后缀 112 | 'TMPL_FILE_DEPR' => '/', //模板文件MODULE_NAME与ACTION_NAME之间的分割符,只对项目分组部署有效 113 | 114 | /* URL设置 */ 115 | 'URL_CASE_INSENSITIVE' => false, // 默认false 表示URL区分大小写 true则表示不区分大小写 116 | 'URL_MODEL' => 1, // URL访问模式,可选参数0、1、2、3,代表以下四种模式: 117 | // 0 (普通模式); 1 (PATHINFO 模式); 2 (REWRITE 模式); 3 (兼容模式) 默认为PATHINFO 模式,提供最好的用户体验和SEO支持 118 | 'URL_PATHINFO_DEPR' => '/', // PATHINFO模式下,各参数之间的分割符号 119 | 'URL_PATHINFO_FETCH' => 'ORIG_PATH_INFO,REDIRECT_PATH_INFO,REDIRECT_URL', // 用于兼容判断PATH_INFO 参数的SERVER替代变量列表 120 | 'URL_HTML_SUFFIX' => '', // URL伪静态后缀设置 121 | 'URL_PARAMS_BIND' => true, // URL变量绑定到Action方法参数 122 | 123 | /* 系统变量名称设置 */ 124 | 'VAR_GROUP' => 'g', // 默认分组获取变量 125 | 'VAR_MODULE' => 'm', // 默认模块获取变量 126 | 'VAR_ACTION' => 'a', // 默认操作获取变量 127 | 'VAR_AJAX_SUBMIT' => 'ajax', // 默认的AJAX提交变量 128 | 'VAR_PATHINFO' => 's', // PATHINFO 兼容模式获取变量例如 ?s=/module/action/id/1 后面的参数取决于URL_PATHINFO_DEPR 129 | 'VAR_URL_PARAMS' => '_URL_', // PATHINFO URL参数变量 130 | 'VAR_TEMPLATE' => 't', // 默认模板切换变量 131 | 'VAR_FILTERS' => '', // 全局系统变量的默认过滤方法 多个用逗号分割 132 | 133 | 'OUTPUT_ENCODE' => true, // 页面压缩输出 134 | 'HTTP_CACHE_CONTROL' => 'private', // 网页缓存控制 135 | 136 | ); -------------------------------------------------------------------------------- /app/Lib/Action/toolsAction.class.php: -------------------------------------------------------------------------------- 1 | display(); 6 | } 7 | 8 | public function gongnengbi(){ 9 | $fmod = M('foodnutrition'); 10 | 11 | 12 | $list = $fmod->where($cc)->order('id desc')->select(); 13 | 14 | $superfood=array(); 15 | 16 | foreach ($list as $key => $value) { 17 | # code... 18 | $bili=$this->gnb($value['danbai'],$value['zhifang'],$value['tanshui']); 19 | 20 | if($bili['danbai']>=0.1 && $bili['danbai']<=0.15 && $bili['zhifang']>=0.2 && $bili['zhifang']<=0.3 && $bili['tanshui']>=0.55 && $bili['tanshui']<=0.65){ 21 | $value['name']=$value['name'].'('.$bili['danbai'].'-'.$bili['zhifang'].'-'.$bili['tanshui'].')'; 22 | array_push($superfood, $value); 23 | } 24 | } 25 | // dump($superfood); die; 26 | 27 | $this->assign('list', $superfood); 28 | 29 | $this->display(); 30 | } 31 | 32 | public function gnb_data(){ 33 | $fid=$this->_request('fid', 'intval'); 34 | $info=M('foodnutrition')->field('name,danbai,zhifang,tanshui')->find($fid); 35 | 36 | $res_dd=array(); 37 | $data['name']='蛋白质'; 38 | $data['value']=$info['danbai']*4; 39 | array_push($res_dd, $data); 40 | 41 | $data['name']='脂肪'; 42 | $data['value']=$info['zhifang']*9; 43 | array_push($res_dd, $data); 44 | 45 | $data['name']='碳水化合物'; 46 | $data['value']=$info['tanshui']*4; 47 | array_push($res_dd, $data); 48 | 49 | $res['dd']=$res_dd; 50 | $res['fname']=$info['name']; 51 | 52 | 53 | $this->ajaxReturn(array('code'=>200,'res'=>$res)); 54 | } 55 | 56 | public function hongdie(){ 57 | 58 | $this->display(); 59 | 60 | } 61 | 62 | public function hongdie_getdata(){ 63 | 64 | $fmod = M('foodnutrition'); 65 | 66 | 67 | $list = $fmod->field('name,danbai,zhifang,tanshui')->where($cc)->order('danbai desc')->select(); 68 | 69 | 70 | $res['name']=array(); 71 | $danbai=array(); 72 | $zhifang=array(); 73 | $tanshui=array(); 74 | 75 | foreach ($list as $key => $value) { 76 | # code... 77 | array_push($res['name'], $value['name']); 78 | array_push($danbai,$value['danbai']); 79 | array_push($zhifang,$value['zhifang']); 80 | array_push($tanshui,$value['tanshui']); 81 | } 82 | 83 | $res['hong'][0]['name']='蛋白质'; 84 | $res['hong'][0]['type']='line'; 85 | // $res['hong'][0]['stack']='含量'; 86 | $res['hong'][0]['data']=$danbai; 87 | 88 | $res['hong'][1]['name']='脂肪'; 89 | $res['hong'][1]['type']='line'; 90 | // $res['hong'][1]['stack']='含量'; 91 | $res['hong'][1]['data']=$zhifang; 92 | 93 | $res['hong'][2]['name']='碳水'; 94 | $res['hong'][2]['type']='line'; 95 | // $res['hong'][2]['stack']='含量'; 96 | $res['hong'][2]['data']=$tanshui; 97 | 98 | 99 | $this->ajaxReturn(array('code'=>200,'res'=>$res)); 100 | } 101 | 102 | 103 | public function gnball(){ 104 | 105 | $this->display(); 106 | 107 | } 108 | 109 | 110 | public function gnball_data(){ 111 | 112 | $fmod = M('foodnutrition'); 113 | 114 | 115 | $list = $fmod->field('name,danbai,zhifang,tanshui')->where($cc)->order('danbai desc')->select(); 116 | 117 | 118 | $res['name']=array(); 119 | $danbai=array(); 120 | $zhifang=array(); 121 | $tanshui=array(); 122 | 123 | foreach ($list as $key => $value) { 124 | # code... 125 | $bili=$this->gnb($value['danbai'],$value['zhifang'],$value['tanshui']); 126 | 127 | array_push($res['name'], $value['name']); 128 | array_push($danbai,$bili['danbai']); 129 | array_push($zhifang,$bili['zhifang']); 130 | array_push($tanshui,$bili['tanshui']); 131 | } 132 | 133 | $res['hong'][0]['name']='蛋白质'; 134 | $res['hong'][0]['type']='line'; 135 | $res['hong'][0]['stack']='供能比'; 136 | $res['hong'][0]['areaStyle']=array('normal'=>''); 137 | $res['hong'][0]['data']=$danbai; 138 | 139 | $res['hong'][1]['name']='脂肪'; 140 | $res['hong'][1]['type']='line'; 141 | $res['hong'][1]['stack']='供能比'; 142 | $res['hong'][1]['areaStyle']=array('normal'=>''); 143 | $res['hong'][1]['data']=$zhifang; 144 | 145 | $res['hong'][2]['name']='碳水'; 146 | $res['hong'][2]['type']='line'; 147 | $res['hong'][2]['stack']='供能比'; 148 | $res['hong'][2]['areaStyle']=array('normal'=>''); 149 | $res['hong'][2]['data']=$tanshui; 150 | 151 | $this->ajaxReturn(array('code'=>200,'res'=>$res)); 152 | } 153 | 154 | public function baota(){ 155 | // 大米-4512 70克 甘薯(红心)-4212 50克 156 | // 蔬菜 白菜-3609 75克 菠菜-3686 45克 蘑菇-3612 30克 157 | // 水果 苹果-4125 50克 葡萄 4086 60克 158 | // 肉 羊肉-4016 50克 鳊鱼-3552 30克 扁豆-4294 30克 159 | // 牛奶-3744 100克 160 | // 油 10 161 | 162 | $total=array(); 163 | $wei=array(); 164 | 165 | $foodlist=array('4512'=>'70','4212'=>'30','3609'=>'75','3686'=>'45','3612'=>'30','4125'=>'50','4086'=>'60','4016'=>'30','3552'=>'30','4294'=>'30','3453'=>'10'); 166 | 167 | // $foodlist=array('4512'=>'150','3609'=>'150','3612'=>'30','4125'=>'100','4016'=>'100','4294'=>'30','3774'=>'100','3453'=>'10'); 168 | 169 | $weilist=array('VA'=>'维生素A','B1'=>'维生素B1','B2'=>'维生素B2','B3'=>'维生素B3','VC'=>'维生素C','VE'=>'维生素E','jia'=>'钾','na'=>'钠','gai'=>'钙','mei'=>'镁','tie'=>'铁','meng'=>'锰','xin'=>'锌','tong'=>'铜','lin'=>'磷','xi'=>'硒'); 170 | 171 | 172 | foreach ($foodlist as $key => $value) { 173 | 174 | $fu=$this->getone($key); 175 | 176 | $flist[$key]['name']=$fu['name']; 177 | $flist[$key]['liang']=$value; 178 | 179 | $total['nengliang']+=$fu['nengliang']*($value/100); 180 | 181 | $total['danbai']+=$fu['danbai']*($value/100); 182 | $total['zhifang']+=$fu['zhifang']*($value/100); 183 | $total['tanshui']+=$fu['tanshui']*($value/100); 184 | $total['xianwei']+=$fu['xianwei']*($value/100); 185 | 186 | foreach ($weilist as $kk => $vv) { 187 | # code... 188 | $wei[$kk]+=$fu[$kk]*($value/100); 189 | } 190 | 191 | } 192 | 193 | // dump($wei);die; 194 | $wei_str=array(); 195 | $wei_data=array(); 196 | 197 | foreach ($weilist as $kk => $vv) { 198 | # code... 199 | array_push($wei_str, "'".$vv."'"); 200 | } 201 | foreach ($wei as $key => $value) { 202 | # code... 203 | array_push($wei_data, "'".$value."'"); 204 | } 205 | $this->assign('wei_str',implode(',', $wei_str)); 206 | $this->assign('wei_data',implode(',', $wei_data)); 207 | 208 | 209 | $this->assign('flist', $flist); 210 | 211 | // dump($total); 212 | 213 | $this->assign('total', $total); 214 | 215 | $bili = $this->gnb($total['danbai'], $total['zhifang'], $total['tanshui']); 216 | 217 | $res_dd=array(); 218 | $data['name']='蛋白质'; 219 | $data['value']=$bili['danbai']; 220 | array_push($res_dd, $data); 221 | 222 | $data['name']='脂肪'; 223 | $data['value']=$bili['zhifang']; 224 | array_push($res_dd, $data); 225 | 226 | $data['name']='碳水化合物'; 227 | $data['value']=$bili['tanshui']; 228 | array_push($res_dd, $data); 229 | 230 | $res_data=json_encode($res_dd); 231 | $this->assign('hong_gnb',$res_data); 232 | 233 | $this->display(); 234 | } 235 | } -------------------------------------------------------------------------------- /framework/Lib/Template/TagLib.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP标签库TagLib解析基类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Template 17 | * @author liu21st 18 | */ 19 | class TagLib { 20 | 21 | /** 22 | * 标签库定义XML文件 23 | * @var string 24 | * @access protected 25 | */ 26 | protected $xml = ''; 27 | protected $tags = array();// 标签定义 28 | /** 29 | * 标签库名称 30 | * @var string 31 | * @access protected 32 | */ 33 | protected $tagLib =''; 34 | 35 | /** 36 | * 标签库标签列表 37 | * @var string 38 | * @access protected 39 | */ 40 | protected $tagList = array(); 41 | 42 | /** 43 | * 标签库分析数组 44 | * @var string 45 | * @access protected 46 | */ 47 | protected $parse = array(); 48 | 49 | /** 50 | * 标签库是否有效 51 | * @var string 52 | * @access protected 53 | */ 54 | protected $valid = false; 55 | 56 | /** 57 | * 当前模板对象 58 | * @var object 59 | * @access protected 60 | */ 61 | protected $tpl; 62 | 63 | protected $comparison = array(' nheq '=>' !== ',' heq '=>' === ',' neq '=>' != ',' eq '=>' == ',' egt '=>' >= ',' gt '=>' > ',' elt '=>' <= ',' lt '=>' < '); 64 | 65 | /** 66 | * 架构函数 67 | * @access public 68 | */ 69 | public function __construct() { 70 | $this->tagLib = strtolower(substr(get_class($this),6)); 71 | $this->tpl = Think::instance('ThinkTemplate'); 72 | } 73 | 74 | /** 75 | * TagLib标签属性分析 返回标签属性数组 76 | * @access public 77 | * @param string $tagStr 标签内容 78 | * @return array 79 | */ 80 | public function parseXmlAttr($attr,$tag) { 81 | //XML解析安全过滤 82 | $attr = str_replace('&','___', $attr); 83 | $xml = ''; 84 | $xml = simplexml_load_string($xml); 85 | if(!$xml) { 86 | throw_exception(L('_XML_TAG_ERROR_').' : '.$attr); 87 | } 88 | $xml = (array)($xml->tag->attributes()); 89 | $array = array_change_key_case($xml['@attributes']); 90 | if($array) { 91 | $attrs = explode(',',$this->tags[strtolower($tag)]['attr']); 92 | foreach($attrs as $name) { 93 | if( isset($array[$name])) { 94 | $array[$name] = str_replace('___','&',$array[$name]); 95 | } 96 | } 97 | return $array; 98 | } 99 | } 100 | 101 | /** 102 | * 解析条件表达式 103 | * @access public 104 | * @param string $condition 表达式标签内容 105 | * @return array 106 | */ 107 | public function parseCondition($condition) { 108 | $condition = str_ireplace(array_keys($this->comparison),array_values($this->comparison),$condition); 109 | $condition = preg_replace('/\$(\w+):(\w+)\s/is','$\\1->\\2 ',$condition); 110 | switch(strtolower(C('TMPL_VAR_IDENTIFY'))) { 111 | case 'array': // 识别为数组 112 | $condition = preg_replace('/\$(\w+)\.(\w+)\s/is','$\\1["\\2"] ',$condition); 113 | break; 114 | case 'obj': // 识别为对象 115 | $condition = preg_replace('/\$(\w+)\.(\w+)\s/is','$\\1->\\2 ',$condition); 116 | break; 117 | default: // 自动判断数组或对象 只支持二维 118 | $condition = preg_replace('/\$(\w+)\.(\w+)\s/is','(is_array($\\1)?$\\1["\\2"]:$\\1->\\2) ',$condition); 119 | } 120 | return $condition; 121 | } 122 | 123 | /** 124 | * 自动识别构建变量 125 | * @access public 126 | * @param string $name 变量描述 127 | * @return string 128 | */ 129 | public function autoBuildVar($name) { 130 | if('Think.' == substr($name,0,6)){ 131 | // 特殊变量 132 | return $this->parseThinkVar($name); 133 | }elseif(strpos($name,'.')) { 134 | $vars = explode('.',$name); 135 | $var = array_shift($vars); 136 | switch(strtolower(C('TMPL_VAR_IDENTIFY'))) { 137 | case 'array': // 识别为数组 138 | $name = '$'.$var; 139 | foreach ($vars as $key=>$val){ 140 | if(0===strpos($val,'$')) { 141 | $name .= '["{'.$val.'}"]'; 142 | }else{ 143 | $name .= '["'.$val.'"]'; 144 | } 145 | } 146 | break; 147 | case 'obj': // 识别为对象 148 | $name = '$'.$var; 149 | foreach ($vars as $key=>$val) 150 | $name .= '->'.$val; 151 | break; 152 | default: // 自动判断数组或对象 只支持二维 153 | $name = 'is_array($'.$var.')?$'.$var.'["'.$vars[0].'"]:$'.$var.'->'.$vars[0]; 154 | } 155 | }elseif(strpos($name,':')){ 156 | // 额外的对象方式支持 157 | $name = '$'.str_replace(':','->',$name); 158 | }elseif(!defined($name)) { 159 | $name = '$'.$name; 160 | } 161 | return $name; 162 | } 163 | 164 | /** 165 | * 用于标签属性里面的特殊模板变量解析 166 | * 格式 以 Think. 打头的变量属于特殊模板变量 167 | * @access public 168 | * @param string $varStr 变量字符串 169 | * @return string 170 | */ 171 | public function parseThinkVar($varStr){ 172 | $vars = explode('.',$varStr); 173 | $vars[1] = strtoupper(trim($vars[1])); 174 | $parseStr = ''; 175 | if(count($vars)>=3){ 176 | $vars[2] = trim($vars[2]); 177 | switch($vars[1]){ 178 | case 'SERVER': $parseStr = '$_SERVER[\''.$vars[2].'\']';break; 179 | case 'GET': $parseStr = '$_GET[\''.$vars[2].'\']';break; 180 | case 'POST': $parseStr = '$_POST[\''.$vars[2].'\']';break; 181 | case 'COOKIE': 182 | if(isset($vars[3])) { 183 | $parseStr = '$_COOKIE[\''.$vars[2].'\'][\''.$vars[3].'\']'; 184 | }elseif(C('COOKIE_PREFIX')){ 185 | $parseStr = '$_COOKIE[\''.C('COOKIE_PREFIX').$vars[2].'\']'; 186 | }else{ 187 | $parseStr = '$_COOKIE[\''.$vars[2].'\']'; 188 | } 189 | break; 190 | case 'SESSION': 191 | if(isset($vars[3])) { 192 | $parseStr = '$_SESSION[\''.$vars[2].'\'][\''.$vars[3].'\']'; 193 | }elseif(C('SESSION_PREFIX')){ 194 | $parseStr = '$_SESSION[\''.C('SESSION_PREFIX').'\'][\''.$vars[2].'\']'; 195 | }else{ 196 | $parseStr = '$_SESSION[\''.$vars[2].'\']'; 197 | } 198 | break; 199 | case 'ENV': $parseStr = '$_ENV[\''.$vars[2].'\']';break; 200 | case 'REQUEST': $parseStr = '$_REQUEST[\''.$vars[2].'\']';break; 201 | case 'CONST': $parseStr = strtoupper($vars[2]);break; 202 | case 'LANG': $parseStr = 'L("'.$vars[2].'")';break; 203 | case 'CONFIG': $parseStr = 'C("'.$vars[2].'")';break; 204 | } 205 | }else if(count($vars)==2){ 206 | switch($vars[1]){ 207 | case 'NOW': $parseStr = "date('Y-m-d g:i a',time())";break; 208 | case 'VERSION': $parseStr = 'THINK_VERSION';break; 209 | case 'TEMPLATE':$parseStr = 'C("TEMPLATE_NAME")';break; 210 | case 'LDELIM': $parseStr = 'C("TMPL_L_DELIM")';break; 211 | case 'RDELIM': $parseStr = 'C("TMPL_R_DELIM")';break; 212 | default: if(defined($vars[1])) $parseStr = $vars[1]; 213 | } 214 | } 215 | return $parseStr; 216 | } 217 | 218 | // 获取标签定义 219 | public function getTags(){ 220 | return $this->tags; 221 | } 222 | } -------------------------------------------------------------------------------- /framework/Lib/Core/Dispatcher.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP内置的Dispatcher类 14 | * 完成URL解析、路由和调度 15 | * @category Think 16 | * @package Think 17 | * @subpackage Core 18 | * @author liu21st 19 | */ 20 | class Dispatcher { 21 | 22 | /** 23 | * URL映射到控制器 24 | * @access public 25 | * @return void 26 | */ 27 | static public function dispatch() { 28 | $urlMode = C('URL_MODEL'); 29 | if(!empty($_GET[C('VAR_PATHINFO')])) { // 判断URL里面是否有兼容模式参数 30 | $_SERVER['PATH_INFO'] = $_GET[C('VAR_PATHINFO')]; 31 | unset($_GET[C('VAR_PATHINFO')]); 32 | } 33 | if($urlMode == URL_COMPAT ){ 34 | // 兼容模式判断 35 | define('PHP_FILE',_PHP_FILE_.'?'.C('VAR_PATHINFO').'='); 36 | }elseif($urlMode == URL_REWRITE ) { 37 | //当前项目地址 38 | $url = dirname(_PHP_FILE_); 39 | if($url == '/' || $url == '\\') 40 | $url = ''; 41 | define('PHP_FILE',$url); 42 | }else { 43 | //当前项目地址 44 | define('PHP_FILE',_PHP_FILE_); 45 | } 46 | 47 | // 开启子域名部署 48 | if(C('APP_SUB_DOMAIN_DEPLOY')) { 49 | $rules = C('APP_SUB_DOMAIN_RULES'); 50 | $subDomain = strtolower(substr($_SERVER['HTTP_HOST'],0,strpos($_SERVER['HTTP_HOST'],'.'))); 51 | define('SUB_DOMAIN',$subDomain); // 二级域名定义 52 | if($subDomain && isset($rules[$subDomain])) { 53 | $rule = $rules[$subDomain]; 54 | }elseif(isset($rules['*'])){ // 泛域名支持 55 | if('www' != $subDomain && !in_array($subDomain,C('APP_SUB_DOMAIN_DENY'))) { 56 | $rule = $rules['*']; 57 | } 58 | } 59 | if(!empty($rule)) { 60 | // 子域名部署规则 '子域名'=>array('分组名/[模块名]','var1=a&var2=b'); 61 | $array = explode('/',$rule[0]); 62 | $module = array_pop($array); 63 | if(!empty($module)) { 64 | $_GET[C('VAR_MODULE')] = $module; 65 | $domainModule = true; 66 | } 67 | if(!empty($array)) { 68 | $_GET[C('VAR_GROUP')] = array_pop($array); 69 | $domainGroup = true; 70 | } 71 | if(isset($rule[1])) { // 传入参数 72 | parse_str($rule[1],$parms); 73 | $_GET = array_merge($_GET,$parms); 74 | } 75 | } 76 | } 77 | // 分析PATHINFO信息 78 | if(empty($_SERVER['PATH_INFO'])) { 79 | $types = explode(',',C('URL_PATHINFO_FETCH')); 80 | foreach ($types as $type){ 81 | if(0===strpos($type,':')) {// 支持函数判断 82 | $_SERVER['PATH_INFO'] = call_user_func(substr($type,1)); 83 | break; 84 | }elseif(!empty($_SERVER[$type])) { 85 | $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type],$_SERVER['SCRIPT_NAME']))? 86 | substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; 87 | break; 88 | } 89 | } 90 | } 91 | 92 | $depr = C('URL_PATHINFO_DEPR'); 93 | if(!empty($_SERVER['PATH_INFO'])) { 94 | tag('path_info'); 95 | $part = pathinfo($_SERVER['PATH_INFO']); 96 | define('__EXT__', isset($part['extension'])?strtolower($part['extension']):''); 97 | if(C('URL_HTML_SUFFIX')) { 98 | $_SERVER['PATH_INFO'] = preg_replace('/\.('.trim(C('URL_HTML_SUFFIX'),'.').')$/i', '', $_SERVER['PATH_INFO']); 99 | }elseif(__EXT__) { 100 | $_SERVER['PATH_INFO'] = preg_replace('/.'.__EXT__.'$/i','',$_SERVER['PATH_INFO']); 101 | } 102 | if(!self::routerCheck()){ // 检测路由规则 如果没有则按默认规则调度URL 103 | $paths = explode($depr,trim($_SERVER['PATH_INFO'],'/')); 104 | if(C('VAR_URL_PARAMS')) { 105 | // 直接通过$_GET['_URL_'][1] $_GET['_URL_'][2] 获取URL参数 方便不用路由时参数获取 106 | $_GET[C('VAR_URL_PARAMS')] = $paths; 107 | } 108 | $var = array(); 109 | if (C('APP_GROUP_LIST') && !isset($_GET[C('VAR_GROUP')])){ 110 | $var[C('VAR_GROUP')] = in_array(strtolower($paths[0]),explode(',',strtolower(C('APP_GROUP_LIST'))))? array_shift($paths) : ''; 111 | if(C('APP_GROUP_DENY') && in_array(strtolower($var[C('VAR_GROUP')]),explode(',',strtolower(C('APP_GROUP_DENY'))))) { 112 | // 禁止直接访问分组 113 | exit; 114 | } 115 | } 116 | if(!isset($_GET[C('VAR_MODULE')])) {// 还没有定义模块名称 117 | $var[C('VAR_MODULE')] = array_shift($paths); 118 | } 119 | $var[C('VAR_ACTION')] = array_shift($paths); 120 | // 解析剩余的URL参数 121 | preg_replace('@(\w+)\/([^\/]+)@e', '$var[\'\\1\']=strip_tags(\'\\2\');', implode('/',$paths)); 122 | $_GET = array_merge($var,$_GET); 123 | } 124 | define('__INFO__',$_SERVER['PATH_INFO']); 125 | } 126 | 127 | // 获取分组 模块和操作名称 128 | if (C('APP_GROUP_LIST')) { 129 | define('GROUP_NAME', self::getGroup(C('VAR_GROUP'))); 130 | } 131 | define('MODULE_NAME',self::getModule(C('VAR_MODULE'))); 132 | define('ACTION_NAME',self::getAction(C('VAR_ACTION'))); 133 | // URL常量 134 | define('__SELF__',strip_tags($_SERVER['REQUEST_URI'])); 135 | // 当前项目地址 136 | define('__APP__',strip_tags(PHP_FILE)); 137 | // 当前模块和分组地址 138 | if(defined('GROUP_NAME')) { 139 | define('__GROUP__',(!empty($domainGroup) || strtolower(GROUP_NAME) == strtolower(C('DEFAULT_GROUP')) )?__APP__ : __APP__.'/'.GROUP_NAME); 140 | define('__URL__',!empty($domainModule)?__GROUP__.$depr : __GROUP__.$depr.MODULE_NAME); 141 | }else{ 142 | define('__URL__',!empty($domainModule)?__APP__.'/' : __APP__.'/'.MODULE_NAME); 143 | } 144 | // 当前操作地址 145 | define('__ACTION__',__URL__.$depr.ACTION_NAME); 146 | //保证$_REQUEST正常取值 147 | $_REQUEST = array_merge($_POST,$_GET); 148 | } 149 | 150 | /** 151 | * 路由检测 152 | * @access public 153 | * @return void 154 | */ 155 | static public function routerCheck() { 156 | $return = false; 157 | // 路由检测标签 158 | tag('route_check',$return); 159 | return $return; 160 | } 161 | 162 | /** 163 | * 获得实际的模块名称 164 | * @access private 165 | * @return string 166 | */ 167 | static private function getModule($var) { 168 | $module = (!empty($_GET[$var])? $_GET[$var]:C('DEFAULT_MODULE')); 169 | unset($_GET[$var]); 170 | if(C('URL_CASE_INSENSITIVE')) { 171 | // URL地址不区分大小写 172 | // 智能识别方式 index.php/user_type/index/ 识别到 UserTypeAction 模块 173 | $module = ucfirst(parse_name($module,1)); 174 | } 175 | return strip_tags($module); 176 | } 177 | 178 | /** 179 | * 获得实际的操作名称 180 | * @access private 181 | * @return string 182 | */ 183 | static private function getAction($var) { 184 | $action = !empty($_POST[$var]) ? 185 | $_POST[$var] : 186 | (!empty($_GET[$var])?$_GET[$var]:C('DEFAULT_ACTION')); 187 | unset($_POST[$var],$_GET[$var]); 188 | return strip_tags(C('URL_CASE_INSENSITIVE')?strtolower($action):$action); 189 | } 190 | 191 | /** 192 | * 获得实际的分组名称 193 | * @access private 194 | * @return string 195 | */ 196 | static private function getGroup($var) { 197 | $group = (!empty($_GET[$var])?$_GET[$var]:C('DEFAULT_GROUP')); 198 | unset($_GET[$var]); 199 | return strip_tags(C('URL_CASE_INSENSITIVE') ?ucfirst(strtolower($group)):$group); 200 | } 201 | 202 | } -------------------------------------------------------------------------------- /app/Tpl/check/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 5 |
    6 | 7 |
    8 | 9 |
    10 | 11 |
    12 | 13 |
    14 | 15 |
    16 | 17 |
    18 | 19 |
    20 | 21 |
    22 | 23 |
    24 | 25 |
    26 | 27 |
    28 | 29 |
    30 | 31 |
    32 | 33 |
    34 | 35 |
    36 | 37 |
    38 | 39 |
    40 | 41 |
    42 | 43 |
    44 | 45 |
    46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /framework/Lib/Behavior/CheckRouteBehavior.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * 系统行为扩展:路由检测 15 | * @category Think 16 | * @package Think 17 | * @subpackage Behavior 18 | * @author liu21st 19 | */ 20 | class CheckRouteBehavior extends Behavior { 21 | // 行为参数定义(默认值) 可在项目配置中覆盖 22 | protected $options = array( 23 | 'URL_ROUTER_ON' => false, // 是否开启URL路由 24 | 'URL_ROUTE_RULES' => array(), // 默认路由规则,注:分组配置无法替代 25 | ); 26 | 27 | // 行为扩展的执行入口必须是run 28 | public function run(&$return){ 29 | // 优先检测是否存在PATH_INFO 30 | $regx = trim($_SERVER['PATH_INFO'],'/'); 31 | __EXT__ && $regx = $regx . '.' . __EXT__; 32 | if(empty($regx)) return $return = true; 33 | // 是否开启路由使用 34 | if(!C('URL_ROUTER_ON')) return $return = false; 35 | // 路由定义文件优先于config中的配置定义 36 | $routes = C('URL_ROUTE_RULES'); 37 | // 路由处理 38 | if(!empty($routes)) { 39 | $depr = C('URL_PATHINFO_DEPR'); 40 | // 分隔符替换 确保路由定义使用统一的分隔符 41 | //$regx = str_replace($depr,'/',$regx); 42 | foreach ($routes as $rule=>$route) { 43 | $rule = str_replace('\\/$/', '$/', $rule); //替换最后一个目录 44 | if(0===strpos($rule,'/') && preg_match($rule,$regx,$matches)) { // 正则路由 45 | return $return = $this->parseRegex($matches,$route,$regx); 46 | }else{ // 规则路由 47 | $len1 = substr_count($regx,'/'); 48 | $len2 = substr_count($rule,'/'); 49 | if($len1>=$len2) { 50 | if('$' == substr($rule,-1,1)) {// 完整匹配 51 | if($len1 != $len2) { 52 | continue; 53 | }else{ 54 | $rule = substr($rule,0,-1); 55 | } 56 | } 57 | $match = $this->checkUrlMatch($regx,$rule); 58 | if($match) return $return = $this->parseRule($rule,$route,$regx); 59 | } 60 | } 61 | } 62 | } 63 | $return = false; 64 | } 65 | 66 | // 检测URL和规则路由是否匹配 67 | private function checkUrlMatch($regx,$rule) { 68 | $m1 = explode('/',$regx); 69 | $m2 = explode('/',$rule); 70 | $match = true; // 是否匹配 71 | foreach ($m2 as $key=>$val){ 72 | if(':' == substr($val,0,1)) {// 动态变量 73 | if(strpos($val,'\\')) { 74 | $type = substr($val,-1); 75 | if('d'==$type && !is_numeric($m1[$key])) { 76 | $match = false; 77 | break; 78 | } 79 | }elseif(strpos($val,'^')){ 80 | $array = explode('|',substr(strstr($val,'^'),1)); 81 | if(in_array($m1[$key],$array)) { 82 | $match = false; 83 | break; 84 | } 85 | } 86 | }elseif(0 !== strcasecmp($val,$m1[$key])){ 87 | $match = false; 88 | break; 89 | } 90 | } 91 | return $match; 92 | } 93 | 94 | // 解析规范的路由地址 95 | // 地址格式 [分组/模块/操作?]参数1=值1&参数2=值2... 96 | private function parseUrl($url) { 97 | $var = array(); 98 | if(false !== strpos($url,'?')) { // [分组/模块/操作?]参数1=值1&参数2=值2... 99 | $info = parse_url($url); 100 | $path = explode('/',$info['path']); 101 | parse_str($info['query'],$var); 102 | }elseif(strpos($url,'/')){ // [分组/模块/操作] 103 | $path = explode('/',$url); 104 | }else{ // 参数1=值1&参数2=值2... 105 | parse_str($url,$var); 106 | } 107 | if(isset($path)) { 108 | $var[C('VAR_ACTION')] = array_pop($path); 109 | if(!empty($path)) { 110 | $var[C('VAR_MODULE')] = array_pop($path); 111 | } 112 | if(!empty($path)) { 113 | $var[C('VAR_GROUP')] = array_pop($path); 114 | } 115 | } 116 | return $var; 117 | } 118 | 119 | // 解析规则路由 120 | // '路由规则'=>'[分组/模块/操作]?额外参数1=值1&额外参数2=值2...' 121 | // '路由规则'=>array('[分组/模块/操作]','额外参数1=值1&额外参数2=值2...') 122 | // '路由规则'=>'外部地址' 123 | // '路由规则'=>array('外部地址','重定向代码') 124 | // 路由规则中 :开头 表示动态变量 125 | // 外部地址中可以用动态变量 采用 :1 :2 的方式 126 | // 'news/:month/:day/:id'=>array('News/read?cate=1','status=1'), 127 | // 'new/:id'=>array('/new.php?id=:1',301), 重定向 128 | private function parseRule($rule,$route,$regx) { 129 | // 获取路由地址规则 130 | $url = is_array($route)?$route[0]:$route; 131 | // 获取URL地址中的参数 132 | $paths = explode('/',$regx); 133 | // 解析路由规则 134 | $matches = array(); 135 | $rule = explode('/',$rule); 136 | foreach ($rule as $item){ 137 | if(0===strpos($item,':')) { // 动态变量获取 138 | if($pos = strpos($item,'^') ) { 139 | $var = substr($item,1,$pos-1); 140 | }elseif(strpos($item,'\\')){ 141 | $var = substr($item,1,-2); 142 | }else{ 143 | $var = substr($item,1); 144 | } 145 | $matches[$var] = array_shift($paths); 146 | }else{ // 过滤URL中的静态变量 147 | array_shift($paths); 148 | } 149 | } 150 | if(0=== strpos($url,'/') || 0===strpos($url,'http')) { // 路由重定向跳转 151 | if(strpos($url,':')) { // 传递动态参数 152 | $values = array_values($matches); 153 | $url = preg_replace('/:(\d+)/e','$values[\\1-1]',$url); 154 | } 155 | header("Location: $url", true,(is_array($route) && isset($route[1]))?$route[1]:301); 156 | exit; 157 | }else{ 158 | // 解析路由地址 159 | $var = $this->parseUrl($url); 160 | // 解析路由地址里面的动态参数 161 | $values = array_values($matches); 162 | foreach ($var as $key=>$val){ 163 | if(0===strpos($val,':')) { 164 | $var[$key] = $values[substr($val,1)-1]; 165 | } 166 | } 167 | $var = array_merge($matches,$var); 168 | // 解析剩余的URL参数 169 | if($paths) { 170 | preg_replace('@(\w+)\/([^\/]+)@e', '$var[strtolower(\'\\1\')]=strip_tags(\'\\2\');', implode('/',$paths)); 171 | } 172 | // 解析路由自动传人参数 173 | if(is_array($route) && isset($route[1])) { 174 | parse_str($route[1],$params); 175 | $var = array_merge($var,$params); 176 | } 177 | $_GET = array_merge($var,$_GET); 178 | } 179 | return true; 180 | } 181 | 182 | // 解析正则路由 183 | // '路由正则'=>'[分组/模块/操作]?参数1=值1&参数2=值2...' 184 | // '路由正则'=>array('[分组/模块/操作]?参数1=值1&参数2=值2...','额外参数1=值1&额外参数2=值2...') 185 | // '路由正则'=>'外部地址' 186 | // '路由正则'=>array('外部地址','重定向代码') 187 | // 参数值和外部地址中可以用动态变量 采用 :1 :2 的方式 188 | // '/new\/(\d+)\/(\d+)/'=>array('News/read?id=:1&page=:2&cate=1','status=1'), 189 | // '/new\/(\d+)/'=>array('/new.php?id=:1&page=:2&status=1','301'), 重定向 190 | private function parseRegex($matches,$route,$regx) { 191 | // 获取路由地址规则 192 | $url = is_array($route)?$route[0]:$route; 193 | $url = preg_replace('/:(\d+)/e','$matches[\\1]',$url); 194 | if(0=== strpos($url,'/') || 0===strpos($url,'http')) { // 路由重定向跳转 195 | header("Location: $url", true,(is_array($route) && isset($route[1]))?$route[1]:301); 196 | exit; 197 | }else{ 198 | // 解析路由地址 199 | $var = $this->parseUrl($url); 200 | // 解析剩余的URL参数 201 | $regx = substr_replace($regx,'',0,strlen($matches[0])); 202 | if($regx) { 203 | preg_replace('@(\w+)\/([^,\/]+)@e', '$var[strtolower(\'\\1\')]=strip_tags(\'\\2\');', $regx); 204 | } 205 | // 解析路由自动传人参数 206 | if(is_array($route) && isset($route[1])) { 207 | parse_str($route[1],$params); 208 | $var = array_merge($var,$params); 209 | } 210 | $_GET = array_merge($var,$_GET); 211 | } 212 | return true; 213 | } 214 | } -------------------------------------------------------------------------------- /framework/Common/runtime.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP 运行时文件 编译后不再加载 14 | * @category Think 15 | * @package Common 16 | * @author liu21st 17 | */ 18 | defined('THINK_PATH') or exit(); 19 | if(version_compare(PHP_VERSION,'5.2.0','<')) die('require PHP > 5.2.0 !'); 20 | 21 | // 版本信息 22 | define('THINK_VERSION', '3.1'); 23 | 24 | // 系统信息 25 | if(version_compare(PHP_VERSION,'5.3.0','<')) { 26 | set_magic_quotes_runtime(0); 27 | define('MAGIC_QUOTES_GPC',get_magic_quotes_gpc()?True:False); 28 | }else{ 29 | define('MAGIC_QUOTES_GPC',True); 30 | } 31 | define('IS_CGI',substr(PHP_SAPI, 0,3)=='cgi' ? 1 : 0 ); 32 | define('IS_WIN',strstr(PHP_OS, 'WIN') ? 1 : 0 ); 33 | define('IS_CLI',PHP_SAPI=='cli'? 1 : 0); 34 | 35 | // 项目名称 36 | defined('APP_NAME') or define('APP_NAME', basename(dirname($_SERVER['SCRIPT_FILENAME']))); 37 | 38 | if(!IS_CLI) { 39 | // 当前文件名 40 | if(!defined('_PHP_FILE_')) { 41 | if(IS_CGI) { 42 | //CGI/FASTCGI模式下 43 | $_temp = explode('.php',$_SERVER['PHP_SELF']); 44 | define('_PHP_FILE_', rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/')); 45 | }else { 46 | define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'],'/')); 47 | } 48 | } 49 | if(!defined('__ROOT__')) { 50 | // 网站URL根目录 51 | if( strtoupper(APP_NAME) == strtoupper(basename(dirname(_PHP_FILE_))) ) { 52 | $_root = dirname(dirname(_PHP_FILE_)); 53 | }else { 54 | $_root = dirname(_PHP_FILE_); 55 | } 56 | define('__ROOT__', (($_root=='/' || $_root=='\\')?'':$_root)); 57 | } 58 | 59 | //支持的URL模式 60 | define('URL_COMMON', 0); //普通模式 61 | define('URL_PATHINFO', 1); //PATHINFO模式 62 | define('URL_REWRITE', 2); //REWRITE模式 63 | define('URL_COMPAT', 3); // 兼容模式 64 | } 65 | 66 | // 路径设置 可在入口文件中重新定义 所有路径常量都必须以/ 结尾 67 | defined('CORE_PATH') or define('CORE_PATH', THINK_PATH.'Lib/'); // 系统核心类库目录 68 | defined('EXTEND_PATH') or define('EXTEND_PATH', THINK_PATH.'Extend/'); // 系统扩展目录 69 | defined('MODE_PATH') or define('MODE_PATH', EXTEND_PATH.'Mode/'); // 模式扩展目录 70 | defined('ENGINE_PATH') or define('ENGINE_PATH', EXTEND_PATH.'Engine/'); // 引擎扩展目录 71 | defined('VENDOR_PATH') or define('VENDOR_PATH', EXTEND_PATH.'Vendor/'); // 第三方类库目录 72 | defined('LIBRARY_PATH') or define('LIBRARY_PATH', EXTEND_PATH.'Library/'); // 扩展类库目录 73 | defined('COMMON_PATH') or define('COMMON_PATH', APP_PATH.'Common/'); // 项目公共目录 74 | defined('LIB_PATH') or define('LIB_PATH', APP_PATH.'Lib/'); // 项目类库目录 75 | defined('CONF_PATH') or define('CONF_PATH', APP_PATH.'Conf/'); // 项目配置目录 76 | defined('LANG_PATH') or define('LANG_PATH', APP_PATH.'Lang/'); // 项目语言包目录 77 | defined('TMPL_PATH') or define('TMPL_PATH', APP_PATH.'Tpl/'); // 项目模板目录 78 | defined('HTML_PATH') or define('HTML_PATH', APP_PATH.'Html/'); // 项目静态目录 79 | defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH.'Logs/'); // 项目日志目录 80 | defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH.'Temp/'); // 项目缓存目录 81 | defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH.'Data/'); // 项目数据目录 82 | defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH.'Cache/'); // 项目模板缓存目录 83 | 84 | // 为了方便导入第三方类库 设置Vendor目录到include_path 85 | set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH); 86 | 87 | // 加载运行时所需要的文件 并负责自动目录生成 88 | function load_runtime_file() { 89 | // 加载系统基础函数库 90 | require THINK_PATH.'Common/common.php'; 91 | // 读取核心编译文件列表 92 | $list = array( 93 | CORE_PATH.'Core/Think.class.php', 94 | CORE_PATH.'Core/ThinkException.class.php', // 异常处理类 95 | CORE_PATH.'Core/Behavior.class.php', 96 | ); 97 | // 加载模式文件列表 98 | foreach ($list as $key=>$file){ 99 | if(is_file($file)) require_cache($file); 100 | } 101 | // 加载系统类库别名定义 102 | alias_import(include THINK_PATH.'Conf/alias.php'); 103 | 104 | // 检查项目目录结构 如果不存在则自动创建 105 | if(!is_dir(LIB_PATH)) { 106 | // 创建项目目录结构 107 | build_app_dir(); 108 | }elseif(!is_dir(CACHE_PATH)){ 109 | // 检查缓存目录 110 | check_runtime(); 111 | }elseif(APP_DEBUG){ 112 | // 调试模式切换删除编译缓存 113 | if(is_file(RUNTIME_FILE)) unlink(RUNTIME_FILE); 114 | } 115 | } 116 | 117 | // 检查缓存目录(Runtime) 如果不存在则自动创建 118 | function check_runtime() { 119 | if(!is_dir(RUNTIME_PATH)) { 120 | mkdir(RUNTIME_PATH); 121 | }elseif(!is_writeable(RUNTIME_PATH)) { 122 | header('Content-Type:text/html; charset=utf-8'); 123 | exit('目录 [ '.RUNTIME_PATH.' ] 不可写!'); 124 | } 125 | mkdir(CACHE_PATH); // 模板缓存目录 126 | if(!is_dir(LOG_PATH)) mkdir(LOG_PATH); // 日志目录 127 | if(!is_dir(TEMP_PATH)) mkdir(TEMP_PATH); // 数据缓存目录 128 | if(!is_dir(DATA_PATH)) mkdir(DATA_PATH); // 数据文件目录 129 | return true; 130 | } 131 | 132 | // 创建编译缓存 133 | function build_runtime_cache($append='') { 134 | // 生成编译文件 135 | $defs = get_defined_constants(TRUE); 136 | $content = '$GLOBALS[\'_beginTime\'] = microtime(TRUE);'; 137 | if(defined('RUNTIME_DEF_FILE')) { // 编译后的常量文件外部引入 138 | file_put_contents(RUNTIME_DEF_FILE,'$item){ 170 | foreach ($item as $key=>$name) { 171 | $content .= is_int($key)?compile(CORE_PATH.'Behavior/'.$name.'Behavior.class.php'):compile($name); 172 | } 173 | } 174 | return $content; 175 | } 176 | 177 | // 创建项目目录结构 178 | function build_app_dir() { 179 | // 没有创建项目目录的话自动创建 180 | if(!is_dir(APP_PATH)) mkdir(APP_PATH,0777,true); 181 | if(is_writeable(APP_PATH)) { 182 | $dirs = array( 183 | LIB_PATH, 184 | RUNTIME_PATH, 185 | CONF_PATH, 186 | COMMON_PATH, 187 | LANG_PATH, 188 | CACHE_PATH, 189 | TMPL_PATH, 190 | TMPL_PATH.C('DEFAULT_THEME').'/', 191 | LOG_PATH, 192 | TEMP_PATH, 193 | DATA_PATH, 194 | LIB_PATH.'Model/', 195 | LIB_PATH.'Action/', 196 | LIB_PATH.'Behavior/', 197 | LIB_PATH.'Widget/', 198 | ); 199 | foreach ($dirs as $dir){ 200 | if(!is_dir($dir)) mkdir($dir,0777,true); 201 | } 202 | // 写入目录安全文件 203 | build_dir_secure($dirs); 204 | // 写入初始配置文件 205 | if(!is_file(CONF_PATH.'config.php')) 206 | file_put_contents(CONF_PATH.'config.php',"'配置值'\n);\n?>"); 207 | // 写入测试Action 208 | if(!is_file(LIB_PATH.'Action/IndexAction.class.php')) 209 | build_first_action(); 210 | }else{ 211 | header('Content-Type:text/html; charset=utf-8'); 212 | exit('项目目录不可写,目录无法自动生成!
    请使用项目生成器或者手动生成项目目录~'); 213 | } 214 | } 215 | 216 | // 创建测试Action 217 | function build_first_action() { 218 | $content = file_get_contents(THINK_PATH.'Tpl/default_index.tpl'); 219 | file_put_contents(LIB_PATH.'Action/IndexAction.class.php',$content); 220 | } 221 | 222 | // 生成目录安全文件 223 | function build_dir_secure($dirs='') { 224 | // 目录安全写入 225 | if(defined('BUILD_DIR_SECURE') && BUILD_DIR_SECURE) { 226 | defined('DIR_SECURE_FILENAME') or define('DIR_SECURE_FILENAME', 'index.html'); 227 | defined('DIR_SECURE_CONTENT') or define('DIR_SECURE_CONTENT', ' '); 228 | // 自动写入目录安全文件 229 | $content = DIR_SECURE_CONTENT; 230 | $files = explode(',', DIR_SECURE_FILENAME); 231 | foreach ($files as $filename){ 232 | foreach ($dirs as $dir) 233 | file_put_contents($dir.$filename,$content); 234 | } 235 | } 236 | } 237 | 238 | // 加载运行时所需文件 239 | load_runtime_file(); 240 | // 记录加载文件时间 241 | G('loadTime'); 242 | // 执行入口 243 | Think::Start(); -------------------------------------------------------------------------------- /framework/Lib/Core/Think.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP Portal类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | class Think { 20 | 21 | private static $_instance = array(); 22 | 23 | /** 24 | * 应用程序初始化 25 | * @access public 26 | * @return void 27 | */ 28 | static public function start() { 29 | // 设定错误和异常处理 30 | register_shutdown_function(array('Think','fatalError')); 31 | set_error_handler(array('Think','appError')); 32 | set_exception_handler(array('Think','appException')); 33 | // 注册AUTOLOAD方法 34 | spl_autoload_register(array('Think', 'autoload')); 35 | //[RUNTIME] 36 | Think::buildApp(); // 预编译项目 37 | //[/RUNTIME] 38 | // 运行应用 39 | App::run(); 40 | return ; 41 | } 42 | 43 | //[RUNTIME] 44 | /** 45 | * 读取配置信息 编译项目 46 | * @access private 47 | * @return string 48 | */ 49 | static private function buildApp() { 50 | // 加载底层惯例配置文件 51 | C(include THINK_PATH.'Conf/convention.php'); 52 | 53 | // 读取运行模式 54 | if(defined('MODE_NAME')) { // 模式的设置并入核心模式 55 | $mode = include MODE_PATH.strtolower(MODE_NAME).'.php'; 56 | }else{ 57 | $mode = array(); 58 | } 59 | 60 | // 加载模式配置文件 61 | if(isset($mode['config'])) { 62 | C( is_array($mode['config'])?$mode['config']:include $mode['config'] ); 63 | } 64 | 65 | // 加载项目配置文件 66 | if(is_file(CONF_PATH.'config.php')) 67 | C(include CONF_PATH.'config.php'); 68 | 69 | // 加载框架底层语言包 70 | L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php'); 71 | 72 | // 加载模式系统行为定义 73 | if(C('APP_TAGS_ON')) { 74 | if(isset($mode['extends'])) { 75 | C('extends',is_array($mode['extends'])?$mode['extends']:include $mode['extends']); 76 | }else{ // 默认加载系统行为扩展定义 77 | C('extends', include THINK_PATH.'Conf/tags.php'); 78 | } 79 | } 80 | 81 | // 加载应用行为定义 82 | if(isset($mode['tags'])) { 83 | C('tags', is_array($mode['tags'])?$mode['tags']:include $mode['tags']); 84 | }elseif(is_file(CONF_PATH.'tags.php')){ 85 | // 默认加载项目配置目录的tags文件定义 86 | C('tags', include CONF_PATH.'tags.php'); 87 | } 88 | 89 | $compile = ''; 90 | // 读取核心编译文件列表 91 | if(isset($mode['core'])) { 92 | $list = $mode['core']; 93 | }else{ 94 | $list = array( 95 | THINK_PATH.'Common/functions.php', // 标准模式函数库 96 | CORE_PATH.'Core/Log.class.php', // 日志处理类 97 | CORE_PATH.'Core/Dispatcher.class.php', // URL调度类 98 | CORE_PATH.'Core/App.class.php', // 应用程序类 99 | CORE_PATH.'Core/Action.class.php', // 控制器类 100 | CORE_PATH.'Core/View.class.php', // 视图类 101 | ); 102 | } 103 | // 项目追加核心编译列表文件 104 | if(is_file(CONF_PATH.'core.php')) { 105 | $list = array_merge($list,include CONF_PATH.'core.php'); 106 | } 107 | foreach ($list as $file){ 108 | if(is_file($file)) { 109 | require_cache($file); 110 | if(!APP_DEBUG) $compile .= compile($file); 111 | } 112 | } 113 | 114 | // 加载项目公共文件 115 | if(is_file(COMMON_PATH.'common.php')) { 116 | include COMMON_PATH.'common.php'; 117 | // 编译文件 118 | if(!APP_DEBUG) $compile .= compile(COMMON_PATH.'common.php'); 119 | } 120 | 121 | // 加载模式别名定义 122 | if(isset($mode['alias'])) { 123 | $alias = is_array($mode['alias'])?$mode['alias']:include $mode['alias']; 124 | alias_import($alias); 125 | if(!APP_DEBUG) $compile .= 'alias_import('.var_export($alias,true).');'; 126 | } 127 | // 加载项目别名定义 128 | if(is_file(CONF_PATH.'alias.php')){ 129 | $alias = include CONF_PATH.'alias.php'; 130 | alias_import($alias); 131 | if(!APP_DEBUG) $compile .= 'alias_import('.var_export($alias,true).');'; 132 | } 133 | 134 | if(APP_DEBUG) { 135 | // 调试模式加载系统默认的配置文件 136 | C(include THINK_PATH.'Conf/debug.php'); 137 | // 读取调试模式的应用状态 138 | $status = C('APP_STATUS'); 139 | // 加载对应的项目配置文件 140 | if(is_file(CONF_PATH.$status.'.php')) 141 | // 允许项目增加开发模式配置定义 142 | C(include CONF_PATH.$status.'.php'); 143 | }else{ 144 | // 部署模式下面生成编译文件 145 | build_runtime_cache($compile); 146 | } 147 | return ; 148 | } 149 | //[/RUNTIME] 150 | 151 | /** 152 | * 系统自动加载ThinkPHP类库 153 | * 并且支持配置自动加载路径 154 | * @param string $class 对象类名 155 | * @return void 156 | */ 157 | public static function autoload($class) { 158 | // 检查是否存在别名定义 159 | if(alias_import($class)) return ; 160 | 161 | if(substr($class,-8)=='Behavior') { // 加载行为 162 | if(require_cache(CORE_PATH.'Behavior/'.$class.'.class.php') 163 | || require_cache(EXTEND_PATH.'Behavior/'.$class.'.class.php') 164 | || require_cache(LIB_PATH.'Behavior/'.$class.'.class.php') 165 | || (defined('MODE_NAME') && require_cache(MODE_PATH.ucwords(MODE_NAME).'/Behavior/'.$class.'.class.php'))) { 166 | return ; 167 | } 168 | }elseif(substr($class,-5)=='Model'){ // 加载模型 169 | if((defined('GROUP_NAME') && require_cache(LIB_PATH.'Model/'.GROUP_NAME.'/'.$class.'.class.php')) 170 | || require_cache(LIB_PATH.'Model/'.$class.'.class.php') 171 | || require_cache(EXTEND_PATH.'Model/'.$class.'.class.php') ) { 172 | return ; 173 | } 174 | }elseif(substr($class,-6)=='Action'){ // 加载控制器 175 | if((defined('GROUP_NAME') && require_cache(LIB_PATH.'Action/'.GROUP_NAME.'/'.$class.'.class.php')) 176 | || require_cache(LIB_PATH.'Action/'.$class.'.class.php') 177 | || require_cache(EXTEND_PATH.'Action/'.$class.'.class.php') ) { 178 | return ; 179 | } 180 | } 181 | 182 | // 根据自动加载路径设置进行尝试搜索 183 | $paths = explode(',',C('APP_AUTOLOAD_PATH')); 184 | foreach ($paths as $path){ 185 | if(import($path.'.'.$class)) 186 | // 如果加载类成功则返回 187 | return ; 188 | } 189 | } 190 | 191 | /** 192 | * 取得对象实例 支持调用类的静态方法 193 | * @param string $class 对象类名 194 | * @param string $method 类的静态方法名 195 | * @return object 196 | */ 197 | static public function instance($class,$method='') { 198 | $identify = $class.$method; 199 | if(!isset(self::$_instance[$identify])) { 200 | if(class_exists($class)){ 201 | $o = new $class(); 202 | if(!empty($method) && method_exists($o,$method)) 203 | self::$_instance[$identify] = call_user_func_array(array(&$o, $method)); 204 | else 205 | self::$_instance[$identify] = $o; 206 | } 207 | else 208 | halt(L('_CLASS_NOT_EXIST_').':'.$class); 209 | } 210 | return self::$_instance[$identify]; 211 | } 212 | 213 | /** 214 | * 自定义异常处理 215 | * @access public 216 | * @param mixed $e 异常对象 217 | */ 218 | static public function appException($e) { 219 | halt($e->__toString()); 220 | } 221 | 222 | /** 223 | * 自定义错误处理 224 | * @access public 225 | * @param int $errno 错误类型 226 | * @param string $errstr 错误信息 227 | * @param string $errfile 错误文件 228 | * @param int $errline 错误行数 229 | * @return void 230 | */ 231 | static public function appError($errno, $errstr, $errfile, $errline) { 232 | switch ($errno) { 233 | case E_ERROR: 234 | case E_PARSE: 235 | case E_CORE_ERROR: 236 | case E_COMPILE_ERROR: 237 | case E_USER_ERROR: 238 | ob_end_clean(); 239 | if(!ini_get('zlib.output_compression') && C('OUTPUT_ENCODE')) ob_start('ob_gzhandler'); 240 | $errorStr = "$errstr ".$errfile." 第 $errline 行."; 241 | if(C('LOG_RECORD')) Log::write("[$errno] ".$errorStr,Log::ERR); 242 | function_exists('halt')?halt($errorStr):exit('ERROR:'.$errorStr); 243 | break; 244 | case E_STRICT: 245 | case E_USER_WARNING: 246 | case E_USER_NOTICE: 247 | default: 248 | $errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行."; 249 | trace($errorStr,'','NOTIC'); 250 | break; 251 | } 252 | } 253 | 254 | // 致命错误捕获 255 | static public function fatalError() { 256 | if ($e = error_get_last()) { 257 | Think::appError($e['type'],$e['message'],$e['file'],$e['line']); 258 | } 259 | } 260 | 261 | } -------------------------------------------------------------------------------- /framework/Lib/Driver/Db/DbMysqli.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | /** 14 | * Mysqli数据库驱动类 15 | * @category Think 16 | * @package Think 17 | * @subpackage Driver.Db 18 | * @author liu21st 19 | */ 20 | class DbMysqli extends Db{ 21 | 22 | /** 23 | * 架构函数 读取数据库配置信息 24 | * @access public 25 | * @param array $config 数据库配置数组 26 | */ 27 | public function __construct($config=''){ 28 | if ( !extension_loaded('mysqli') ) { 29 | throw_exception(L('_NOT_SUPPERT_').':mysqli'); 30 | } 31 | if(!empty($config)) { 32 | $this->config = $config; 33 | if(empty($this->config['params'])) { 34 | $this->config['params'] = ''; 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * 连接数据库方法 41 | * @access public 42 | * @throws ThinkExecption 43 | */ 44 | public function connect($config='',$linkNum=0) { 45 | if ( !isset($this->linkID[$linkNum]) ) { 46 | if(empty($config)) $config = $this->config; 47 | $this->linkID[$linkNum] = new mysqli($config['hostname'],$config['username'],$config['password'],$config['database'],$config['hostport']?intval($config['hostport']):3306); 48 | if (mysqli_connect_errno()) throw_exception(mysqli_connect_error()); 49 | $dbVersion = $this->linkID[$linkNum]->server_version; 50 | if ($dbVersion >= '4.1') { 51 | // 设置数据库编码 需要mysql 4.1.0以上支持 52 | $this->linkID[$linkNum]->query("SET NAMES '".C('DB_CHARSET')."'"); 53 | } 54 | //设置 sql_model 55 | if($dbVersion >'5.0.1'){ 56 | $this->linkID[$linkNum]->query("SET sql_mode=''"); 57 | } 58 | // 标记连接成功 59 | $this->connected = true; 60 | //注销数据库安全信息 61 | if(1 != C('DB_DEPLOY_TYPE')) unset($this->config); 62 | } 63 | return $this->linkID[$linkNum]; 64 | } 65 | 66 | /** 67 | * 释放查询结果 68 | * @access public 69 | */ 70 | public function free() { 71 | $this->queryID->free_result(); 72 | $this->queryID = null; 73 | } 74 | 75 | /** 76 | * 执行查询 返回数据集 77 | * @access public 78 | * @param string $str sql指令 79 | * @return mixed 80 | */ 81 | public function query($str) { 82 | $this->initConnect(false); 83 | if ( !$this->_linkID ) return false; 84 | $this->queryStr = $str; 85 | //释放前次的查询结果 86 | if ( $this->queryID ) $this->free(); 87 | N('db_query',1); 88 | // 记录开始执行时间 89 | G('queryStartTime'); 90 | $this->queryID = $this->_linkID->query($str); 91 | // 对存储过程改进 92 | if( $this->_linkID->more_results() ){ 93 | while (($res = $this->_linkID->next_result()) != NULL) { 94 | $res->free_result(); 95 | } 96 | } 97 | $this->debug(); 98 | if ( false === $this->queryID ) { 99 | $this->error(); 100 | return false; 101 | } else { 102 | $this->numRows = $this->queryID->num_rows; 103 | $this->numCols = $this->queryID->field_count; 104 | return $this->getAll(); 105 | } 106 | } 107 | 108 | /** 109 | * 执行语句 110 | * @access public 111 | * @param string $str sql指令 112 | * @return integer 113 | */ 114 | public function execute($str) { 115 | $this->initConnect(true); 116 | if ( !$this->_linkID ) return false; 117 | $this->queryStr = $str; 118 | //释放前次的查询结果 119 | if ( $this->queryID ) $this->free(); 120 | N('db_write',1); 121 | // 记录开始执行时间 122 | G('queryStartTime'); 123 | $result = $this->_linkID->query($str); 124 | $this->debug(); 125 | if ( false === $result ) { 126 | $this->error(); 127 | return false; 128 | } else { 129 | $this->numRows = $this->_linkID->affected_rows; 130 | $this->lastInsID = $this->_linkID->insert_id; 131 | return $this->numRows; 132 | } 133 | } 134 | 135 | /** 136 | * 启动事务 137 | * @access public 138 | * @return void 139 | */ 140 | public function startTrans() { 141 | $this->initConnect(true); 142 | //数据rollback 支持 143 | if ($this->transTimes == 0) { 144 | $this->_linkID->autocommit(false); 145 | } 146 | $this->transTimes++; 147 | return ; 148 | } 149 | 150 | /** 151 | * 用于非自动提交状态下面的查询提交 152 | * @access public 153 | * @return boolen 154 | */ 155 | public function commit() { 156 | if ($this->transTimes > 0) { 157 | $result = $this->_linkID->commit(); 158 | $this->_linkID->autocommit( true); 159 | $this->transTimes = 0; 160 | if(!$result){ 161 | $this->error(); 162 | return false; 163 | } 164 | } 165 | return true; 166 | } 167 | 168 | /** 169 | * 事务回滚 170 | * @access public 171 | * @return boolen 172 | */ 173 | public function rollback() { 174 | if ($this->transTimes > 0) { 175 | $result = $this->_linkID->rollback(); 176 | $this->transTimes = 0; 177 | if(!$result){ 178 | $this->error(); 179 | return false; 180 | } 181 | } 182 | return true; 183 | } 184 | 185 | /** 186 | * 获得所有的查询数据 187 | * @access private 188 | * @param string $sql sql语句 189 | * @return array 190 | */ 191 | private function getAll() { 192 | //返回数据集 193 | $result = array(); 194 | if($this->numRows>0) { 195 | //返回数据集 196 | for($i=0;$i<$this->numRows ;$i++ ){ 197 | $result[$i] = $this->queryID->fetch_assoc(); 198 | } 199 | $this->queryID->data_seek(0); 200 | } 201 | return $result; 202 | } 203 | 204 | /** 205 | * 取得数据表的字段信息 206 | * @access public 207 | * @return array 208 | */ 209 | public function getFields($tableName) { 210 | $result = $this->query('SHOW COLUMNS FROM '.$this->parseKey($tableName)); 211 | $info = array(); 212 | if($result) { 213 | foreach ($result as $key => $val) { 214 | $info[$val['Field']] = array( 215 | 'name' => $val['Field'], 216 | 'type' => $val['Type'], 217 | 'notnull' => (bool) ($val['Null'] === ''), // not null is empty, null is yes 218 | 'default' => $val['Default'], 219 | 'primary' => (strtolower($val['Key']) == 'pri'), 220 | 'autoinc' => (strtolower($val['Extra']) == 'auto_increment'), 221 | ); 222 | } 223 | } 224 | return $info; 225 | } 226 | 227 | /** 228 | * 取得数据表的字段信息 229 | * @access public 230 | * @return array 231 | */ 232 | public function getTables($dbName='') { 233 | $sql = !empty($dbName)?'SHOW TABLES FROM '.$dbName:'SHOW TABLES '; 234 | $result = $this->query($sql); 235 | $info = array(); 236 | if($result) { 237 | foreach ($result as $key => $val) { 238 | $info[$key] = current($val); 239 | } 240 | } 241 | return $info; 242 | } 243 | 244 | /** 245 | * 替换记录 246 | * @access public 247 | * @param mixed $data 数据 248 | * @param array $options 参数表达式 249 | * @return false | integer 250 | */ 251 | public function replace($data,$options=array()) { 252 | foreach ($data as $key=>$val){ 253 | $value = $this->parseValue($val); 254 | if(is_scalar($value)) { // 过滤非标量数据 255 | $values[] = $value; 256 | $fields[] = $this->parseKey($key); 257 | } 258 | } 259 | $sql = 'REPLACE INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')'; 260 | return $this->execute($sql); 261 | } 262 | 263 | /** 264 | * 插入记录 265 | * @access public 266 | * @param mixed $datas 数据 267 | * @param array $options 参数表达式 268 | * @param boolean $replace 是否replace 269 | * @return false | integer 270 | */ 271 | public function insertAll($datas,$options=array(),$replace=false) { 272 | if(!is_array($datas[0])) return false; 273 | $fields = array_keys($datas[0]); 274 | array_walk($fields, array($this, 'parseKey')); 275 | $values = array(); 276 | foreach ($datas as $data){ 277 | $value = array(); 278 | foreach ($data as $key=>$val){ 279 | $val = $this->parseValue($val); 280 | if(is_scalar($val)) { // 过滤非标量数据 281 | $value[] = $val; 282 | } 283 | } 284 | $values[] = '('.implode(',', $value).')'; 285 | } 286 | $sql = ($replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES '.implode(',',$values); 287 | return $this->execute($sql); 288 | } 289 | 290 | /** 291 | * 关闭数据库 292 | * @access public 293 | * @return volid 294 | */ 295 | public function close() { 296 | if ($this->_linkID){ 297 | $this->_linkID->close(); 298 | } 299 | $this->_linkID = null; 300 | } 301 | 302 | /** 303 | * 数据库错误信息 304 | * 并显示当前的SQL语句 305 | * @static 306 | * @access public 307 | * @return string 308 | */ 309 | public function error() { 310 | $this->error = $this->_linkID->error; 311 | if('' != $this->queryStr){ 312 | $this->error .= "\n [ SQL语句 ] : ".$this->queryStr; 313 | } 314 | trace($this->error,'','ERR'); 315 | return $this->error; 316 | } 317 | 318 | /** 319 | * SQL指令安全过滤 320 | * @static 321 | * @access public 322 | * @param string $str SQL指令 323 | * @return string 324 | */ 325 | public function escapeString($str) { 326 | if($this->_linkID) { 327 | return $this->_linkID->real_escape_string($str); 328 | }else{ 329 | return addslashes($str); 330 | } 331 | } 332 | 333 | /** 334 | * 字段和表名处理添加` 335 | * @access protected 336 | * @param string $key 337 | * @return string 338 | */ 339 | protected function parseKey(&$key) { 340 | $key = trim($key); 341 | if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) { 342 | $key = '`'.$key.'`'; 343 | } 344 | return $key; 345 | } 346 | } -------------------------------------------------------------------------------- /framework/Lib/Driver/Db/DbMysql.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | defined('THINK_PATH') or exit(); 13 | define('CLIENT_MULTI_RESULTS', 131072); 14 | /** 15 | * Mysql数据库驱动类 16 | * @category Think 17 | * @package Think 18 | * @subpackage Driver.Db 19 | * @author liu21st 20 | */ 21 | class DbMysql extends Db{ 22 | 23 | /** 24 | * 架构函数 读取数据库配置信息 25 | * @access public 26 | * @param array $config 数据库配置数组 27 | */ 28 | public function __construct($config=''){ 29 | if ( !extension_loaded('mysql') ) { 30 | throw_exception(L('_NOT_SUPPERT_').':mysql'); 31 | } 32 | if(!empty($config)) { 33 | $this->config = $config; 34 | if(empty($this->config['params'])) { 35 | $this->config['params'] = ''; 36 | } 37 | } 38 | } 39 | 40 | /** 41 | * 连接数据库方法 42 | * @access public 43 | * @throws ThinkExecption 44 | */ 45 | public function connect($config='',$linkNum=0,$force=false) { 46 | if ( !isset($this->linkID[$linkNum]) ) { 47 | if(empty($config)) $config = $this->config; 48 | // 处理不带端口号的socket连接情况 49 | $host = $config['hostname'].($config['hostport']?":{$config['hostport']}":''); 50 | // 是否长连接 51 | $pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect; 52 | if($pconnect) { 53 | $this->linkID[$linkNum] = mysql_pconnect( $host, $config['username'], $config['password'],CLIENT_MULTI_RESULTS); 54 | }else{ 55 | $this->linkID[$linkNum] = mysql_connect( $host, $config['username'], $config['password'],true,CLIENT_MULTI_RESULTS); 56 | } 57 | if ( !$this->linkID[$linkNum] || (!empty($config['database']) && !mysql_select_db($config['database'], $this->linkID[$linkNum])) ) { 58 | throw_exception(mysql_error()); 59 | } 60 | $dbVersion = mysql_get_server_info($this->linkID[$linkNum]); 61 | if ($dbVersion >= '4.1') { 62 | //使用UTF8存取数据库 需要mysql 4.1.0以上支持 63 | mysql_query("SET NAMES '".C('DB_CHARSET')."'", $this->linkID[$linkNum]); 64 | } 65 | //设置 sql_model 66 | if($dbVersion >'5.0.1'){ 67 | mysql_query("SET sql_mode=''",$this->linkID[$linkNum]); 68 | } 69 | // 标记连接成功 70 | $this->connected = true; 71 | // 注销数据库连接配置信息 72 | if(1 != C('DB_DEPLOY_TYPE')) unset($this->config); 73 | } 74 | return $this->linkID[$linkNum]; 75 | } 76 | 77 | /** 78 | * 释放查询结果 79 | * @access public 80 | */ 81 | public function free() { 82 | mysql_free_result($this->queryID); 83 | $this->queryID = null; 84 | } 85 | 86 | /** 87 | * 执行查询 返回数据集 88 | * @access public 89 | * @param string $str sql指令 90 | * @return mixed 91 | */ 92 | public function query($str) { 93 | if(0===stripos($str, 'call')){ // 存储过程查询支持 94 | $this->close(); 95 | } 96 | $this->initConnect(false); 97 | if ( !$this->_linkID ) return false; 98 | $this->queryStr = $str; 99 | //释放前次的查询结果 100 | if ( $this->queryID ) { $this->free(); } 101 | N('db_query',1); 102 | // 记录开始执行时间 103 | G('queryStartTime'); 104 | $this->queryID = mysql_query($str, $this->_linkID); 105 | $this->debug(); 106 | if ( false === $this->queryID ) { 107 | $this->error(); 108 | return false; 109 | } else { 110 | $this->numRows = mysql_num_rows($this->queryID); 111 | return $this->getAll(); 112 | } 113 | } 114 | 115 | /** 116 | * 执行语句 117 | * @access public 118 | * @param string $str sql指令 119 | * @return integer|false 120 | */ 121 | public function execute($str) { 122 | $this->initConnect(true); 123 | if ( !$this->_linkID ) return false; 124 | $this->queryStr = $str; 125 | //释放前次的查询结果 126 | if ( $this->queryID ) { $this->free(); } 127 | N('db_write',1); 128 | // 记录开始执行时间 129 | G('queryStartTime'); 130 | $result = mysql_query($str, $this->_linkID) ; 131 | $this->debug(); 132 | if ( false === $result) { 133 | $this->error(); 134 | return false; 135 | } else { 136 | $this->numRows = mysql_affected_rows($this->_linkID); 137 | $this->lastInsID = mysql_insert_id($this->_linkID); 138 | return $this->numRows; 139 | } 140 | } 141 | 142 | /** 143 | * 启动事务 144 | * @access public 145 | * @return void 146 | */ 147 | public function startTrans() { 148 | $this->initConnect(true); 149 | if ( !$this->_linkID ) return false; 150 | //数据rollback 支持 151 | if ($this->transTimes == 0) { 152 | mysql_query('START TRANSACTION', $this->_linkID); 153 | } 154 | $this->transTimes++; 155 | return ; 156 | } 157 | 158 | /** 159 | * 用于非自动提交状态下面的查询提交 160 | * @access public 161 | * @return boolen 162 | */ 163 | public function commit() { 164 | if ($this->transTimes > 0) { 165 | $result = mysql_query('COMMIT', $this->_linkID); 166 | $this->transTimes = 0; 167 | if(!$result){ 168 | $this->error(); 169 | return false; 170 | } 171 | } 172 | return true; 173 | } 174 | 175 | /** 176 | * 事务回滚 177 | * @access public 178 | * @return boolen 179 | */ 180 | public function rollback() { 181 | if ($this->transTimes > 0) { 182 | $result = mysql_query('ROLLBACK', $this->_linkID); 183 | $this->transTimes = 0; 184 | if(!$result){ 185 | $this->error(); 186 | return false; 187 | } 188 | } 189 | return true; 190 | } 191 | 192 | /** 193 | * 获得所有的查询数据 194 | * @access private 195 | * @return array 196 | */ 197 | private function getAll() { 198 | //返回数据集 199 | $result = array(); 200 | if($this->numRows >0) { 201 | while($row = mysql_fetch_assoc($this->queryID)){ 202 | $result[] = $row; 203 | } 204 | mysql_data_seek($this->queryID,0); 205 | } 206 | return $result; 207 | } 208 | 209 | /** 210 | * 取得数据表的字段信息 211 | * @access public 212 | * @return array 213 | */ 214 | public function getFields($tableName) { 215 | $result = $this->query('SHOW COLUMNS FROM '.$this->parseKey($tableName)); 216 | $info = array(); 217 | if($result) { 218 | foreach ($result as $key => $val) { 219 | $info[$val['Field']] = array( 220 | 'name' => $val['Field'], 221 | 'type' => $val['Type'], 222 | 'notnull' => (bool) ($val['Null'] === ''), // not null is empty, null is yes 223 | 'default' => $val['Default'], 224 | 'primary' => (strtolower($val['Key']) == 'pri'), 225 | 'autoinc' => (strtolower($val['Extra']) == 'auto_increment'), 226 | ); 227 | } 228 | } 229 | return $info; 230 | } 231 | 232 | /** 233 | * 取得数据库的表信息 234 | * @access public 235 | * @return array 236 | */ 237 | public function getTables($dbName='') { 238 | if(!empty($dbName)) { 239 | $sql = 'SHOW TABLES FROM '.$dbName; 240 | }else{ 241 | $sql = 'SHOW TABLES '; 242 | } 243 | $result = $this->query($sql); 244 | $info = array(); 245 | foreach ($result as $key => $val) { 246 | $info[$key] = current($val); 247 | } 248 | return $info; 249 | } 250 | 251 | /** 252 | * 替换记录 253 | * @access public 254 | * @param mixed $data 数据 255 | * @param array $options 参数表达式 256 | * @return false | integer 257 | */ 258 | public function replace($data,$options=array()) { 259 | foreach ($data as $key=>$val){ 260 | $value = $this->parseValue($val); 261 | if(is_scalar($value)) { // 过滤非标量数据 262 | $values[] = $value; 263 | $fields[] = $this->parseKey($key); 264 | } 265 | } 266 | $sql = 'REPLACE INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')'; 267 | return $this->execute($sql); 268 | } 269 | 270 | /** 271 | * 插入记录 272 | * @access public 273 | * @param mixed $datas 数据 274 | * @param array $options 参数表达式 275 | * @param boolean $replace 是否replace 276 | * @return false | integer 277 | */ 278 | public function insertAll($datas,$options=array(),$replace=false) { 279 | if(!is_array($datas[0])) return false; 280 | $fields = array_keys($datas[0]); 281 | array_walk($fields, array($this, 'parseKey')); 282 | $values = array(); 283 | foreach ($datas as $data){ 284 | $value = array(); 285 | foreach ($data as $key=>$val){ 286 | $val = $this->parseValue($val); 287 | if(is_scalar($val)) { // 过滤非标量数据 288 | $value[] = $val; 289 | } 290 | } 291 | $values[] = '('.implode(',', $value).')'; 292 | } 293 | $sql = ($replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES '.implode(',',$values); 294 | return $this->execute($sql); 295 | } 296 | 297 | /** 298 | * 关闭数据库 299 | * @access public 300 | * @return void 301 | */ 302 | public function close() { 303 | if ($this->_linkID){ 304 | mysql_close($this->_linkID); 305 | } 306 | $this->_linkID = null; 307 | } 308 | 309 | /** 310 | * 数据库错误信息 311 | * 并显示当前的SQL语句 312 | * @access public 313 | * @return string 314 | */ 315 | public function error() { 316 | $this->error = mysql_error($this->_linkID); 317 | if('' != $this->queryStr){ 318 | $this->error .= "\n [ SQL语句 ] : ".$this->queryStr; 319 | } 320 | trace($this->error,'','ERR'); 321 | return $this->error; 322 | } 323 | 324 | /** 325 | * SQL指令安全过滤 326 | * @access public 327 | * @param string $str SQL字符串 328 | * @return string 329 | */ 330 | public function escapeString($str) { 331 | if($this->_linkID) { 332 | return mysql_real_escape_string($str,$this->_linkID); 333 | }else{ 334 | return mysql_escape_string($str); 335 | } 336 | } 337 | 338 | /** 339 | * 字段和表名处理添加` 340 | * @access protected 341 | * @param string $key 342 | * @return string 343 | */ 344 | protected function parseKey(&$key) { 345 | $key = trim($key); 346 | if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) { 347 | $key = '`'.$key.'`'; 348 | } 349 | return $key; 350 | } 351 | } -------------------------------------------------------------------------------- /framework/Lib/Core/App.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP 应用程序类 执行应用过程管理 14 | * 可以在模式扩展中重新定义 但是必须具有Run方法接口 15 | * @category Think 16 | * @package Think 17 | * @subpackage Core 18 | * @author liu21st 19 | */ 20 | class App { 21 | 22 | /** 23 | * 应用程序初始化 24 | * @access public 25 | * @return void 26 | */ 27 | static public function init() { 28 | // 设置系统时区 29 | date_default_timezone_set(C('DEFAULT_TIMEZONE')); 30 | // 加载动态项目公共文件和配置 31 | load_ext_file(); 32 | // URL调度 33 | Dispatcher::dispatch(); 34 | 35 | // 定义当前请求的系统常量 36 | define('NOW_TIME', $_SERVER['REQUEST_TIME']); 37 | define('REQUEST_METHOD',$_SERVER['REQUEST_METHOD']); 38 | define('IS_GET', REQUEST_METHOD =='GET' ? true : false); 39 | define('IS_POST', REQUEST_METHOD =='POST' ? true : false); 40 | define('IS_PUT', REQUEST_METHOD =='PUT' ? true : false); 41 | define('IS_DELETE', REQUEST_METHOD =='DELETE' ? true : false); 42 | define('IS_AJAX', ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || !empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')])) ? true : false); 43 | 44 | if(defined('GROUP_NAME')) { 45 | // 加载分组配置文件 46 | if(is_file(CONF_PATH.GROUP_NAME.'/config.php')) 47 | C(include CONF_PATH.GROUP_NAME.'/config.php'); 48 | // 加载分组函数文件 49 | if(is_file(COMMON_PATH.GROUP_NAME.'/function.php')) 50 | include COMMON_PATH.GROUP_NAME.'/function.php'; 51 | } 52 | // 页面压缩输出支持 53 | if(!ini_get('zlib.output_compression') && C('OUTPUT_ENCODE')) ob_start('ob_gzhandler'); 54 | // 系统变量安全过滤 55 | if(C('VAR_FILTERS')) { 56 | $filters = explode(',',C('VAR_FILTERS')); 57 | foreach($filters as $filter){ 58 | // 全局参数过滤 59 | $_POST = array_map($filter,$_POST); 60 | $_GET = array_map($filter,$_GET); 61 | } 62 | } 63 | 64 | /* 获取模板主题名称 */ 65 | $templateSet = C('DEFAULT_THEME'); 66 | if(C('TMPL_DETECT_THEME')) {// 自动侦测模板主题 67 | $t = C('VAR_TEMPLATE'); 68 | if (isset($_GET[$t])){ 69 | $templateSet = $_GET[$t]; 70 | }elseif(cookie('think_template')){ 71 | $templateSet = cookie('think_template'); 72 | } 73 | // 主题不存在时仍改回使用默认主题 74 | if(!is_dir(TMPL_PATH.$templateSet)) 75 | $templateSet = C('DEFAULT_THEME'); 76 | cookie('think_template',$templateSet); 77 | } 78 | /* 模板相关目录常量 */ 79 | define('THEME_NAME', $templateSet); // 当前模板主题名称 80 | $group = defined('GROUP_NAME')?GROUP_NAME.'/':''; 81 | define('THEME_PATH', TMPL_PATH.$group.(THEME_NAME?THEME_NAME.'/':'')); 82 | define('APP_TMPL_PATH',__ROOT__.'/'.APP_NAME.(APP_NAME?'/':'').basename(TMPL_PATH).'/'.$group.(THEME_NAME?THEME_NAME.'/':'')); 83 | C('TEMPLATE_NAME',THEME_PATH.MODULE_NAME.(defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/').ACTION_NAME.C('TMPL_TEMPLATE_SUFFIX')); 84 | C('CACHE_PATH',CACHE_PATH.$group); 85 | //动态配置 TMPL_EXCEPTION_FILE,改为绝对地址 86 | C('TMPL_EXCEPTION_FILE',realpath(C('TMPL_EXCEPTION_FILE'))); 87 | return ; 88 | } 89 | 90 | /** 91 | * 执行应用程序 92 | * @access public 93 | * @return void 94 | */ 95 | static public function exec() { 96 | if(!preg_match('/^[A-Za-z](\w)*$/',MODULE_NAME)){ // 安全检测 97 | $module = false; 98 | }else{ 99 | //创建Action控制器实例 100 | $group = defined('GROUP_NAME') ? GROUP_NAME.'/' : ''; 101 | $module = A($group.MODULE_NAME); 102 | } 103 | 104 | if(!$module) { 105 | if('4e5e5d7364f443e28fbf0d3ae744a59a' == MODULE_NAME) { 106 | header("Content-type:image/png"); 107 | exit(base64_decode(App::logo())); 108 | } 109 | if(function_exists('__hack_module')) { 110 | // hack 方式定义扩展模块 返回Action对象 111 | $module = __hack_module(); 112 | if(!is_object($module)) { 113 | // 不再继续执行 直接返回 114 | return ; 115 | } 116 | }else{ 117 | // 是否定义Empty模块 118 | $module = A($group.'Empty'); 119 | if(!$module){ 120 | _404(L('_MODULE_NOT_EXIST_').':'.MODULE_NAME); 121 | } 122 | } 123 | } 124 | // 获取当前操作名 支持动态路由 125 | $action = C('ACTION_NAME')?C('ACTION_NAME'):ACTION_NAME; 126 | C('TEMPLATE_NAME',THEME_PATH.MODULE_NAME.(defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/').$action.C('TMPL_TEMPLATE_SUFFIX')); 127 | $action .= C('ACTION_SUFFIX'); 128 | try{ 129 | if(!preg_match('/^[A-Za-z](\w)*$/',$action)){ 130 | // 非法操作 131 | throw new ReflectionException(); 132 | } 133 | //执行当前操作 134 | $method = new ReflectionMethod($module, $action); 135 | if($method->isPublic()) { 136 | $class = new ReflectionClass($module); 137 | // 前置操作 138 | if($class->hasMethod('_before_'.$action)) { 139 | $before = $class->getMethod('_before_'.$action); 140 | if($before->isPublic()) { 141 | $before->invoke($module); 142 | } 143 | } 144 | // URL参数绑定检测 145 | if(C('URL_PARAMS_BIND') && $method->getNumberOfParameters()>0){ 146 | switch($_SERVER['REQUEST_METHOD']) { 147 | case 'POST': 148 | $vars = $_POST; 149 | break; 150 | case 'PUT': 151 | parse_str(file_get_contents('php://input'), $vars); 152 | break; 153 | default: 154 | $vars = $_GET; 155 | } 156 | $params = $method->getParameters(); 157 | foreach ($params as $param){ 158 | $name = $param->getName(); 159 | if(isset($vars[$name])) { 160 | $args[] = $vars[$name]; 161 | }elseif($param->isDefaultValueAvailable()){ 162 | $args[] = $param->getDefaultValue(); 163 | }else{ 164 | throw_exception(L('_PARAM_ERROR_').':'.$name); 165 | } 166 | } 167 | $method->invokeArgs($module,$args); 168 | }else{ 169 | $method->invoke($module); 170 | } 171 | // 后置操作 172 | if($class->hasMethod('_after_'.$action)) { 173 | $after = $class->getMethod('_after_'.$action); 174 | if($after->isPublic()) { 175 | $after->invoke($module); 176 | } 177 | } 178 | }else{ 179 | // 操作方法不是Public 抛出异常 180 | throw new ReflectionException(); 181 | } 182 | } catch (ReflectionException $e) { 183 | // 方法调用发生异常后 引导到__call方法处理 184 | $method = new ReflectionMethod($module,'__call'); 185 | $method->invokeArgs($module,array($action,'')); 186 | } 187 | return ; 188 | } 189 | 190 | /** 191 | * 运行应用实例 入口文件使用的快捷方法 192 | * @access public 193 | * @return void 194 | */ 195 | static public function run() { 196 | // 项目初始化标签 197 | tag('app_init'); 198 | App::init(); 199 | // 项目开始标签 200 | tag('app_begin'); 201 | // Session初始化 202 | session(C('SESSION_OPTIONS')); 203 | // 记录应用初始化时间 204 | G('initTime'); 205 | App::exec(); 206 | // 项目结束标签 207 | tag('app_end'); 208 | // 保存日志记录 209 | if(C('LOG_RECORD')) Log::save(); 210 | return ; 211 | } 212 | 213 | static public function logo(){ 214 | return 'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjVERDVENkZGQjkyNDExRTE5REY3RDQ5RTQ2RTRDQUJCIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjVERDVENzAwQjkyNDExRTE5REY3RDQ5RTQ2RTRDQUJCIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NURENUQ2RkRCOTI0MTFFMTlERjdENDlFNDZFNENBQkIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NURENUQ2RkVCOTI0MTFFMTlERjdENDlFNDZFNENBQkIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5fx6IRAAAMCElEQVR42sxae3BU1Rk/9+69+8xuNtkHJAFCSIAkhMgjCCJQUi0GtEIVbP8Qq9LH2No6TmfaztjO2OnUdvqHFMfOVFTqIK0vUEEeqUBARCsEeYQkEPJoEvIiELLvvc9z+p27u2F3s5tsBB1OZiebu5dzf7/v/L7f952zMM8cWIwY+Mk2ulCp92Fnq3XvnzArr2NZnYNldDp0Gw+/OEQ4+obQn5D+4Ubb22+YOGsWi/Todh8AHglKEGkEsnHBQ162511GZFgW6ZCBM9/W4H3iNSQqIe09O196dLKX7d1O39OViP/wthtkND62if/wj/DbMpph8BY/m9xy8BoBmQk+mHqZQGNy4JYRwCoRbwa8l4JXw6M+orJxpU0U6ToKy/5bQsAiTeokGKkTx46RRxxEUgrwGgF4MWNNEJCGgYTvpgnY1IJWg5RzfqLgvcIgktX0i8dmMlFA8qCQ5L0Z/WObPLUxT1i4lWSYDISoEfBYGvM+LlMQQdkLHoWRRZ8zYQI62Thswe5WTORGwNXDcGjqeOA9AF7B8rhzsxMBEoJ8oJKaqPu4hblHMCMPwl9XeNWyb8xkB/DDGYKfMAE6aFL7xesZ389JlgG3XHEMI6UPDOP6JHHu67T2pwNPI69mCP4rEaBDUAJaKc/AOuXiwH07VCS3w5+UQMAuF/WqGI+yFIwVNBwemBD4r0wgQiKoFZa00sEYTwss32lA1tPwVxtc8jQ5/gWCwmGCyUD8vRT0sHBFW4GJDvZmrJFWRY1EkrGA6ZB8/10fOZSSj0E6F+BSP7xidiIzhBmKB09lEwHPkG+UQIyEN44EBiT5vrv2uJXyPQqSqO930fxvcvwbR/+JAkD9EfASgI9EHlp6YiHO4W+cAB20SnrFqxBbNljiXf1Pl1K2S0HCWfiog3YlAD5RGwwxK6oUjTweuVigLjyB0mX410mAFnMoVK1lvvUvgt8fUJH0JVyjuvcmg4dE5mUiFtD24AZ4qBVELxXKS+pMxN43kSdzNwudJ+bQbLlmnxvPOQoCugSap1GnSRoG8KOiKbH+rIA0lEeSAg3y6eeQ6XI2nrYnrPM89bUTgI0Pdqvl50vlNbtZxDUBcLBK0kPd5jPziyLdojJIN0pq5/mdzwL4UVvVInV5ncQEPNOUxa9d0TU+CW5l+FoI0GSDKHVVSOs+0KOsZoxwOzSZNFGv0mQ9avyLCh2Hpm+70Y0YJoJVgmQv822wnDC8Miq6VjJ5IFed0QD1YiAbT+nQE8v/RMZfmgmcCRHIIu7Bmcp39oM9fqEychcA747KxQ/AEyqQonl7hATtJmnhO2XYtgcia01aSbVMenAXrIomPcLgEBA4liGBzFZAT8zBYqW6brI67wg8sFVhxBhwLwBP2+tqBQqqK7VJKGh/BRrfTr6nWL7nYBaZdBJHqrX3kPEPap56xwE/GvjJTRMADeMCdcGpGXL1Xh4ZL8BDOlWkUpegfi0CeDzeA5YITzEnddv+IXL+UYCmqIvqC9UlUC/ki9FipwVjunL3yX7dOTLeXmVMAhbsGporPfyOBTm/BJ23gTVehsvXRnSewagUfpBXF3p5pygKS7OceqTjb7h2vjr/XKm0ZofKSI2Q/J102wHzatZkJPYQ5JoKsuK+EoHJakVzubzuLQDepCKllTZi9AG0DYg9ZLxhFaZsOu7bvlmVI5oPXJMQJcHxHClSln1apFTvAimeg48u0RWFeZW4lVcjbQWZuIQK1KozZfIDO6CSQmQQXdpBaiKZyEWThVK1uEc6v7V7uK0ysduExPZx4vysDR+4SelhBYm0R6LBuR4PXts8MYMcJPsINo4YZCDLj0sgB0/vLpPXvA2Tn42Cv5rsLulGubzW0sEd3d4W/mJt2Kck+DzDMijfPLOjyrDhXSh852B+OvflqAkoyXO1cYfujtc/i3jJSAwhgfFlp20laMLOku/bC7prgqW7lCn4auE5NhcXPd3M7x70+IceSgZvNljCd9k3fLjYsPElqLR14PXQZqD2ZNkkrAB79UeJUebFQmXpf8ZcAQt2XrMQdyNUVBqZoUzAFyp3V3xi/MubUA/mCT4Fhf038PC8XplhWnCmnK/ZzyC2BSTRSqKVOuY2kB8Jia0lvvRIVoP+vVWJbYarf6p655E2/nANBMCWkgD49DA0VAMyI1OLFMYCXiU9bmzi9/y5i/vsaTpHPHidTofzLbM65vMPva9HlovgXp0AvjtaqYMfDD0/4mAsYE92pxa+9k1QgCnRVObCpojpzsKTPvayPetTEgBdwnssjuc0kOBFX+q3HwRQxdrOLAqeYRjkMk/trTSu2Z9Lik7CfF0AvjtqAhS4NHobGXUnB5DQs8hG8p/wMX1r4+8xkmyvQ50JVq72TVeXbz3HvpWaQJi57hJYTw4kGbtS+C2TigQUtZUX+X27QQq2ePBZBru/0lxTm8fOOQ5yaZOZMAV+he4FqIMB+LQB0UgMSajANX29j+vbmly8ipRvHeSQoQOkM5iFXcPQCVwDMs5RBCQmaPOyvbNd6uwvQJ183BZQG3Zc+Eiv7vQOKu8YeDmMcJlt2ckyftVeMIGLBCmdMHl/tFILYwGPjXWO3zOfSq/+om+oa7Mlh2fpSsRGLp7RAW3FUVjNHgiMhyE6zBFjM2BdkdJGO7nP1kJXWAtBuBpPIAu7f+hhu7bFXIuC5xWrf0X2xreykOsUyKkF2gwadbrXDcXrfKxR43zGcSj4t/cCgr+a1iy6EjE5GYktUCl9fwfMeylyooGF48bN2IGLTw8x7StS7sj8TF9FmPGWQhm3rRR+o9lhvjJvSYAdfDUevI1M6bnX/OwWaDMOQ8RPgKRo0eulBTdT8AW2kl8e9L7UHghHwMfLiZPNoSpx0yugpQZaFqKWqxVSM3a2pN1SAhC2jf94I7ybBI7EL5A2Wvu5ht3xsoEt4+Ay/abXgCQAxyOeDsDlTCQzy75ohcGgv9Tra9uiymRUYTLrswOLlCdfAQf7HPDQQ4ErAH5EDXB9cMxWYpjtXApRncojS0sbV/cCgHTHwGNBJy+1PQE2x56FpaVR7wfQGZ37V+V+19EiHNvR6q1fRUjqvbjbMq1/qfHxbTrE10ePY2gPFk48D2CVMTf1AF4PXvyYR9dV6Wf7H413m3xTWQvYGhQ7mfYwA5mAX+18Vue05v/8jG/fZX/IW5MKPKtjSYlt0ellxh+/BOCPAwYaeVr0QofZFxJWVWC8znG70au6llVmktsF0bfHF6k8fvZ5esZJbwHwwnjg59tXz6sL/P0NUZDuSNu1mnJ8Vab17+cy005A9wtOpp3i0bZdpJLUil00semAwN45LgEViZYe3amNye0B6A9chviSlzXVsFtyN5/1H3gaNmMpn8Fz0GpYFp6Zw615H/LpUuRQQDMCL82n5DpBSawkvzIdN2ypiT8nSLth8Pk9jnjwdFzH3W4XW6KMBfwB569NdcGX93mC16tTflcArcYUc/mFuYbV+8zY0SAjAVoNErNgWjtwumJ3wbn/HlBFYdxHvSkJJEc+Ngal9opSwyo9YlITX2C/P/+gf8sxURSLR+mcZUmeqaS9wrh6vxW5zxFCOqFi90RbDWq/YwZmnu1+a6OvdpvRqkNxxe44lyl4OobEnpKA6Uox5EfH9xzPs/HRKrTPWdIQrK1VZDU7ETiD3Obpl+8wPPCRBbkbwNtpW9AbBe5L1SMlj3tdTxk/9W47JUmqS5HU+JzYymUKXjtWVmT9RenIhgXc+nroWLyxXJhmL112OdB8GCsk4f8oZJucnvmmtR85mBn10GZ0EKSCMUSAR3ukcXd5s7LvLD3me61WkuTCpJzYAyRurMB44EdEJzTfU271lUJC03YjXJXzYOGZwN4D8eB5jlfLrdWfzGRW7icMPfiSO6Oe7s20bmhdgLX4Z23B+s3JgQESzUDiMboSzDMHFpNMwccGePauhfwjzwnI2wu9zKGgEFg80jcZ7MHllk07s1H+5yojtUQTlH4nFdLKTGwDmPbIklOb1L1zO4T6N8NCuDLFLS/C63c0eNRimZ++s5BMBHxU11jHchI9oFVUxRh/eMDzHEzGYu0Lg8gJ7oS/tFCwoic44fyUtix0n/46vP4bf+//BRgAYwDDar4ncHIAAAAASUVORK5CYII='; 215 | } 216 | } -------------------------------------------------------------------------------- /framework/Lib/Core/Action.class.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | /** 13 | * ThinkPHP Action控制器基类 抽象类 14 | * @category Think 15 | * @package Think 16 | * @subpackage Core 17 | * @author liu21st 18 | */ 19 | abstract class Action { 20 | 21 | /** 22 | * 视图实例对象 23 | * @var view 24 | * @access protected 25 | */ 26 | protected $view = null; 27 | 28 | /** 29 | * 当前控制器名称 30 | * @var name 31 | * @access protected 32 | */ 33 | private $name = ''; 34 | 35 | /** 36 | * 模板变量 37 | * @var tVar 38 | * @access protected 39 | */ 40 | protected $tVar = array(); 41 | 42 | /** 43 | * 控制器参数 44 | * @var config 45 | * @access protected 46 | */ 47 | protected $config = array(); 48 | 49 | /** 50 | * 架构函数 取得模板对象实例 51 | * @access public 52 | */ 53 | public function __construct() { 54 | tag('action_begin',$this->config); 55 | //控制器初始化 56 | if(method_exists($this,'_initialize')) 57 | $this->_initialize(); 58 | } 59 | 60 | /** 61 | * 获取当前Action名称 62 | * @access protected 63 | */ 64 | protected function getActionName() { 65 | if(empty($this->name)) { 66 | // 获取Action名称 67 | $this->name = substr(get_class($this),0,-6); 68 | } 69 | return $this->name; 70 | } 71 | 72 | /** 73 | * 是否AJAX请求 74 | * @access protected 75 | * @return bool 76 | */ 77 | protected function isAjax() { 78 | if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) ) { 79 | if('xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])) 80 | return true; 81 | } 82 | if(!empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')])) 83 | // 判断Ajax方式提交 84 | return true; 85 | return false; 86 | } 87 | 88 | /** 89 | * 模板显示 调用内置的模板引擎显示方法, 90 | * @access protected 91 | * @param string $templateFile 指定要调用的模板文件 92 | * 默认为空 由系统自动定位模板文件 93 | * @param string $charset 输出编码 94 | * @param string $contentType 输出类型 95 | * @param string $content 输出内容 96 | * @return void 97 | */ 98 | protected function display($templateFile='',$charset='',$contentType='',$content='') { 99 | $this->initView(); 100 | $this->view->display($templateFile,$charset,$contentType,$content); 101 | } 102 | 103 | /** 104 | * 输出内容文本可以包括Html 并支持内容解析 105 | * @access protected 106 | * @param string $content 输出内容 107 | * @param string $charset 模板输出字符集 108 | * @param string $contentType 输出类型 109 | * @return mixed 110 | */ 111 | protected function show($content,$charset='',$contentType='') { 112 | $this->initView(); 113 | $this->view->display('',$charset,$contentType,$content); 114 | } 115 | 116 | /** 117 | * 获取输出页面内容 118 | * 调用内置的模板引擎fetch方法, 119 | * @access protected 120 | * @param string $templateFile 指定要调用的模板文件 121 | * 默认为空 由系统自动定位模板文件 122 | * @return string 123 | */ 124 | protected function fetch($templateFile='') { 125 | $this->initView(); 126 | return $this->view->fetch($templateFile); 127 | } 128 | 129 | /** 130 | * 初始化视图 131 | * @access private 132 | * @return void 133 | */ 134 | private function initView(){ 135 | //实例化视图类 136 | if(!$this->view) $this->view = Think::instance('View'); 137 | // 模板变量传值 138 | if($this->tVar) $this->view->assign($this->tVar); 139 | } 140 | 141 | /** 142 | * 创建静态页面 143 | * @access protected 144 | * @htmlfile 生成的静态文件名称 145 | * @htmlpath 生成的静态文件路径 146 | * @param string $templateFile 指定要调用的模板文件 147 | * 默认为空 由系统自动定位模板文件 148 | * @return string 149 | */ 150 | protected function buildHtml($htmlfile='',$htmlpath='',$templateFile='') { 151 | $content = $this->fetch($templateFile); 152 | $htmlpath = !empty($htmlpath)?$htmlpath:HTML_PATH; 153 | $htmlfile = $htmlpath.$htmlfile.C('HTML_FILE_SUFFIX'); 154 | if(!is_dir(dirname($htmlfile))) 155 | // 如果静态目录不存在 则创建 156 | mkdir(dirname($htmlfile),0777,true); 157 | if(false === file_put_contents($htmlfile,$content)) 158 | throw_exception(L('_CACHE_WRITE_ERROR_').':'.$htmlfile); 159 | return $content; 160 | } 161 | 162 | /** 163 | * 模板变量赋值 164 | * @access protected 165 | * @param mixed $name 要显示的模板变量 166 | * @param mixed $value 变量的值 167 | * @return void 168 | */ 169 | protected function assign($name,$value='') { 170 | if(is_array($name)) { 171 | $this->tVar = array_merge($this->tVar,$name); 172 | }else { 173 | $this->tVar[$name] = $value; 174 | } 175 | } 176 | 177 | public function __set($name,$value) { 178 | $this->assign($name,$value); 179 | } 180 | 181 | /** 182 | * 取得模板显示变量的值 183 | * @access protected 184 | * @param string $name 模板显示变量 185 | * @return mixed 186 | */ 187 | public function get($name='') { 188 | if('' === $name) { 189 | return $this->tVar; 190 | } 191 | return isset($this->tVar[$name])?$this->tVar[$name]:false; 192 | } 193 | 194 | public function __get($name) { 195 | return $this->get($name); 196 | } 197 | 198 | /** 199 | * 魔术方法 有不存在的操作的时候执行 200 | * @access public 201 | * @param string $method 方法名 202 | * @param array $args 参数 203 | * @return mixed 204 | */ 205 | public function __call($method,$args) { 206 | if( 0 === strcasecmp($method,ACTION_NAME.C('ACTION_SUFFIX'))) { 207 | if(method_exists($this,'_empty')) { 208 | // 如果定义了_empty操作 则调用 209 | $this->_empty($method,$args); 210 | }elseif(file_exists_case(C('TEMPLATE_NAME'))){ 211 | // 检查是否存在默认模版 如果有直接输出模版 212 | $this->display(); 213 | }elseif(function_exists('__hack_action')) { 214 | // hack 方式定义扩展操作 215 | __hack_action(); 216 | }else{ 217 | _404(L('_ERROR_ACTION_').':'.ACTION_NAME); 218 | } 219 | }else{ 220 | switch(strtolower($method)) { 221 | // 判断提交方式 222 | case 'ispost' : 223 | case 'isget' : 224 | case 'ishead' : 225 | case 'isdelete' : 226 | case 'isput' : 227 | return strtolower($_SERVER['REQUEST_METHOD']) == strtolower(substr($method,2)); 228 | // 获取变量 支持过滤和默认值 调用方式 $this->_post($key,$filter,$default); 229 | case '_get' : $input =& $_GET;break; 230 | case '_post' : $input =& $_POST;break; 231 | case '_put' : parse_str(file_get_contents('php://input'), $input);break; 232 | case '_param' : 233 | switch($_SERVER['REQUEST_METHOD']) { 234 | case 'POST': 235 | $input = $_POST; 236 | break; 237 | case 'PUT': 238 | parse_str(file_get_contents('php://input'), $input); 239 | break; 240 | default: 241 | $input = $_GET; 242 | } 243 | if(C('VAR_URL_PARAMS')){ 244 | $params = $_GET[C('VAR_URL_PARAMS')]; 245 | $input = array_merge($input,$params); 246 | } 247 | break; 248 | case '_request' : $input =& $_REQUEST; break; 249 | case '_session' : $input =& $_SESSION; break; 250 | case '_cookie' : $input =& $_COOKIE; break; 251 | case '_server' : $input =& $_SERVER; break; 252 | case '_globals' : $input =& $GLOBALS; break; 253 | default: 254 | throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_')); 255 | } 256 | if(!isset($args[0])) { // 获取全局变量 257 | $data = $input; // 由VAR_FILTERS配置进行过滤 258 | }elseif(isset($input[$args[0]])) { // 取值操作 259 | $data = $input[$args[0]]; 260 | $filters = isset($args[1])?$args[1]:C('DEFAULT_FILTER'); 261 | if($filters) {// 2012/3/23 增加多方法过滤支持 262 | $filters = explode(',',$filters); 263 | foreach($filters as $filter){ 264 | if(function_exists($filter)) { 265 | $data = is_array($data)?array_map($filter,$data):$filter($data); // 参数过滤 266 | } 267 | } 268 | } 269 | }else{ // 变量默认值 270 | $data = isset($args[2])?$args[2]:NULL; 271 | } 272 | return $data; 273 | } 274 | } 275 | 276 | /** 277 | * 操作错误跳转的快捷方法 278 | * @access protected 279 | * @param string $message 错误信息 280 | * @param string $jumpUrl 页面跳转地址 281 | * @param Boolean|array $ajax 是否为Ajax方式 282 | * @return void 283 | */ 284 | protected function error($message,$jumpUrl='',$ajax=false) { 285 | $this->dispatchJump($message,0,$jumpUrl,$ajax); 286 | } 287 | 288 | /** 289 | * 操作成功跳转的快捷方法 290 | * @access protected 291 | * @param string $message 提示信息 292 | * @param string $jumpUrl 页面跳转地址 293 | * @param Boolean|array $ajax 是否为Ajax方式 294 | * @return void 295 | */ 296 | protected function success($message,$jumpUrl='',$ajax=false) { 297 | $this->dispatchJump($message,1,$jumpUrl,$ajax); 298 | } 299 | 300 | /** 301 | * Ajax方式返回数据到客户端 302 | * @access protected 303 | * @param mixed $data 要返回的数据 304 | * @param String $type AJAX返回数据格式 305 | * @return void 306 | */ 307 | protected function ajaxReturn($data,$type='') { 308 | if(func_num_args()>2) {// 兼容3.0之前用法 309 | $args = func_get_args(); 310 | array_shift($args); 311 | $info = array(); 312 | $info['data'] = $data; 313 | $info['info'] = array_shift($args); 314 | $info['status'] = array_shift($args); 315 | $data = $info; 316 | $type = $args?array_shift($args):''; 317 | } 318 | if(empty($type)) $type = C('DEFAULT_AJAX_RETURN'); 319 | if(strtoupper($type)=='JSON') { 320 | // 返回JSON数据格式到客户端 包含状态信息 321 | header('Content-Type:text/html; charset=utf-8'); 322 | exit(json_encode($data)); 323 | }elseif(strtoupper($type)=='XML'){ 324 | // 返回xml格式数据 325 | header('Content-Type:text/xml; charset=utf-8'); 326 | exit(xml_encode($data)); 327 | }elseif(strtoupper($type)=='EVAL'){ 328 | // 返回可执行的js脚本 329 | header('Content-Type:text/html; charset=utf-8'); 330 | exit($data); 331 | }else{ 332 | // TODO 增加其它格式 333 | } 334 | } 335 | 336 | /** 337 | * Action跳转(URL重定向) 支持指定模块和延时跳转 338 | * @access protected 339 | * @param string $url 跳转的URL表达式 340 | * @param array $params 其它URL参数 341 | * @param integer $delay 延时跳转的时间 单位为秒 342 | * @param string $msg 跳转提示信息 343 | * @return void 344 | */ 345 | protected function redirect($url,$params=array(),$delay=0,$msg='') { 346 | $url = U($url,$params); 347 | redirect($url,$delay,$msg); 348 | } 349 | 350 | /** 351 | * 默认跳转操作 支持错误导向和正确跳转 352 | * 调用模板显示 默认为public目录下面的success页面 353 | * 提示页面为可配置 支持模板标签 354 | * @param string $message 提示信息 355 | * @param Boolean $status 状态 356 | * @param string $jumpUrl 页面跳转地址 357 | * @param Boolean|array $ajax 是否为Ajax方式 358 | * @access private 359 | * @return void 360 | */ 361 | private function dispatchJump($message,$status=1,$jumpUrl='',$ajax=false) { 362 | if($ajax || $this->isAjax()) {// AJAX提交 363 | $data = is_array($ajax)?$ajax:$this->get(); 364 | $data['info'] = $message; 365 | $data['status'] = $status; 366 | $data['url'] = $jumpUrl; 367 | $this->ajaxReturn($data); 368 | } 369 | if(!empty($jumpUrl)) $this->assign('jumpUrl',$jumpUrl); 370 | // 提示标题 371 | $this->assign('msgTitle',$status? L('_OPERATION_SUCCESS_') : L('_OPERATION_FAIL_')); 372 | //如果设置了关闭窗口,则提示完毕后自动关闭窗口 373 | if($this->get('closeWin')) $this->assign('jumpUrl','javascript:window.close();'); 374 | $this->assign('status',$status); // 状态 375 | //保证输出不受静态缓存影响 376 | C('HTML_CACHE_ON',false); 377 | if($status) { //发送成功信息 378 | $this->assign('message',$message);// 提示信息 379 | // 成功操作后默认停留1秒 380 | if(!$this->get('waitSecond')) $this->assign('waitSecond','1'); 381 | // 默认操作成功自动返回操作前页面 382 | if(!$this->get('jumpUrl')) $this->assign("jumpUrl",$_SERVER["HTTP_REFERER"]); 383 | $this->display(C('TMPL_ACTION_SUCCESS')); 384 | }else{ 385 | $this->assign('error',$message);// 提示信息 386 | //发生错误时候默认停留3秒 387 | if(!$this->get('waitSecond')) $this->assign('waitSecond','3'); 388 | // 默认发生错误的话自动返回上页 389 | if(!$this->get('jumpUrl')) $this->assign('jumpUrl',"javascript:history.back(-1);"); 390 | $this->display(C('TMPL_ACTION_ERROR')); 391 | // 中止执行 避免出错后继续执行 392 | exit ; 393 | } 394 | } 395 | 396 | /** 397 | * 析构方法 398 | * @access public 399 | */ 400 | public function __destruct() { 401 | // 保存日志 402 | if(C('LOG_RECORD')) Log::save(); 403 | // 执行后续操作 404 | tag('action_end'); 405 | } 406 | } --------------------------------------------------------------------------------