invoke($data); } /** * 获取输入参数 支持过滤和默认值 * 使用方法: * * I('id',0); 获取id参数 自动判断get或者post * I('post.name','','htmlspecialchars'); 获取$_POST['name'] * I('get.'); 获取$_GET * * @param string $name 变量的名称 支持指定类型 * @param mixed $default 不存在的时候默认值 * @param mixed $filter 参数过滤方法 * @return mixed */ function I($name,$default='',$filter=null) { if(strpos($name,'.')) { // 指定参数来源 //判断参数$name中是否包括.号 list($method,$name) = explode('.',$name,2); //如果包括.号将.号前后分隔,并且分别赋值给$method以及$name }else{ // 默认为自动判断 //如果没有.号 $method = 'param'; } switch(strtolower($method)) {//将$method转换为小写 //如果$method为get,则$input为$_GET case 'get' : $input =& $_GET;break; //如果$method为get,则$input为$_POST case 'post' : $input =& $_POST;break; //如果为put,则将post的原始数据转参数给$input case 'put' : parse_str(file_get_contents('php://input'), $input);break; //如果是param case 'param' : //判断$_SERVER['REQUEST_METHOD'] switch($_SERVER['REQUEST_METHOD']) { //如果为post,则$input的内容为$_POST的内容 case 'POST': $input = $_POST; break; //如果为PUT.则input的内容为PUT的内容 case 'PUT': parse_str(file_get_contents('php://input'), $input); break; //默认为$_GET的内容 default: $input = $_GET; } break; //如果$method为request,则$input为$_REQUEST case 'request' : $input =& $_REQUEST; break; //如果$method为session,则$input为$_SESSION case 'session' : $input =& $_SESSION; break; //如果$method为cookie,则$input为$_COOKIE case 'cookie' : $input =& $_COOKIE; break; //如果$method为server,则$input为$_SERVER case 'server' : $input =& $_SERVER; break; //如果$method为globals,则$input为$GLOBALS case 'globals' : $input =& $GLOBALS; break; //默认返回空 default: return NULL; } /** * 到此为止,已经根据传入的参数的需要(第一个参数.号前面的),把所有的变量都取到了。下面就是返回变量的内容了。 **/ //如果$name为空,也就是I()第一个参数的.号后面为空的时候 if(empty($name)) { // 获取全部变量 //获取到的变量$input全部复制给$data $data = $input; //array_walk_recursive — 对数组中的每个成员递归地应用用户函数 //将$data的键值作为filter_exp函数的第一个参数,键名作为第二个参数 //如果$data的键值中含有or或者exp这两个字符,自动在后面加一个空格 array_walk_recursive($data,'filter_exp'); //判断过滤参数是否有,如果有的话,就直接使用过滤方法,如果没有的话,就使用配置中的过滤方法 $filters = isset($filter)?$filter:C('DEFAULT_FILTER'); if($filters) { $filters = explode(',',$filters); //将过滤参数中的每个方法都应用到$data中 foreach($filters as $filter){ //将$data的每个值使用$filters过滤 $data = array_map_recursive($filter,$data); // 参数过滤 } } }elseif(isset($input[$name])) { // 取值操作 $data = $input[$name]; is_array($data) && array_walk_recursive($data,'filter_exp'); $filters = isset($filter)?$filter:C('DEFAULT_FILTER'); if($filters) { $filters = explode(',',$filters); foreach($filters as $filter){ if(function_exists($filter)) { $data = is_array($data)?array_map_recursive($filter,$data):$filter($data); // 参数过滤 }else{ $data = filter_var($data,is_int($filter)?$filter:filter_id($filter)); if(false === $data) { return isset($default)?$default:NULL; } } } } }else{ // 变量默认值 $data = isset($default)?$default:NULL; } return $data; } /** * 终止程序运行 * @param string $str 终止原因 * @param bool $display 是否显示调用栈,默认不显示 * @return void */ function halt($str, $display=false){ Log::fatal($str.' debug_backtrace:'.var_export(debug_backtrace(), true)); header("Content-Type:text/html; charset=utf-8"); if($display){ echo "
";
        debug_print_backtrace();
        echo "
"; } echo $str; exit; } /** * 获取数据库实例 * @return DB */ function M(){ $dbConf = C(array('DB_HOST','DB_PORT','DB_USER','DB_PWD','DB_NAME','DB_CHARSET')); return DB::getInstance($dbConf); } /** * 如果文件存在就include进来 * @param string $path 文件路径 * @return void */ function includeIfExist($path){ if(file_exists($path)){ include $path; } } /** * 总控类 */ class SinglePHP { /** * 控制器 * @var string */ private $c; /** * Action * @var string */ private $a; /** * 单例 * @var SinglePHP */ private static $_instance; /** * 构造函数,初始化配置 * @param array $conf */ private function __construct($conf){ C($conf); } private function __clone(){} /** * 获取单例 * @param array $conf * @return SinglePHP */ public static function getInstance($conf){ if(!(self::$_instance instanceof self)){ self::$_instance = new self($conf); } return self::$_instance; } /** * 运行应用实例 * @access public * @return void */ public function run(){ if(C('USE_SESSION') == true){ session_start(); } C('APP_FULL_PATH', getcwd().'/'.C('APP_PATH').'/'); $pathMod = C('PATH_MOD'); $pathMod = empty($pathMod)?'NORMAL':$pathMod; spl_autoload_register(array('SinglePHP', 'autoload')); if(strcmp(strtoupper($pathMod),'NORMAL') === 0 || !isset($_SERVER['PATH_INFO'])){ $this->c = isset($_GET['c'])?$_GET['c']:'Index'; $this->a = isset($_GET['a'])?$_GET['a']:'Index'; }else{ $pathInfo = isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:''; $pathInfoArr = explode('/',trim($pathInfo,'/')); if(isset($pathInfoArr[0]) && $pathInfoArr[0] !== ''){ $this->c = $pathInfoArr[0]; }else{ $this->c = 'Index'; } if(isset($pathInfoArr[1])){ $this->a = $pathInfoArr[1]; }else{ $this->a = 'Index'; } } $controllerClass = $this->c.'Controller'; $controller = new $controllerClass(); if(!class_exists($this->c.'Controller')){ //halt('控制器'.$this->c.'不存在'); //halt('jsonp1({"error":"控制器'.$this->c.'不存在"})'); halt('jsonp1({"error":"非法访问"})'); } if($this->c == "index" || $this->c == "Index" ||$this->c == "api" || $this->c == "Api" || $this->c == "other" || $this->c == "Other"){ call_user_func(array($controller,'BaseAction'),$this->a); }else{ call_user_func(array($controller,$this->a.'Action')); } } /** * 自动加载函数 * @param string $class 类名 */ public static function autoload($class){ if(substr($class,-10)=='Controller'){ includeIfExist(C('APP_FULL_PATH').'/Controller/'.$class.'.class.php'); }elseif(substr($class,-6)=='Widget'){ includeIfExist(C('APP_FULL_PATH').'/Widget/'.$class.'.class.php'); }else{ includeIfExist(C('APP_FULL_PATH').'/Lib/'.$class.'.class.php'); } } } /** * 控制器类 */ class Controller { /** * 视图实例 * @var View */ private $_view; /** * 构造函数,初始化视图实例,调用hook */ public function __construct(){ $this->_view = new View(); $this->_init(); } /** * 前置hook */ protected function _init(){} /** * 渲染模板并输出 * @param null|string $tpl 模板文件路径 * 参数为相对于App/View/文件的相对路径,不包含后缀名,例如index/index * 如果参数为空,则默认使用$controller/$action.php * 如果参数不包含"/",则默认使用$controller/$tpl * @return void */ protected function display($tpl=''){ if($tpl === ''){ $trace = debug_backtrace(); $controller = substr($trace[1]['class'], 0, -10); $action = substr($trace[1]['function'], 0 , -6); $tpl = $controller . '/' . $action; }elseif(strpos($tpl, '/') === false){ $trace = debug_backtrace(); $controller = substr($trace[1]['class'], 0, -10); $tpl = $controller . '/' . $tpl; } $this->_view->display($tpl); } /** * 为视图引擎设置一个模板变量 * @param string $name 要在模板中使用的变量名 * @param mixed $value 模板中该变量名对应的值 * @return void */ protected function assign($name,$value){ $this->_view->assign($name,$value); } /** * 将数据用json格式输出至浏览器,并停止执行代码 * @param array $data 要输出的数据 */ protected function ajaxReturn($data){ echo json_encode($data); exit; } /** * 重定向至指定url * @param string $url 要跳转的url * @param void */ protected function redirect($url){ header("Location: $url"); exit; } } /** * 视图类 */ class View { /** * 视图文件目录 * @var string */ private $_tplDir; /** * 视图文件路径 * @var string */ private $_viewPath; /** * 视图变量列表 * @var array */ private $_data = array(); /** * 给tplInclude用的变量列表 * @var array */ private static $tmpData; /** * @param string $tplDir */ public function __construct($tplDir=''){ if($tplDir == ''){ $this->_tplDir = './'.C('APP_PATH').'/View/'; }else{ $this->_tplDir = $tplDir; } } /** * 为视图引擎设置一个模板变量 * @param string $key 要在模板中使用的变量名 * @param mixed $value 模板中该变量名对应的值 * @return void */ public function assign($key, $value) { $this->_data[$key] = $value; } /** * 渲染模板并输出 * @param null|string $tplFile 模板文件路径,相对于App/View/文件的相对路径,不包含后缀名,例如index/index * @return void */ public function display($tplFile) { $this->_viewPath = $this->_tplDir . $tplFile . '.php'; unset($tplFile); extract($this->_data); include $this->_viewPath; } /** * 用于在模板文件中包含其他模板 * @param string $path 相对于View目录的路径 * @param array $data 传递给子模板的变量列表,key为变量名,value为变量值 * @return void */ public static function tplInclude($path, $data=array()){ self::$tmpData = array( 'path' => C('APP_FULL_PATH') . '/View/' . $path . '.php', 'data' => $data, ); unset($path); unset($data); extract(self::$tmpData['data']); include self::$tmpData['path']; } } /** * Widget类 * 使用时需继承此类,重写invoke方法,并在invoke方法中调用display */ class Widget { /** * 视图实例 * @var View */ protected $_view; /** * Widget名 * @var string */ protected $_widgetName; /** * 构造函数,初始化视图实例 */ public function __construct(){ $this->_widgetName = get_class($this); $dir = C('APP_FULL_PATH') . '/Widget/Tpl/'; $this->_view = new View($dir); } /** * 处理逻辑 * @param mixed $data 参数 */ public function invoke($data){} /** * 渲染模板 * @param string $tpl 模板路径,如果为空则用类名作为模板名 */ protected function display($tpl=''){ if($tpl == ''){ $tpl = $this->_widgetName; } $this->_view->display($tpl); } /** * 为视图引擎设置一个模板变量 * @param string $name 要在模板中使用的变量名 * @param mixed $value 模板中该变量名对应的值 * @return void */ protected function assign($name,$value){ $this->_view->assign($name,$value); } } /** * 数据库操作类 * 使用方法: * DB::getInstance($conf)->query('select * from table'); * 其中$conf是一个关联数组,需要包含以下key: * DB_HOST DB_USER DB_PWD DB_NAME * 可以用DB_PORT和DB_CHARSET来指定端口和编码,默认3306和utf8 */ class DB { /** * 数据库链接 * @var resource */ private $_db; /** * 保存最后一条sql * @var string */ private $_lastSql; /** * 上次sql语句影响的行数 * @var int */ private $_rows; /** * 上次sql执行的错误 * @var string */ private $_error; /** * 实例数组 * @var array */ private static $_instance = array(); /** * 构造函数 * @param array $dbConf 配置数组 */ private function __construct($dbConf){ if(!isset($dbConf['DB_CHARSET'])){ $dbConf['DB_CHARSET'] = 'utf8'; } $this->_db = mysql_connect($dbConf['DB_HOST'].':'.$dbConf['DB_PORT'],$dbConf['DB_USER'],$dbConf['DB_PWD']); if($this->_db === false){ halt(mysql_error()); } $selectDb = mysql_select_db($dbConf['DB_NAME'],$this->_db); if($selectDb === false){ halt(mysql_error()); } mysql_set_charset($dbConf['DB_CHARSET']); } private function __clone(){} /** * 获取DB类 * @param array $dbConf 配置数组 * @return DB */ static public function getInstance($dbConf){ if(!isset($dbConf['DB_PORT'])){ $dbConf['DB_PORT'] = '3306'; } $key = $dbConf['DB_HOST'].':'.$dbConf['DB_PORT']; if(!isset(self::$_instance[$key]) || !(self::$_instance[$key] instanceof self)){ self::$_instance[$key] = new self($dbConf); } return self::$_instance[$key]; } /** * 转义字符串 * @param string $str 要转义的字符串 * @return string 转义后的字符串 */ public function escape($str){ return mysql_real_escape_string($str, $this->_db); } /** * 查询,用于select语句 * @param string $sql 要查询的sql * @return bool|array 查询成功返回对应数组,失败返回false */ public function query($sql){ $this->_rows = 0; $this->_error = ''; $this->_lastSql = $sql; $this->logSql(); $res = mysql_query($sql,$this->_db); if($res === false){ $this->_error = mysql_error($this->_db); $this->logError(); return false; }else{ $this->_rows = mysql_num_rows($res); $result = array(); if($this->_rows >0) { while($row = mysql_fetch_array($res, MYSQL_ASSOC)){ $result[] = $row; } mysql_data_seek($res,0); } return $result; } } /** * 查询,用于insert/update/delete语句 * @param string $sql 要查询的sql * @return bool|int 查询成功返回影响的记录数量,失败返回false */ public function execute($sql) { $this->_rows = 0; $this->_error = ''; $this->_lastSql = $sql; $this->logSql(); $result = mysql_query($sql, $this->_db) ; if ( false === $result) { $this->_error = mysql_error($this->_db); $this->logError(); return false; } else { $this->_rows = mysql_affected_rows($this->_db); return $this->_rows; } } /** * 查询,用于insert/update/delete语句 * @param string $sql 要查询的sql * @return bool|int 查询成功返回影响的记录数量,失败返回false */ public function executeinsert($sql) { $this->_rows = 0; $this->_error = ''; $this->_lastSql = $sql; $this->logSql(); $result = mysql_query($sql, $this->_db) ; if ( false === $result) { $this->_error = mysql_error($this->_db); $this->logError(); return false; } else { $this->_rows = mysql_insert_id($this->_db); return $this->_rows; } } /** * 获取上一次查询影响的记录数量 * @return int 影响的记录数量 */ public function getRows(){ return $this->_rows; } /** * 获取上一次insert后生成的自增id * @return int 自增ID */ public function getInsertId() { return mysql_insert_id($this->_db); } /** * 获取上一次查询的sql * @return string sql */ public function getLastSql(){ return $this->_lastSql; } /** * 获取上一次查询的错误信息 * @return string 错误信息 */ public function getError(){ return $this->_error; } /** * 记录sql到文件 */ private function logSql(){ Log::sql($this->_lastSql); } /** * 记录错误日志到文件 */ private function logError(){ $str = '[SQL ERR]'.$this->_error.' SQL:'.$this->_lastSql; Log::warn($str); } } /** * 日志类 * 使用方法:Log::fatal('error msg'); * 保存路径为 App/Log,按天存放 * fatal和warning会记录在.log.wf文件中 */ class Log{ /** * 打日志,支持SAE环境 * @param string $msg 日志内容 * @param string $level 日志等级 * @param bool $wf 是否为错误日志 */ public static function write($msg, $level='DEBUG', $wf=false,$file){ if(function_exists('sae_debug')){ //如果是SAE,则使用sae_debug函数打日志 $msg = "[{$level}]".$msg; sae_set_display_errors(false); sae_debug(trim($msg)); sae_set_display_errors(true); }else{ $msg = date('[ Y-m-d H:i:s ]')."[{$level}]".$msg."\r\n"; $logPath = C('APP_FULL_PATH').'/Log/'.date('Ymd').$file.'.log'; if($wf){ $logPath .= '.wf'; } file_put_contents($logPath, $msg, FILE_APPEND); } } /** * 打印fatal日志 * @param string $msg 日志信息 */ public static function fatal($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'FATAL', true); } /** * 打印warning日志 * @param string $msg 日志信息 */ public static function warn($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'WARN', true); } /** * 打印notice日志 * @param string $msg 日志信息 */ public static function notice($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'NOTICE'); } /** * 打印gethis日志 * @param string $msg 日志信息 */ public static function gethis($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'GETHIS'); } /** * 打印gethis日志 * @param string $msg 日志信息 */ public static function posthis($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'POSTHIS'); } /** * 打印gethis日志 * @param string $msg 日志信息 */ public static function soaphis($msg,$file){ //$msg = iconv("utf-8","GB2312//IGNORE",$msg); //$msg = mb_convert_encoding($msg, "GB2312","UTF-8"); $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'SOAPHIS',false,$file); } /** * 打印xmlerr日志 * @param string $msg 日志信息 */ public static function xmlerr($msg){ self::write($msg, 'XMLERR'); } /** * 打印xmltc日志 * @param string $msg 日志信息 */ public static function xmltc($msg){ self::write($msg, 'XMLTC'); } /** * 打印syncdberr日志 * @param string $msg 日志信息 */ public static function syncdberr($msg){ self::write($msg, 'SYNCDBERR'); } /** * 打印cur_err日志 * @param string $msg 日志信息 */ public static function cur_err($msg){ self::write($msg, 'CURERR'); } /** * 打印返回前台JSON日志 * @param string $msg 日志信息 */ public static function json($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'JSON'); } /** * 打印debug日志 * @param string $msg 日志信息 */ public static function debug($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'DEBUG'); } /** * 打印sql日志 * @param string $msg 日志信息 */ public static function sql($msg){ $msg = iconv("utf-8","gb2312",$msg); self::write($msg, 'SQL'); } /** * 打印getpost日志 * @param string $msg 日志信息 */ public static function getpost($msg){ self::write($msg, 'GETPOST'); } } /** * ExtException类,记录额外的异常信息 */ class ExtException extends Exception{ /** * @var array */ protected $extra; /** * @param string $message * @param array $extra * @param int $code * @param null $previous */ public function __construct($message = "", $extra = array(), $code = 0, $previous = null){ $this->extra = $extra; parent::__construct($message, $code, $previous); } /** * 获取额外的异常信息 * @return array */ public function getExtra(){ return $this->extra; } }