/** * 错误输出 * * debug状态下,谁都可以看到错误信息 * developer状态下,只有开发者才能开间错误信息,开发者[指定的ip和帐号] * 其他的不能看到错误信息 * * @access public * @param mixed $errdata 错误信息 * @param string $errpage 错误页面URL * @author songdengtao <http://www.songdengtao.cn> * * @return void */ public static function halt($errdata, $errpage = '') { $e = []; $ip = ''; $developerIps = []; $isDebug = \Pandaphp::get('debug'); $isCli = \Pandaphp::get('isCli'); $isOpen = true; if (false === $isCli) { $ip = \Pandaphp::shell('Ip::getClientIp'); $developerIps = \Pandaphp::shell('Config::get', 'developer_ips'); if (!in_array($ip, $developerIps)) { $isOpen = false; } } if ($isOpen || $isDebug || $isCli) { if (!is_array($errdata)) { $trace = debug_backtrace(); $e['message'] = '<b style="color:#FF9900;">[ pandaphp_error ] :</b><br> ' . $errdata; $e['file'] = $trace[1]['file']; $e['line'] = $trace[1]['line']; ob_start(); debug_print_backtrace(); $e['trace'] = ob_get_clean(); } else { $e = $errdata; } if ($isCli) { $errstr = $e['message']; if (\Pandaphp::get('isWin')) { $errstr = iconv('UTF-8', 'gbk', $e['message']); } $errstr .= PHP_EOL; $errstr .= 'FILE:' . $e['file'] . PHP_EOL; $errstr .= 'LILE:' . $e['line'] . PHP_EOL; $errstr .= $e['trace']; die($errstr); } } else { if (in_array($ip, $developerIps)) { $message = $errdata['message']; } else { $message = is_array($errdata) ? $errdata['message'] : $errdata; $errorMsg = \Pandaphp::shell('Config::get', 'error_message'); $message = $isDebug ? $message : $errorMsg; } $e['message'] = $message; } if (empty($errpage)) { $errpage = \Pandaphp::shell('Config::get', 'error_page'); $errpage = \Pandaphp::get('webroot') . $errpage; } if (\Pandaphp::shell('File::isExist', $errpage, true)) { include $errpage; exit; } else { static::defaultErrorPrint($e, $isDebug); } die($e); }
private static function _isRuntimesExistAndWritable() { $runtimesPath = \Pandaphp::get('runtimePath'); $isExist = \Pandaphp::shell('Dir::isExist', $runtimesPath); $isWriteable = \Pandaphp::shell('Dir::isWritable', $runtimesPath); return $isExist && $isWriteable; }
public function __construct() { parent::__construct(); $ds = '/'; $module = MODULE_NAME; $leftDelimiter = \Pandaphp::shell('Config::get', 'template_smarty_left_delimiter'); $this->left_delimiter = $leftDelimiter; $rightDelimiter = \Pandaphp::shell('Config::get', 'template_smarty_right_delimiter'); $this->right_delimiter = $rightDelimiter; // 设置模板文件目录 $viewDirname = \Pandaphp::shell('Config::get', 'dirname_view'); $theme = \Pandaphp::shell('Config::get', 'template_theme'); $theme = $theme ? $theme . $ds : ''; $templateDir = \Pandaphp::get('appPath') . $module . $ds . $viewDirname . $ds . $theme; $this->setTemplateDir($templateDir); // 设置编译后的模板文件目录] $runtimeDir = \Pandaphp::get('runtimePath'); $compileDir = $runtimeDir . $module . $ds . 'template_complie' . $ds; $this->setCompileDir($compileDir); // 设置缓存的模板文件目录 $cacheDir = $runtimeDir . $module . $ds . 'template_cache' . $ds; $this->setCacheDir($cacheDir); $isTemplateCache = \Pandaphp::shell('Config::get', 'template_cache_on'); $this->setCaching($isTemplateCache); $templateCacheLifetime = \Pandaphp::shell('Config::get', 'template_cache_lifetime'); $this->setCacheLifetime($templateCacheLifetime); }
/** * 获取客户端IP地址, * 如果开发者的开发环境ip和服务器在同一个内网内,则获取的是局域网内的ip地址 * @access public * @author songdengtao <http://www.songdengtao.cn/> * @return string */ public static function getClientIp() { if (false === \Pandaphp::get('isCli')) { $client = ''; if (isset($_SERVER['HTTP_CLIENT_IP'])) { $client = $_SERVER['HTTP_CLIENT_IP']; } $forward = ''; if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $forward = $_SERVER['HTTP_X_FORWARDED_FOR']; } $remote = $_SERVER['REMOTE_ADDR']; if (filter_var($client, FILTER_VALIDATE_IP)) { $ip = $client; } elseif (filter_var($forward, FILTER_VALIDATE_IP)) { $ip = $forward; } else { $ip = $remote; } return $ip; } else { if (isset($_SERVER['SSH_CLIENT'])) { return strstr($_SERVER['SSH_CLIENT'], ' ', true); } else { return ''; } } }
private static function _getRouterInstance() { if (is_null(static::$_routerInstance)) { $class = 'pandaphp\\router\\'; $class .= \Pandaphp::get('isCli') ? 'CliRouter' : 'CgiRouter'; static::$_routerInstance = new $class(); } return static::$_routerInstance; }
/** * 调用不存在的控制器方法时的响应 * @access public * @param string $name * @param array $arguments * @author songdengtao <http://www.songdengtao.cn/> * @return void */ public function __call($name, $arguments) { if (method_exists($this, '_empty')) { $this->_empty(); } else { // 访问的页面不存在,跳转之404页面 \Pandaphp::shell('Error::halt', '404 Not Found:' . $name); } }
/** * 检查PHP扩展是否已加载 * @access protected * @param string $extensionName php扩展名称 * @author songdengtao <http://www.songdengtao.cn/> * @return void */ protected function checkExtensionLoad($extensionName) { if (!empty($extensionName)) { if (!extension_loaded($extensionName)) { // 系统不支持$extensionName \Pandaphp::shell('Error::halt', '目前系统不支持' . $extensionName . '扩展,请安装相关扩展!'); } } }
/** * 获取WHERE部分的字符串和绑定的数组 * @access public * @param array $whereElement * @author songdengtao <http://www.songdengtao.cn> * @return array ['where' => , 'bind'] */ public function getWhereAndBind(array $whereElement = []) { $ret = []; $bindKey = $this->bindKey($whereElement[0]); $field = $whereElement[0]; $ret['where'] = $field . " LIKE :" . \Pandaphp::shell('Str::bindReplace', $field); $ret['bindKey'] = $whereElement[1][0]; $ret['bindVal'] = $whereElement[1][1]; return $ret; }
public static function set($name = '', $value = '', $expire = 0, $path = '/', $domain = '') { $name = static::_setCookiePrefix($name); $expire = intval($expire) > 0 ? $expire : \Pandaphp::shell('Config::get', 'cookie_expire'); $path = empty($path) ? \Pandaphp::shell('Config::get', 'cookie_path') : $path; $domain = empty($domain) ? \Pandaphp::shell('Config::get', 'cookie_domain') : $domain; $secure = \Pandaphp::shell('Config::get', 'cookie_secure'); $httponly = \Pandaphp::shell('Config::get', 'cookie_httponly'); setcookie($name, $value, $expire, $path, $domain, $secure, $httponly); }
/** * 开启SESSION * @access public * @author songdengtao <http://www.songdengtao.cn> * @return void */ public static function start() { $sessionCookiePath = \Pandaphp::shell('Config::get', 'session_cookie_path'); ini_set('session.cookie_path', $sessionCookiePath); $sessionCookieDomain = \Pandaphp::shell('Config::get', 'session_cookie_domain'); ini_set('session.cookie_domain', $sessionCookieDomain); $sessionCookieExpire = \Pandaphp::shell('Config::get', 'session_cookie_expire'); ini_set('session.cookie_lifetime', $sessionCookieExpire); session_start(); }
/** * 路由调度 * @access public * @author songdengtao <http://www.songdengtao.cn/> * @return void */ public function dispatch() { $pandaUri = $this->getPandaUri(); $data = $this->parsePandaUri($pandaUri); define('MODULE_NAME', $data['module']); define('CONTROLLER_NAME', $data['controller']); define('ACTION_NAME', $data['action']); define('CONTROLLER_NAMESPACE', $this->getCtrlNamespace(MODULE_NAME)); $_GET = $data['_GET']; $_POST = \Pandaphp::shell('Input::post'); $_REQUEST = array_merge($_GET, $_POST); }
private function _getTableName($tableName = '') { if (empty($tableName)) { if (empty($this->tableName)) { $modleClassName = get_class($this); $modleClassName = strrchr($modleClassName, '\\'); $modleClassName = str_replace(['\\', 'Model'], '', $modleClassName); $tableName = \Pandaphp::shell('Str::toUnderline', lcfirst($modleClassName)); } } return $tableName; }
/** * 生成CSS link标签的href * 生成javascript script 标签的src * 生成样式图片image image 标签的src * @access public * @param string $file * @param array $options * @author songdengtao <http://www.songdengtao.cn> * @return string */ public static function create($file = '', array $options = []) { $ret = ''; if (empty($file)) { return $ret; } $cjiHttpDomain = \Pandaphp::shell('Config::get', 'http_domain_cji'); $module = defined('MODULE_NAME') ? MODULE_NAME : ''; if (isset($options['module']) && !empty($options['module'])) { $module = $options['module']; } $theme = \Pandaphp::shell('Config::get', 'template_theme'); if (isset($options['theme']) && !empty($options['theme'])) { $theme = $options['theme']; } $isComplete = false; if (isset($options['isComplete'])) { $isComplete = $options['isComplete']; } $cjiHttpDomain = rtrim($cjiHttpDomain, '/'); if (!$isComplete) { $theme = !empty($theme) ? '/' . $theme : ''; $ret = $cjiHttpDomain . '/' . $module . $theme; $fileSuffix = substr($file, strrpos($file, '.') + 1); switch ($fileSuffix) { case 'css': $ret .= '/css/'; break; case 'js': $ret .= '/js/'; break; case 'jpg': case 'jpeg': case 'png': case 'gif': case 'ico': case 'bmp': $ret .= '/images/'; break; default: break; } $ret .= ltrim($file, '/'); } else { $ret = $cjiHttpDomain . '/' . ltrim($file, '/'); } return $ret; }
/** * 缓存驱动初始化 * @param array $options 缓存参数数组 * @author songdengtao <http://www.songdengtao.cn/> * @return $this */ public function connect(array $options = []) { $this->options = \Pandaphp::shell('Config::get', 'cache_memcache'); if (!empty($options)) { $this->options = array_merge($this->options, $options); } $this->handler = new \Memcache(); // 支持集群 $hosts = explode(',', $this->options['host']); $ports = explode(',', $this->options['port']); foreach ((array) $hosts as $i => $host) { $port = isset($ports[$i]) ? $ports[$i] : $ports[0]; if (false === $this->options['timeout']) { $this->handler->addServer($host, $port, $this->options['ispconnect'], 1); } else { $this->handler->addServer($host, $port, $this->options['ispconnect'], 1, $this->options['timeout']); } } }
/** * 解析请求的URI,获得PANDAURI * @access public * @author songdengtao <http://www.songdengtao.cn/> * @return string */ public function getPandaUri() { $queryVar = \Pandaphp::get('httpQueryStr'); $inputData = \Pandaphp::shell('Input::get'); $queryStr = ''; if (isset($inputData[$queryVar])) { $mdlCtrlActStr = $inputData[$queryVar]; if (\Pandaphp::shell('Str::isEnd', $mdlCtrlActStr, $this->urlHtmlSuffix)) { $queryStr .= str_replace($this->urlHtmlSuffix, '', $mdlCtrlActStr); } else { $queryStr .= $mdlCtrlActStr; } $queryStr = str_replace('/index.php', '', $queryStr) . '/'; } $subDomain = \Pandaphp::shell('Http::getSubDomain'); $isDomainDeploy = $this->urlDomainDeployOn && (isset($this->urlDomainDeployMapping[$subDomain]) || empty($subDomain)); if ($isDomainDeploy) { if (empty($subDomain)) { $subDomain = 'www'; } $runtimeModule = $this->urlDomainDeployMapping[$subDomain]; } else { if (isset($inputData[$queryVar])) { $runtimeModule = substr($queryStr, 1, strpos(trim($queryStr, '/'), '/')); } else { $runtimeModule = $this->defaultModule; } } \Pandaphp::set('runtimeModule', $runtimeModule); $this->defaultController = \Pandaphp::shell('Config::get', 'default_controller'); $this->defaultAction = \Pandaphp::shell('Config::get', 'default_action'); if (isset($inputData[$queryVar])) { $queryStr = '/' . $runtimeModule . $queryStr; unset($inputData[$queryVar]); } else { $queryStr .= '/' . $runtimeModule . '/' . $this->defaultController . '/' . $this->defaultAction . '/'; } foreach ($inputData as $key => $val) { $queryStr .= $key . '/' . $val . '/'; } return $queryStr; }
private static function _GetCacheHanlder($type = '', array $config = []) { if (empty(!$type)) { $types = \Pandaphp::shell('Config::get', 'cache_types'); if (!in_array($type, $types)) { \Pandaphp::shell('Error::halt', '不支持缓存或者cache_types未配置'); } } else { $type = \Pandaphp::shell('Config::get', 'cache_type'); } if (empty($config)) { $config = \Pandaphp::shell('Config::get', 'cache_' . $type); } $handler = null; $class = '\\pandaphp\\cache\\' . \Pandaphp::shell('Str::toBigHump', $type) . 'Cache'; if (class_exists($class)) { $handler = new $class($config); } else { \Pandaphp::shell('Error::halt', '缓存驱动' . $class . '不存在'); } return $handler; }
/** * 缓存驱动初始化 * @param array $options 缓存参数数组 * @author songdengtao <http://www.songdengtao.cn/> * @return $this */ public function connect(array $options = []) { $this->options = \Pandaphp::shell('Config::get', 'cache_redis'); if (!empty($options)) { $this->options = array_merge($this->options, $options); } $this->handler = new \Redis(); $func = $this->options['ispconnect'] ? 'pconnect' : 'connect'; if (false === $this->options['timeout']) { $res = $this->handler->{$func}($this->options['host'], $this->options['port']); } else { $res = $this->handler->{$func}($this->options['host'], $this->options['port'], $this->options['timeout']); } if (!$res) { \Pandaphp::shell('Error::halt', 'redis未启动'); } if (!empty($this->options['passwd'])) { $authRes = $this->handler->auth($this->options['passwd']); if (!$authRes) { \Pandaphp::shell('Error::halt', 'redis认证失败'); } } }
/** * 设置WHERE表达式对象 * @access private * @author songdengtao <http://www.songdengtao.cn> * @return void */ private function _setWhereOperator() { if (count($this->_whereElement) >= 2 && isset($this->_whereElement[1][0])) { $operatorType = strtolower($this->_whereElement[1][0]); $normalOperator = ['eq' => '=', 'neq' => '<>', 'lt' => '<', 'elt' => '<=', 'gt' => '>', 'egt' => '>=']; if (in_array($operatorType, ['eq', 'neq', 'lt', 'elt', 'gt', 'egt'])) { $this->_whereOperator = new Normal($normalOperator[$operatorType]); } else { $className = ucwords($operatorType); if ($operatorType === 'and' || $operatorType === 'or') { $className = 'AndOr'; } $class = 'pandaphp\\db\\mysql\\' . $className; if (class_exists($class)) { $this->_whereOperator = new $class(); } else { \Pandaphp::shell('Error::halt', ' class is not exist!'); } } } else { #todo _setWhereOperator } }
/** * 404页面 * @access public * @param string $msg 展示的信息 * @param string $_404PageUrl 404页面URL * @author songdengtao <http://www.songdengtao.cn> * @return void */ public static function _404($msg = '', $_404PageUrl = '') { if (empty($_404PageUrl)) { $_404PageUrl = \Pandaphp::shell('Config::get', '404'); $_404PageUrl = \Pandaphp::get('webroot') . $_404PageUrl; } if (\Pandaphp::shell('File::isExist', $_404PageUrl)) { require_once $_404PageUrl; } else { \Pandaphp::shell('Error::halt', $msg); } #todo 读秒跳转 exit; }
/** * 数据库连接 * @access private * @param array $config 数据库配置 * @author songdengtao <http://www.songdengtao.cn> * @return object 数据库PDO连接对象 */ private function _connect(array $config = []) { $this->hostname = $config['hostname']; $this->port = $config['port']; $this->charset = $config['charset']; $this->username = $config['username']; $this->password = $config['password']; $this->dbname = $config['name']; $this->tablePrefix = $config['table_prefix']; if (isset($type) && !empty($type)) { $type = strtolower($type); if (in_array($type, $this->allowedTypes)) { $this->type = $type; } else { if ($type === 'mysqli') { $this->type = 'mysql'; } } } $handler = null; try { $dsn = $this->type . ':host=' . $this->hostname . ';port=' . $this->port . ';dbname=' . $this->dbname; $handler = new \PDO($dsn, $this->username, $this->password); } catch (\PDOException $e) { \Pandaphp::shell('Error::halt', 'Database connection failed:' . $e->getMessage()); } if (!is_null($handler)) { $handler->query('set names ' . $this->charset); } return $handler; }
/** * 构建join字符串 * @access protected * @author songdengtao <http://www.songdengtao.cn> * @return string */ protected function getJoinStr() { $ret = ''; if (!empty($this->joinArr)) { $ret = implode(' ', $this->joinArr); } return \Pandaphp::shell('Str::lblank', $ret); }
protected function bindKey($key = '') { return \Pandaphp::shell('Str::bindReplace', ':' . $key); }
/** * 获取module,controller, action * @access public * @param string $pandaUri * @author songdengtao <http://www.songdengtao.cn/> * @return array */ public function getMdlCtrlActGET($pandaUri = '') { $ret = ['module' => \Pandaphp::get('runtimeModule'), 'controller' => $this->defaultController, 'action' => $this->defaultAction, '_GET' => []]; if (!empty($pandaUri)) { $pandaUriArr = explode('/', trim($pandaUri, '/')); array_shift($pandaUriArr); if (count($pandaUriArr) >= 1) { $ret['controller'] = ucwords(array_shift($pandaUriArr)); } if (count($pandaUriArr) >= 1) { $ret['action'] = array_shift($pandaUriArr); } $ret['_GET'] = $pandaUriArr; } else { \Pandaphp::shell('Error::halt', '请检查默认的模块,控制器,操作是否空或不存在!'); } if (!empty($ret['_GET'])) { $queryArr = $ret['_GET']; $keyArr = []; $valArr = []; foreach ($queryArr as $key => $val) { if ($key % 2 === 0) { $keyArr[] = $val; } else { $valArr[] = $val; } } $GET = []; foreach ($keyArr as $k => $v) { if (isset($valArr[$k]) && false === is_null($valArr[$k])) { $GET[$v] = $valArr[$k]; } } $ret['_GET'] = $GET; } $ret['_GET'] = (array) $ret['_GET']; return \Pandaphp::shell('Filter::inputFilter', $ret); }
<?php /** * 项目入口文件 */ require_once dirname(__DIR__) . '/framework/Pandaphp.php'; // 生产环节请将debug 设置为false Pandaphp::set('debug', true); // 根据环境,自定义读取配置文件 Pandaphp::set('status', 'development'); Pandaphp::run();
private function _createNavAUrl($urlParam = [], $suffix = '', $module = '') { $url = ''; $module = empty($module) ? MODULE_NAME : $module; if (is_string($urlParam)) { if (\Pandaphp::shell('Str::isEnd', $urlParam, '/')) { $urlParam = rtrim($urlParam, '/'); } $urlParam = (array) $urlParam; } $pageNumArr = [$this->_pageNumberVarName => $this->_pageNumberPlaceholder]; $urlParam = array_merge($urlParam, $pageNumArr); $url = \Pandaphp::shell('Uri::create', $urlParam, $suffix, $module); return $url; }
/** * 获取配置 * @access private * @param string $key 配置键 * @param array $configFilePaths 配置文件路径数组 * @author songdengtao <http://www.songdengtao.cn/> * @return mixed */ protected function _GetConfigValue($key = '', array $configFilePaths = []) { $ret = null; if (!empty($key)) { foreach ($configFilePaths as $k => $v) { $GLOBALSKEY = md5($v); if (array_key_exists($GLOBALSKEY, $GLOBALS)) { $GLOBALSVAL = json_decode($GLOBALS[$GLOBALSKEY], true); } else { $data = \Pandaphp::shell('File::returnInclude', $v); if ($data) { $GLOBALSVAL = $data; $GLOBALS[$GLOBALSKEY] = json_encode($data); } else { continue; } } if (array_key_exists($key, $GLOBALSVAL)) { $ret = $GLOBALSVAL[$key]; break; } } } return $ret; }
/** * 上传单张文件 * @access public * @param array $imageFile $_FILES[filename] * @author songdengtao <http://www.songdengtao.cn> * @return array */ public function uploadOne(array $imageFile = []) { if (empty($imageFile)) { return ['stat' => 4, 'msg' => '请选择文件']; } $checkFileErrorRes = $this->_CheckFileError($imageFile['error']); if ($checkFileErrorRes['stat'] !== 0) { return $checkFileErrorRes; } //原文件名 $fileName = strip_tags($imageFile['name']); //服务器上临时文件名 $tempName = $imageFile['tmp_name']; //文件大小 $fileSize = $imageFile['size']; //检查文件名 if (!$fileName) { return ['stat' => 4, 'msg' => '请选择文件']; } // 检查上传的目录是否存在 if (!@is_dir($this->savePath)) { return ['stat' => 9, 'msg' => '上传目录不存在']; } //检查目录写权限 if (!@is_writable($this->savePath)) { return ['stat' => 10, 'msg' => '上传目录没有写权限']; } //检查是否已上传 if (!@is_uploaded_file($tempName)) { return ['stat' => 8, 'msg' => '文件上传失败']; } //检查文件大小 if ($this->maxSize !== 0 && $fileSize > $this->maxSize) { return ['stat' => 11, 'msg' => '上传文件大小超过系统限制']; } //获得文件扩展名 $tempArr = explode(".", $fileName); $fileExt = strtolower(trim(array_pop($tempArr))); //检查扩展名 if (!in_array($fileExt, $this->exts)) { return ['stat' => 12, 'msg' => '上传文件扩展名是不允许的扩展名:' . $fileExt]; } // 检查mime $mime = \Pandaphp::shell('Image::getFileMimeType', $tempName); if (!in_array($mime, $this->mimes)) { return ['stat' => 13, 'msg' => '文件的MIME是不允许的MIME:' . $mime]; } //创建文件夹 if ($this->autoSub) { // 子目录保存 $subDirName = date('Ymd'); if (function_exists($this->nameSub[0])) { $subDirName = $this->nameSub[0]($this->nameSub[1]); } $dirpath = $this->savePath . $subDirName . '/'; } else { $dirpath = $this->savePath; } if (!\Pandaphp::shell('Dir::mkdir', $dirpath, true)) { return ['stat' => 14, 'msg' => '创建文件保存目录和子目录失败,请检查权限或者手动创建']; } // 创建新的文件 if ($this->saveExt) { $fileExt = $this->saveExt; } $newFileName = date("YmdHis") . '_' . rand(10000, 99999); if (function_exists($this->saveName[0])) { $newFileName = $this->saveName[0]($this->saveName[1]); } $newFile = $newFileName . '.' . $fileExt; // 如果重名 if (file_exists($newFile) && !$this->overwrite) { $newFile = $newFileName . '_' . rand(10000, 99999) . $fileExt; } //移动文件 $newFilePath = $dirpath . $newFile; if (move_uploaded_file($tempName, $newFilePath) === false) { return ['stat' => 8, 'msg' => '文件上传失败']; } @chmod($newFilePath, 0644); return ['stat' => 0, 'msg' => '文件上传成功', 'data' => ['name' => $newFileName, 'ext' => $fileExt, 'size' => $fileSize, 'path' => $newFilePath, 'src' => str_replace(\Pandaphp::get('webroot'), '/', $newFilePath)]]; }
private function _getUrlHost($module = null) { if (is_null($module) || !is_string($module) || empty($module)) { $module = MODULE_NAME; } $domain = \Pandaphp::shell('Http::getDomain'); $domainSuffix = \Pandaphp::shell('Http::getDomainSuffix'); $urlHost = $domain . $domainSuffix . '/' . $module . '/'; if ($this->urlDomainDeployOn) { $reDomainDeployMapping = array_flip($this->urlDomainDeployMapping); if (isset($reDomainDeployMapping[$module])) { $urlHost = $reDomainDeployMapping[$module] . '.' . $domain . $domainSuffix . '/'; } } return $urlHost; }