params = self::params(); return self::$instance; } /** * 获取ip地址 * * @return string ip地址:如 59.151.9.90 */ public function ip() { if (isset($_SERVER)) { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $realip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { $realip = $_SERVER['HTTP_CLIENT_IP']; } else { $realip = $_SERVER['REMOTE_ADDR']; } } else { if (getenv("HTTP_X_FORWARDED_FOR")) { $realip = getenv("HTTP_X_FORWARDED_FOR"); } elseif (getenv("HTTP_CLIENT_IP")) { $realip = getenv("HTTP_CLIENT_IP"); } else { $realip = getenv("REMOTE_ADDR"); } } $realip = preg_replace('#,.*$#', '', $realip); $realip = preg_replace('#[^\d\.]+#', '', $realip);// 从支付平台发现,有时会获取到这种ip,%20%2058.255.8.39,说明前面有有空格,处理一下 return $realip; } /** * 从 REQUEST_URI 字段获取请求路径 * 如:/article/index.php?id=857&action=show 会被处理成:article/index.php * * @param string | null $request_uri * @return string */ public function path($request_uri = null) { if (is_null($request_uri)) { $request_uri = $_SERVER['REQUEST_URI']; } if (($iPos = strpos($request_uri, '?')) !== false) { $request_uri = substr($request_uri, 0, $iPos); } $request_uri = str_replace(' ', '/', trim(str_replace('/', ' ', $request_uri))); $request_uri = urldecode($request_uri); return $request_uri; } /** * * 获取当前请求的url * @return String 完整的url,如:http://www.kimiss.com/test.php?c=Default */ public function url() { $port = $_SERVER['SERVER_PORT'] == '80' ? '' : ":{$_SERVER['SERVER_PORT']}"; $url = "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; return $url; } /** * * 获取分类url的模版 * @param string $pageKey 请求里表示分页的参数 * @return string */ public function pageUrlTpl($pageKey = 'page') { $routeParams = Route::getInstance()->getsRouteParams(); if ($routeParams) { $routeParams[$pageKey] = '{page}'; $path = Route::getInstance()->reverse($routeParams); $url = "http://{$_SERVER['HTTP_HOST']}/" . $path; return String::jointUrl($url, array_diff_key($_GET, $routeParams)); } else { $request_params = $_GET; $request_params[$pageKey] = '{page}'; $url = "http://{$_SERVER['HTTP_HOST']}/" . $this->path(); return String::jointUrl($url, $request_params); } } /** * * 获取带请求协议的域名url,如:https://kimiss.com * @return string */ static public function schemeDomain() { $protocol_str = $_SERVER['SERVER_PROTOCOL']; if (!$protocol_str) { return ''; } list($protocol,) = explode('/', $protocol_str); return strtolower($protocol) . "://{$_SERVER['HTTP_HOST']}"; } /** * * 获取当前请求的顶级域名 * @param string $host * @return string */ public function rootDomain($host = null) { if (is_null($host)) $host = $_SERVER['HTTP_HOST']; if (empty($host)) { return ''; } $host = strtolower($host); # 是个ip直访的url if (filter_var($host, FILTER_VALIDATE_IP)) { return ''; } # 不带.,可能是绑host的域名 if (strpos($host, '.') === FALSE) { return $host; } $domain_suffs = array( '.com', '.cn', '.net', '.com.cn', '.net.cn', '.org', '.me', '.biz', '.name', '.org.cn', '.gov.cn', '.info', '.so', '.tel', '.mobi', '.asia', '.cc', '.tv', '.co', ); foreach ($domain_suffs as $suff) { $tmp_stuff_pos = strrpos($host, $suff); if ($tmp_stuff_pos === false) { continue; } $tmp_rootdomain_pos = strrpos($host, '.', 0-strlen(substr($host, $tmp_stuff_pos))-1); if ($tmp_rootdomain_pos === false) { return $host; } return substr($host, $tmp_rootdomain_pos+1); } } /** * 获取请求url中的查询字符串 * * @return string */ static public function queryString() { return $_SERVER['QUERY_STRING']; } /** * * 获取请求的referer * @return string */ static public function referer() { return $_SERVER['HTTP_REFERER']; } /** * 是否POST请求 * * @return boolean */ static public function isPost() { return strtoupper($_SERVER['REQUEST_METHOD']) == 'POST'; } /** * 是否GET请求 * * @return boolean */ static public function isGet() { return strtoupper($_SERVER['REQUEST_METHOD']) == 'GET'; } /** * 该请求是否由 蜘蛛 发出 * * @return boolean */ public function isSpider() { if (self::isCLI()) { return false; } if (!isset($_SERVER['HTTP_USER_AGENT'])) { return false; } $bots = array( 'Googebot', 'Baiduspider', 'Yahoo! Slurp', 'Sosospider', 'Sogou', 'Sogou-Test-Spider', 'Sogou head spider', 'YoudaoBot', 'qihoobot', 'iaskspider', 'LeapTag', 'MSIECrawler' ); foreach ($bots as $bot) { if (strpos($_SERVER['HTTP_USER_AGENT'], $bot) !== false) { return true; } } if (stristr($_SERVER['HTTP_USER_AGENT'], 'Windows') !== false) { return false; } $bots = array( 'spider', 'bit', 'crawler', 'slurp', 'subscriber', 'http', 'rssreader', 'blogline', 'greatnews', 'feed', 'alexa', 'php' ); foreach ($bots as $bot) { if (stristr($_SERVER['HTTP_USER_AGENT'], $bot) !== false) { return true; } } return false; } /** * 该请求是否从相同的主机过来,即来源页是否与当前页处于相同域下 * * @return boolean */ public function isFromSameHost() { if (!isset($_SERVER['HTTP_REFERER'])) { return true; } $url_parts = parse_url($_SERVER['HTTP_REFERER']); $host = $url_parts['host']; if ($_SERVER['HTTP_HOST'] == $host) { return true; } return false; } /** * 从请求的 $_GET 变量里获取 变量的整数值,如果不存在该变量或不为整数,则返回 $default 值 * @param string $varName 变量名 * @param int $default 默认值 * @return int */ public function varGetInt($varName, $default = 0) { if (!isset($_GET[$varName])) { return $default; } if (!Verify::unsignedInt($_GET[$varName])) { return $default; } return $_GET[$varName]; } /** * 从请求的 $_POST 变量里获取 变量的整数值,如果不存在该变量或不为整数,则返回 $default 值 * @param string $varName 变量名 * @param int $default 默认值 * @return int */ public function varPostInt($varName, $default = 0) { if (!isset($_POST[$varName])) { return $default; } if (!Verify::unsignedInt($_POST[$varName])) { return $default; } return $_POST[$varName]; } /** * 从请求的 $_POST 变量里获取 变量的整数值,如果不存在该变量或不为整数,则返回 $default 值 * @param string $varName 变量名 * @param int $default 默认值 * @return int */ public function varRequestInt($varName, $default = 0) { if (!isset($_REQUEST[$varName])) { return $default; } if (!Verify::unsignedInt($_REQUEST[$varName])) { return $default; } return $_REQUEST[$varName]; } /** * 获取请求的参数集。 * 支持http访问的参数 以及 命令行下访问的参数 * demo1:php test.php -p3 -t=abc --opt=valopt --opt2 valopt2 * demo2 http://test.kimiss.com/index.php?c=xxx&a=ddd * @return array */ public function params() { if (self::isCLI()) { return self::cliParams(); } else { return $_REQUEST; } } /** * * 获取命令行下传递进来的参数 * 只支持以 - 或 -- 开头的参数 * demo:php test.php -p3 -t=abc --opt=valopt --opt2 valopt2 * @return array */ private function cliParams() { $result = array(); $params = $GLOBALS['argv']; array_shift($params); reset($params); do { $tmpEachResult = each($params); if (!$tmpEachResult) { break; } list($tmp, $p) = $tmpEachResult; if ($p{0} == '-') { $pname = substr($p, 1); $value = false; if ($pname{0} == '-') {// 长选项 (--) $pname = substr($pname, 1); if (strpos($p, '=') !== false) { // value specified inline (--=) list($pname, $value) = explode('=', substr($p, 2), 2); } } else {// 短选项 if (strpos($p, '=') !== false) { // value specified inline (-=) list($pname, $value) = explode('=', substr($p, 1), 2); } else if (strlen($p) > 1) { $pname = substr($p, 1, 1); $value = substr($p, 2); } } # 如果上面没有取到值,并且下一个不是以-开头的,则下一个值为当前参数的值 $nextparm = current($params); if ($value === false && $nextparm !== false && $nextparm{0} != '-' ) { list($tmp, $value) = each($params); } $result[$pname] = (string) $value;// 将 false转为空串,以便与http访问时对参数的处理一致 } else { # 不是以-指定开始的参数,一律丢弃 //$result[] = $p; } } while (true); return $result; } /** * * 获取 $_GET 里指定key $name 的值,同时可以指定 $filters 过滤方法处理值 * * 用法: * 1、对值不做任何处理:Request::getInstance()->get('content', null); * 2、对值做html转义处理:Request::getInstance()->get('name'); * * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * $filters支持以下格式: * 1) 标量类型,如: * Filter::HTMLSPECIALCHARS; * 2) 多个filter,如: * array( * Filter::HTMLSPECIALCHARS, * Filter::STRIP_TAGS, * ); * 3) 多个filter,并且某些filter另外指定参数,如: * array( * array( * Filter::HTMLSPECIALCHARS => ENT_QUOTES, * ), * array( * Filter::STRIP_TAGS => "", * ), * Filter::STRIP_SELECTED_TAGS, * ); * * @throws ParamsException "无效的过滤方法filter" * @return string */ public function get($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { if (!isset($_GET[$name])) { return false; } $val = $_GET[$name]; if (is_null($filters)) { return $val; } if (!is_array($filters)) { $filters = array($filters); } return self::filter($val, $filters); } /** * * get的别名方法 * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string */ public function g($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { return self::get($name, $filters); } /** * * 获取 $_POST 里指定key $name 的值,同时可以指定 $filters 过滤方法处理值 * * 用法: * 1、对值不做任何处理:Request::getInstance()->post('content', null); * 2、对值做html转义处理:Request::getInstance()->post('name'); * * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string */ public function post($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { if (!isset($_POST[$name])) { return false; } $val = $_POST[$name]; if (is_null($filters)) { return $val; } if (!is_array($filters)) { $filters = array($filters); } return self::filter($val, $filters); } /** * * post的别名方法 * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string */ public function p($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { return self::post($name, $filters); } /** * * 获取 $_REQUEST 里指定key $name 的值,同时可以指定 $filters 过滤方法处理值 * !! 因为与类同名的方法会被认为是构造函数,所以这个方法名加个小字符 !! * * 用法: * 1、对值不做任何处理:Request::getInstance()->requestV('content', null); * 2、对值做html转义处理:Request::getInstance()->requestV('name'); * * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string */ public function requestV($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { if (!isset($_REQUEST[$name])) { return false; } $val = $_REQUEST[$name]; if (is_null($filters)) { return $val; } if (!is_array($filters)) { $filters = array($filters); } return self::filter($val, $filters); } /** * * requestV的别名方法 * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string */ public function r($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { return self::requestV($name, $filters); } /** * * 获取 $_COOKIE 里指定key $name 的值,同时可以指定 $filters 过滤方法处理值 * * 用法: * 1、对值不做任何处理:Request::getInstance()->cookie('content', null); * 2、对值做html转义处理:Request::getInstance()->cookie('name'); * * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string | false */ public function cookie($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { if (!isset($_COOKIE[$name])) { return false; } $val = $_COOKIE[$name]; if (is_null($filters)) { return $val; } if (!is_array($filters)) { $filters = array($filters); } return self::filter($val, $filters); } /** * * cookie的别名方法 * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string | false */ public function c($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { return self::cookie($name, $filters); } /** * * 获取当前请求参数里指定key $name 的值,同时可以指定 $filters 过滤方法处理值 * * 用法: * 1、对值不做任何处理:Request::getInstance()->param('content', null); * 2、对值做html转义处理:Request::getInstance()->param('name'); * * @param string $name * @param mixed $filters 默认使用html转义过滤。当值为null里,对值不做任何过滤。 * @throws ParamsException "无效的过滤方法filter" * @return string | false */ public function param($name, $filters = array(Filter::HTMLSPECIALCHARS, Filter::TRIM)) { if (!isset($this->params[$name])) { return false; } $val = $this->params[$name]; if (is_null($filters)) { return $val; } if (!is_array($filters)) { $filters = array($filters); } return self::filter($val, $filters); } /** * * 使用用户指定的 过滤方法,过滤值 $val * @param string $val * @param array $filters 过滤方法相关信息 * @throws ParamsException "无效的过滤方法filter" * @return string */ private function filter($val, array $filters) { foreach ($filters as $filter) { $params = array($val); if (is_array($filter)) { list($filter_name, $filter_options) = each($filter); } else { $filter_name = $filter; $filter_options = null; } if (!Filter::isValid($filter_name)) { throw new ParamsException("无效的过滤方法filter"); } $val = call_user_func(array('KIF\String\Filter', $filter_name), $val, $filter_options); } return $val; } /** * 是否处于命令行下 * @return Boolean */ static public function isCLI() { if (php_sapi_name() == "cli"//PHP 4 >= 4.0.1, PHP 5 support php_sapi_name function || empty($_SERVER['PHP_SELF'])//If PHP is running as a command-line processor this variable contains the script name since PHP 4.3.0. Previously it was not available. ) { return true; } else { return false; } } /** * 是否类unix系统 * @return Boolean */ static public function isUnixLike() { $os = strtolower(PHP_OS); if (in_array($os, array('linux', 'freebsd', 'unix', 'netbsd'))) { return true; } return false; } /** * * 分发请求,调用Controller以及对应的action */ public function dispatch() { $params = $this->params; $controllerName = self::getController($params); if (!class_exists($controllerName)) { throw new Exception("controller: {$controllerName} not exists!"); } $action = self::getAction($params); $controller = new $controllerName(); $controller->setAction($action); $controller->run(); if (method_exists($controller, 'display')) { $controller->display(); } } public function getController() { $c = self::param('c'); $c = trim($c, '_'); $arr_class_path = array_map(function ($tmpV) { return ucfirst($tmpV); }, explode('_', $c)); $c = join('\\', $arr_class_path); $NS = Config::getInstance()->get('Namespace'); $controller = "{$NS}\Controller\\{$c}"; return $controller; } public function getAction(array $params = null) { $action = self::param('a'); return $action; } }