重新启程:TP5拿个Request类来加入核心过滤数据
2017-03-13 本文已影响0人
Godtoy
使用方法:
<code>
$state = $this->request->request("state", 0, "intval");
</code>
<?php
class lib_request
{
protected $method;
/**
* @var string 域名(含协议和端口)
*/
protected $domain;
/**
* @var string URL地址
*/
protected $url;
/**
* @var string 基础URL
*/
protected $baseUrl;
/**
* @var string 当前执行的文件
*/
protected $baseFile;
/**
* @var string 访问的ROOT地址
*/
protected $root;
/**
* @var string pathinfo
*/
protected $pathinfo;
/**
* @var string pathinfo(不含后缀)
*/
protected $path;
/**
* @var array 当前路由信息
*/
protected $routeInfo = [];
/**
* @var array 请求参数
*/
protected $param = [];
protected $get = [];
protected $post = [];
protected $request = [];
protected $route = [];
protected $put;
protected $session = [];
protected $file = [];
protected $cookie = [];
protected $server = [];
protected $header = [];
/**
* @var array 资源类型
*/
protected $mimeType = [
'xml' => 'application/xml,text/xml,application/x-xml',
'json' => 'application/json,text/x-json,application/jsonrequest,text/json',
'js' => 'text/javascript,application/javascript,application/x-javascript',
'css' => 'text/css',
'rss' => 'application/rss+xml',
'yaml' => 'application/x-yaml,text/yaml',
'atom' => 'application/atom+xml',
'pdf' => 'application/pdf',
'text' => 'text/plain',
'png' => 'image/png',
'jpg' => 'image/jpg,image/jpeg,image/pjpeg',
'gif' => 'image/gif',
'csv' => 'text/csv',
'html' => 'text/html,application/xhtml+xml,*/*',
];
protected $content;
// 全局过滤规则
protected $filter;
// Hook扩展方法
protected static $hook = [];
// 绑定的属性
protected $bind = [];
// php://input
protected $input;
// 请求缓存
protected $cache;
// 缓存是否检查
protected $isCheckCache;
/**
* 架构函数
* @access protected
* @param array $options 参数
*/
public function __construct($options = [])
{
foreach ($options as $name => $item) {
if (property_exists($this, $name)) {
$this->$name = $item;
}
}
if (is_null($this->filter)) {
$this->filter = 'strip_tags,htmlspecialchars';
}
// 保存 php://input
$this->input = file_get_contents('php://input');
}
public function __call($method, $args)
{
if (array_key_exists($method, self::$hook)) {
array_unshift($args, $this);
return call_user_func_array(self::$hook[$method], $args);
} else {
throw new Exception('method not exists:' . __CLASS__ . '->' . $method);
}
}
/**
* 设置或获取当前包含协议的域名
* @access public
* @param string $domain 域名
* @return string
*/
public function domain($domain = null)
{
if (!is_null($domain)) {
$this->domain = $domain;
return $this;
} elseif (!$this->domain) {
$this->domain = $this->scheme() . '://' . $this->host();
}
return $this->domain;
}
/**
* 设置或获取当前完整URL 包括QUERY_STRING
* @access public
* @param string|true $url URL地址 true 带域名获取
* @return string
*/
public function url($url = null)
{
if (!is_null($url) && true !== $url) {
$this->url = $url;
return $this;
} elseif (!$this->url) {
if (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
$this->url = $_SERVER['HTTP_X_REWRITE_URL'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$this->url = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['ORIG_PATH_INFO'])) {
$this->url = $_SERVER['ORIG_PATH_INFO'] . (!empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '');
} else {
$this->url = '';
}
}
return true === $url ? $this->domain() . $this->url : $this->url;
}
/**
* 设置或获取当前URL 不含QUERY_STRING
* @access public
* @param string $url URL地址
* @return string
*/
public function baseUrl($url = null)
{
if (!is_null($url) && true !== $url) {
$this->baseUrl = $url;
return $this;
} elseif (!$this->baseUrl) {
$str = $this->url();
$this->baseUrl = strpos($str, '?') ? strstr($str, '?', true) : $str;
}
return true === $url ? $this->domain() . $this->baseUrl : $this->baseUrl;
}
/**
* 获取当前请求的时间
* @access public
* @param bool $float 是否使用浮点类型
* @return integer|float
*/
public function time($float = false)
{
return $float ? $_SERVER['REQUEST_TIME_FLOAT'] : $_SERVER['REQUEST_TIME'];
}
/**
* 当前请求的资源类型
* @access public
* @return false|string
*/
public function type()
{
$accept = $this->server('HTTP_ACCEPT');
if (empty($accept)) {
return false;
}
foreach ($this->mimeType as $key => $val) {
$array = explode(',', $val);
foreach ($array as $k => $v) {
if (stristr($accept, $v)) {
return $key;
}
}
}
return false;
}
/**
* 设置资源类型
* @access public
* @param string|array $type 资源类型名
* @param string $val 资源类型
* @return void
*/
public function mimeType($type, $val = '')
{
if (is_array($type)) {
$this->mimeType = array_merge($this->mimeType, $type);
} else {
$this->mimeType[$type] = $val;
}
}
/**
* 是否为cli
* @access public
* @return bool
*/
public function isCli()
{
return PHP_SAPI == 'cli';
}
/**
* 是否为cgi
* @access public
* @return bool
*/
public function isCgi()
{
return strpos(PHP_SAPI, 'cgi') === 0;
}
/**
* 设置获取获取路由参数
* @access public
* @param string|array $name 变量名
* @param mixed $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function route($name = '', $default = null, $filter = '')
{
if (is_array($name)) {
$this->param = [];
return $this->route = array_merge($this->route, $name);
}
return $this->input($this->route, $name, $default, $filter);
}
/**
* 设置获取获取GET参数
* @access public
* @param string|array $name 变量名
* @param mixed $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function get($name = '', $default = null, $filter = '')
{
if (empty($this->get)) {
$this->get = $_GET;
}
if (is_array($name)) {
$this->param = [];
return $this->get = array_merge($this->get, $name);
}
return $this->input($this->get, $name, $default, $filter);
}
/**
* 设置获取获取POST参数
* @access public
* @param string $name 变量名
* @param mixed $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function post($name = '', $default = null, $filter = '')
{
if (empty($this->post)) {
$content = $this->input;
if (empty($_POST) && 'application/json' == $this->contentType()) {
$this->post = (array)json_decode($content, true);
} else {
$this->post = $_POST;
}
}
if (is_array($name)) {
$this->param = [];
return $this->post = array_merge($this->post, $name);
}
return $this->input($this->post, $name, $default, $filter);
}
/**
* 设置获取获取PUT参数
* @access public
* @param string|array $name 变量名
* @param mixed $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function put($name = '', $default = null, $filter = '')
{
if (is_null($this->put)) {
$content = $this->input;
if ('application/json' == $this->contentType()) {
$this->put = (array)json_decode($content, true);
} else {
parse_str($content, $this->put);
}
}
if (is_array($name)) {
$this->param = [];
return $this->put = is_null($this->put) ? $name : array_merge($this->put, $name);
}
return $this->input($this->put, $name, $default, $filter);
}
/**
* 设置获取获取DELETE参数
* @access public
* @param string|array $name 变量名
* @param mixed $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function delete($name = '', $default = null, $filter = '')
{
return $this->put($name, $default, $filter);
}
/**
* 设置获取获取PATCH参数
* @access public
* @param string|array $name 变量名
* @param mixed $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function patch($name = '', $default = null, $filter = '')
{
return $this->put($name, $default, $filter);
}
/**
* 获取request变量
* @param string $name 数据名称
* @param string $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function request($name = '', $default = null, $filter = '')
{
if (empty($this->request)) {
$this->request = $_REQUEST;
}
if (is_array($name)) {
$this->param = [];
return $this->request = array_merge($this->request, $name);
}
return $this->input($this->request, $name, $default, $filter);
}
/**
* 获取cookie参数
* @access public
* @param string|array $name 数据名称
* @param string $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function cookie($name = '', $default = null, $filter = '')
{
if (empty($this->cookie)) {
$this->cookie = $_COOKIE;
}
if (is_array($name)) {
return $this->cookie = array_merge($this->cookie, $name);
}
return $this->input($this->cookie, $name, $default, $filter);
}
/**
* 获取server参数
* @access public
* @param string|array $name 数据名称
* @param string $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function server($name = '', $default = null, $filter = '')
{
if (empty($this->server)) {
$this->server = $_SERVER;
}
if (is_array($name)) {
return $this->server = array_merge($this->server, $name);
}
return $this->input($this->server, false === $name ? false : strtoupper($name), $default, $filter);
}
/**
* 获取环境变量
* @param string|array $name 数据名称
* @param string $default 默认值
* @param string|array $filter 过滤方法
* @return mixed
*/
public function env($name = '', $default = null, $filter = '')
{
if (empty($this->env)) {
$this->env = $_ENV;
}
if (is_array($name)) {
return $this->env = array_merge($this->env, $name);
}
return $this->input($this->env, false === $name ? false : strtoupper($name), $default, $filter);
}
/**
* 设置或者获取当前的Header
* @access public
* @param string|array $name header名称
* @param string $default 默认值
* @return string
*/
public function header($name = '', $default = null)
{
if (empty($this->header)) {
$header = [];
if (function_exists('apache_request_headers') && $result = apache_request_headers()) {
$header = $result;
} else {
$server = $this->server ?: $_SERVER;
foreach ($server as $key => $val) {
if (0 === strpos($key, 'HTTP_')) {
$key = str_replace('_', '-', strtolower(substr($key, 5)));
$header[$key] = $val;
}
}
if (isset($server['CONTENT_TYPE'])) {
$header['content-type'] = $server['CONTENT_TYPE'];
}
if (isset($server['CONTENT_LENGTH'])) {
$header['content-length'] = $server['CONTENT_LENGTH'];
}
}
$this->header = array_change_key_case($header);
}
if (is_array($name)) {
return $this->header = array_merge($this->header, $name);
}
if ('' === $name) {
return $this->header;
}
$name = str_replace('_', '-', strtolower($name));
return isset($this->header[$name]) ? $this->header[$name] : $default;
}
/**
* 获取变量 支持过滤和默认值
* @param array $data 数据源
* @param string|false $name 字段名
* @param mixed $default 默认值
* @param string|array $filter 过滤函数
* @return mixed
*/
public function input($data = [], $name = '', $default = null, $filter = '')
{
if (false === $name) {
// 获取原始数据
return $data;
}
$name = (string)$name;
if ('' != $name) {
// 解析name
if (strpos($name, '/')) {
list($name, $type) = explode('/', $name);
} else {
$type = 's';
}
// 按.拆分成多维数组进行判断
foreach (explode('.', $name) as $val) {
if (isset($data[$val])) {
$data = $data[$val];
} else {
// 无输入数据,返回默认值
return $default;
}
}
if (is_object($data)) {
return $data;
}
}
// 解析过滤器
if (is_null($filter)) {
$filter = [];
} else {
$filter = $filter ?: $this->filter;
if (is_string($filter)) {
$filter = explode(',', $filter);
} else {
$filter = (array)$filter;
}
}
$filter[] = $default;
if (is_array($data)) {
array_walk_recursive($data, [$this, 'filterValue'], $filter);
reset($data);
} else {
$this->filterValue($data, $name, $filter);
}
if (isset($type) && $data !== $default) {
// 强制类型转换
$this->typeCast($data, $type);
}
return $data;
}
/**
* 设置或获取当前的过滤规则
* @param mixed $filter 过滤规则
* @return mixed
*/
public function filter($filter = null)
{
if (is_null($filter)) {
return $this->filter;
} else {
$this->filter = $filter;
}
}
/**
* 递归过滤给定的值
* @param mixed $value 键值
* @param mixed $key 键名
* @param array $filters 过滤方法+默认值
* @return mixed
*/
private function filterValue(&$value, $key, $filters)
{
$default = array_pop($filters);
foreach ($filters as $filter) {
if (is_callable($filter)) {
// 调用函数或者方法过滤
$value = call_user_func($filter, $value);
} elseif (is_scalar($value)) {
if (strpos($filter, '/')) {
// 正则过滤
if (!preg_match($filter, $value)) {
// 匹配不成功返回默认值
$value = $default;
break;
}
} elseif (!empty($filter)) {
// filter函数不存在时, 则使用filter_var进行过滤
// filter为非整形值时, 调用filter_id取得过滤id
$value = filter_var($value, is_int($filter) ? $filter : filter_id($filter));
if (false === $value) {
$value = $default;
break;
}
}
}
}
return $this->filterExp($value);
}
/**
* 过滤表单中的表达式
* @param string $value
* @return void
*/
public function filterExp(&$value)
{
// 过滤查询特殊字符
if (is_string($value) && preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) {
$value .= ' ';
}
// TODO 其他安全过滤
}
/**
* 强制类型转换
* @param string $data
* @param string $type
* @return mixed
*/
private function typeCast(&$data, $type)
{
switch (strtolower($type)) {
// 数组
case 'a':
$data = (array)$data;
break;
// 数字
case 'd':
$data = (int)$data;
break;
// 浮点
case 'f':
$data = (float)$data;
break;
// 布尔
case 'b':
$data = (boolean)$data;
break;
// 字符串
case 's':
default:
if (is_scalar($data)) {
$data = (string)$data;
} else {
throw new \InvalidArgumentException('variable type error:' . gettype($data));
}
}
}
/**
* 是否存在某个请求参数
* @access public
* @param string $name 变量名
* @param string $type 变量类型
* @param bool $checkEmpty 是否检测空值
* @return mixed
*/
public function has($name, $type = 'param', $checkEmpty = false)
{
if (empty($this->$type)) {
$param = $this->$type();
} else {
$param = $this->$type;
}
// 按.拆分成多维数组进行判断
foreach (explode('.', $name) as $val) {
if (isset($param[$val])) {
$param = $param[$val];
} else {
return false;
}
}
return ($checkEmpty && '' === $param) ? false : true;
}
/**
* 获取指定的参数
* @access public
* @param string|array $name 变量名
* @param string $type 变量类型
* @return mixed
*/
public function only($name, $type = 'param')
{
$param = $this->$type();
if (is_string($name)) {
$name = explode(',', $name);
}
$item = [];
foreach ($name as $key) {
if (isset($param[$key])) {
$item[$key] = $param[$key];
}
}
return $item;
}
/**
* 排除指定参数获取
* @access public
* @param string|array $name 变量名
* @param string $type 变量类型
* @return mixed
*/
public function except($name, $type = 'param')
{
$param = $this->$type();
if (is_string($name)) {
$name = explode(',', $name);
}
foreach ($name as $key) {
if (isset($param[$key])) {
unset($param[$key]);
}
}
return $param;
}
/**
* 当前是否ssl
* @access public
* @return bool
*/
public function isSsl()
{
$server = array_merge($_SERVER, $this->server);
if (isset($server['HTTPS']) && ('1' == $server['HTTPS'] || 'on' == strtolower($server['HTTPS']))) {
return true;
} elseif (isset($server['REQUEST_SCHEME']) && 'https' == $server['REQUEST_SCHEME']) {
return true;
} elseif (isset($server['SERVER_PORT']) && ('443' == $server['SERVER_PORT'])) {
return true;
} elseif (isset($server['HTTP_X_FORWARDED_PROTO']) && 'https' == $server['HTTP_X_FORWARDED_PROTO']) {
return true;
}
return false;
}
/**
* 当前是否Ajax请求
* @access public
* @param bool $ajax true 获取原始ajax请求
* @return bool
*/
public function isAjax()
{
$value = $this->server('HTTP_X_REQUESTED_WITH', '', 'strtolower');
$result = ('xmlhttprequest' == $value) ? true : false;
return $result;
}
/**
* 获取客户端IP地址
* @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
* @param boolean $adv 是否进行高级模式获取(有可能被伪装)
* @return mixed
*/
public function ip($type = 0, $adv = false)
{
$type = $type ? 1 : 0;
static $ip = null;
if (null !== $ip) {
return $ip[$type];
}
if ($adv) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$pos = array_search('unknown', $arr);
if (false !== $pos) {
unset($arr[$pos]);
}
$ip = trim(current($arr));
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// IP地址合法验证
$long = sprintf("%u", ip2long($ip));
$ip = $long ? [$ip, $long] : ['0.0.0.0', 0];
return $ip[$type];
}
/**
* 检测是否使用手机访问
* @access public
* @return bool
*/
public function isMobile()
{
if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) {
return true;
} elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) {
return true;
} elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
return true;
} elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) {
return true;
} else {
return false;
}
}
/**
* 当前URL地址中的scheme参数
* @access public
* @return string
*/
public function scheme()
{
return $this->isSsl() ? 'https' : 'http';
}
/**
* 当前请求URL地址中的query参数
* @access public
* @return string
*/
public function query()
{
return $this->server('QUERY_STRING');
}
/**
* 当前请求的host
* @access public
* @return string
*/
public function host()
{
return $this->server('HTTP_HOST');
}
/**
* 当前请求URL地址中的port参数
* @access public
* @return integer
*/
public function port()
{
return $this->server('SERVER_PORT');
}
/**
* 当前请求 SERVER_PROTOCOL
* @access public
* @return integer
*/
public function protocol()
{
return $this->server('SERVER_PROTOCOL');
}
/**
* 当前请求 REMOTE_PORT
* @access public
* @return integer
*/
public function remotePort()
{
return $this->server('REMOTE_PORT');
}
/**
* 当前请求 HTTP_CONTENT_TYPE
* @access public
* @return string
*/
public function contentType()
{
$contentType = $this->server('CONTENT_TYPE');
if ($contentType) {
list($type) = explode(';', $contentType);
return trim($type);
}
return '';
}
/**
* 获取当前请求的路由信息
* @access public
* @param array $route 路由名称
* @return array
*/
public function routeInfo($route = [])
{
if (!empty($route)) {
$this->routeInfo = $route;
} else {
return $this->routeInfo;
}
}
/**
* 设置或者获取当前请求的content
* @access public
* @return string
*/
public function getContent()
{
if (is_null($this->content)) {
$this->content = $this->input;
}
return $this->content;
}
/**
* 获取当前请求的php://input
* @access public
* @return string
*/
public function getInput()
{
return $this->input;
}
/**
* 设置当前请求绑定的对象实例
* @access public
* @param string $name 绑定的对象标识
* @param mixed $obj 绑定的对象实例
* @return mixed
*/
public function bind($name, $obj = null)
{
if (is_array($name)) {
$this->bind = array_merge($this->bind, $name);
} else {
$this->bind[$name] = $obj;
}
}
public function __set($name, $value)
{
$this->bind[$name] = $value;
}
public function __get($name)
{
return isset($this->bind[$name]) ? $this->bind[$name] : null;
}
public function __isset($name)
{
return isset($this->bind[$name]);
}
}