diff --git a/helper.php b/helper.php index 892fac8c..78a49390 100644 --- a/helper.php +++ b/helper.php @@ -106,18 +106,16 @@ function config($name = '', $value = null, $range = '') * @param bool $merge 是否合并系统默认过滤方法 * @return mixed */ -function input($key, $default = null, $filter = null, $merge = false) +function input($key, $default = null, $filter = null) { if (0 === strpos($key, '?')) { $key = substr($key, 1); - $has = '?'; - } else { - $has = ''; + $has = true; } if ($pos = strpos($key, '.')) { // 指定参数来源 $method = substr($key, 0, $pos); - if (in_array($method, ['get', 'post', 'put', 'delete', 'param', 'request', 'session', 'cookie', 'server', 'globals', 'env', 'path', 'file'])) { + if (in_array($method, ['get', 'post', 'put', 'delete', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) { $key = substr($key, $pos + 1); } else { $method = 'param'; @@ -126,7 +124,11 @@ function input($key, $default = null, $filter = null, $merge = false) // 默认为自动判断 $method = 'param'; } - return Input::$method($has . $key, $default, $filter, $merge); + if(isset($has)){ + return request()->has($key, $method, $default); + }else{ + return request()->$method($key, $default, $filter); + } } /** diff --git a/library/think/App.php b/library/think/App.php index e98c0763..edeac39e 100644 --- a/library/think/App.php +++ b/library/think/App.php @@ -222,7 +222,7 @@ class App } } // 全局过滤 - array_walk_recursive($args, 'think\\Input::filterExp'); + array_walk_recursive($args, [Request::instance(),'filterExp']); } return $args; } @@ -458,8 +458,7 @@ class App // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索 $result = Route::parseUrl($path, $depr, $config['controller_auto_search'], $config['url_param_type']); } - //保证$_REQUEST正常取值 - $_REQUEST = array_merge($_POST, $_GET, $_COOKIE); + // 注册调度机制 return $request->dispatch($result); } diff --git a/library/think/Input.php b/library/think/Input.php deleted file mode 100644 index de287b14..00000000 --- a/library/think/Input.php +++ /dev/null @@ -1,481 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -use think\Config; -use think\File; -use think\Session; - -class Input -{ - // 全局过滤规则 - public static $filters; - - /** - * 获取get变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function get($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($_GET, $name, $default, $filter, $merge); - } - - /** - * 获取post变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function post($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($_POST, $name, $default, $filter, $merge); - } - - /** - * 获取put变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function put($name = '', $default = null, $filter = null, $merge = false) - { - static $_PUT = null; - if (is_null($_PUT)) { - parse_str(file_get_contents('php://input'), $_PUT); - } - return self::data($_PUT, $name, $default, $filter, $merge); - } - - /** - * 获取delete变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function delete($name = '', $default = null, $filter = null, $merge = false) - { - static $_DELETE = null; - if (is_null($_DELETE)) { - parse_str(file_get_contents('php://input'), $_DELETE); - $_DELETE = array_merge($_DELETE, $_GET); - } - return self::data($_DELETE, $name, $default, $filter, $merge); - } - - /** - * 根据请求方法获取变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function param($name = '', $default = null, $filter = null, $merge = false) - { - switch ($_SERVER['REQUEST_METHOD']) { - case 'POST': - $method = 'post'; - break; - case 'PUT': - $method = 'put'; - break; - case 'DELETE': - $method = 'delete'; - break; - default: - $method = 'get'; - } - return self::$method($name, $default, $filter, $merge); - } - - /** - * 获取request变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function request($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($_REQUEST, $name, $default, $filter, $merge); - } - - /** - * 获取session变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function session($name = '', $default = null, $filter = null, $merge = false) - { - return self::data(Session::get(), $name, $default, $filter, $merge); - } - - /** - * 获取cookie变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function cookie($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($_COOKIE, $name, $default, $filter, $merge); - } - - /** - * 获取post变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function server($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($_SERVER, strtoupper($name), $default, $filter, $merge); - } - - /** - * 获取GLOBALS变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function globals($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($GLOBALS, $name, $default, $filter, $merge); - } - - /** - * 获取环境变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function env($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($_ENV, strtoupper($name), $default, $filter, $merge); - } - - /** - * 获取PATH_INFO - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function path($name = '', $default = null, $filter = null, $merge = false) - { - if (!empty($_SERVER['PATH_INFO'])) { - $depr = Config::get('pathinfo_depr'); - $input = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); - return self::data($input, $name, $default, $filter, $merge); - } else { - return $default; - } - } - - /** - * 获取$_FILES - * @param string $name 数据名称 - * @param array $files 上传文件 - * @return \think\File|array - */ - public static function file($name = '', $files = []) - { - $files = $files ?: (isset($_FILES) ? $_FILES : []); - if (!empty($files)) { - // 处理上传文件 - $array = []; - $n = 0; - foreach ($files as $key => $file) { - if (is_array($file['name'])) { - $keys = array_keys($file); - $count = count($file['name']); - for ($i = 0; $i < $count; $i++) { - $array[$n]['key'] = $key; - foreach ($keys as $_key) { - $array[$n][$_key] = $file[$_key][$i]; - } - $n++; - } - } else { - $array = $files; - break; - } - } - - if ('' === $name) { - // 获取全部文件 - $item = []; - foreach ($array as $key => $val) { - if($val instanceof File){ - $item[$key] = $val; - }else{ - if (empty($val['tmp_name'])) { - continue; - } - $item[$key] = new File($val['tmp_name'], $val); - } - } - return $item; - } elseif (isset($array[$name])) { - if($array[$name] instanceof File){ - return $array[$name]; - } elseif (!empty($array[$name]['tmp_name'])){ - return new File($array[$name]['tmp_name'], $array[$name]); - } - } - } - return null; - } - - /** - * 获取变量 支持过滤和默认值 - * @param array $input 数据源 - * @param string $name 字段名 - * @param mixed $default 默认值 - * @param mixed $filter 过滤函数 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function data($input, $name = '', $default = null, $filter = null, $merge = false) - { - if (0 === strpos($name, '?')) { - return self::has(substr($name, 1), $input); - } - - $data = $input; - $name = (string) $name; - if ('' != $name) { - // 解析name - list($name, $type) = static::parseName($name); - // 按.拆分成多维数组进行判断 - foreach (explode('.', $name) as $val) { - if (isset($data[$val])) { - $data = $data[$val]; - } else { - // 无输入数据,返回默认值 - return $default; - } - } - } - - // 解析过滤器 - $filters = static::parseFilter($filter, $merge); - // 为方便传参把默认值附加在过滤器后面 - $filters[] = $default; - if (is_array($data)) { - array_walk_recursive($data, 'self::filter', $filters); - } else { - self::filter($data, $name ?: 0, $filters); - } - if (isset($type) && $data !== $default) { - // 强制类型转换 - static::typeCast($data, $type); - } - - return $data; - } - - /** - * 判断一个变量是否设置 - * @param string $name - * @param array $data - * @return bool - */ - public static function has($name, $data) - { - foreach (explode('.', $name) as $val) { - if (!isset($data[$val])) { - return false; - } else { - $data = $data[$val]; - } - } - return true; - } - - /** - * 设置默认的过滤函数 - * @param string|array $name - * @return array - */ - public static function setFilter($name) - { - if (is_string($name)) { - $name = explode(',', $name); - } - static::$filters = $name; - } - - /** - * 过滤表单中的表达式 - * @param string $value - * @return void - */ - public static function filterExp(&$value) - { - // TODO 其他安全过滤 - - // 过滤查询特殊字符 - 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 .= ' '; - } - } - - /** - * 递归过滤给定的值 - * @param mixed $value 键值 - * @param mixed $key 键名 - * @param array $filters 过滤方法+默认值 - * @return mixed - */ - private static function filter(&$value, $key, $filters) - { - // 分离出默认值 - $default = array_pop($filters); - foreach ($filters as $filter) { - if (is_callable($filter)) { - // 调用函数过滤 - $value = call_user_func($filter, $value); - } else { - $begin = substr($filter, 0, 1); - if (in_array($begin, ['/', '#', '~']) && $begin == $end = substr($filter, -1)) { - // 正则过滤 - if (!preg_match($filter, $value)) { - // 匹配不成功返回默认值 - $value = $default; - break; - } - } else { - // filter函数不存在时, 则使用filter_var进行过滤 - // filter为非整形值时, 调用filter_id取得过滤id - $value = filter_var($value, is_int($filter) ? $filter : filter_id($filter)); - if (false === $value) { - // 不通过过滤器则返回默认值 - $value = $default; - break; - } - } - } - } - self::filterExp($value); - } - - /** - * 解析name - * @param string $name - * @return array 返回name和类型 - */ - private static function parseName($name) - { - return strpos($name, '/') ? explode('/', $name, 2) : [$name, 's']; - } - - /** - * 解析过滤器 - * @param mixed $filter - * @return array - */ - private static function parseFilter($filter, $merge = false) - { - if (is_null($filter)) { - $result = self::getFilter(); - } elseif (empty($filter)) { - $result = []; - } else { - if (is_array($filter)) { - $result = $filter; - } elseif (is_string($filter) && false === strpos($filter, '/') && strpos($filter, ',')) { - $result = explode(',', $filter); - } else { - $result = [$filter]; - } - if ($merge) { - // 与默认的过滤函数合并 - $result = array_merge(self::getFilter(), array_diff($result, self::getFilter())); - } - } - return $result; - } - - /** - * 获取过滤方法 - * @return array - */ - private static function getFilter() - { - if (is_null(static::$filters)) { - // 从配置项中读取 - $filters = Config::get('default_filter'); - static::$filters = empty($filters) ? [] : (is_array($filters) ? $filters : explode(',', $filters)); - } - return static::$filters; - } - - /** - * 强类型转换 - * @param string $data - * @param string $type - * @return mixed - */ - private static 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)); - } - } - } -} diff --git a/library/think/Paginator.php b/library/think/Paginator.php index c37dc5aa..eba38587 100644 --- a/library/think/Paginator.php +++ b/library/think/Paginator.php @@ -12,6 +12,7 @@ namespace think; use think\paginator\Collection as PaginatorCollection; +use think\Request; abstract class Paginator { @@ -122,7 +123,7 @@ abstract class Paginator */ public static function getCurrentPage($varPage = 'page', $default = 1) { - $page = Input::request($varPage); + $page = Request::instance()->request($varPage); if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int)$page >= 1) { return $page; diff --git a/library/think/Request.php b/library/think/Request.php index 5fffbdc2..f3b86152 100644 --- a/library/think/Request.php +++ b/library/think/Request.php @@ -883,9 +883,9 @@ class Request $name = (string) $name; if ('' != $name) { // 解析name - if(strpos($name, '/')){ - list($name, $type) = explode($name, '/'); - }else{ + if (strpos($name, '/')) { + list($name, $type) = explode('/', $name); + } else { $type = 's'; } // 按.拆分成多维数组进行判断 @@ -901,15 +901,19 @@ class Request // 解析过滤器 $filter = $filter ?: $this->filter; + if (is_string($filter)) { - $filter = explode(',',$filter); + $filter = explode(',', $filter); + } else { + $filter = (array)$filter; } $filter[] = $default; if (is_array($data)) { - array_walk_recursive($data, [$this,'filterValue'], $filter); + array_walk_recursive($data, [$this, 'filterValue'], $filter); } else { - $this->filterValue($data, $name,$filter); + $this->filterValue($data, $name, $filter); } + if (isset($type) && $data !== $default) { // 强制类型转换 $this->typeCast($data, $type); @@ -943,11 +947,10 @@ class Request $default = array_pop($filters); foreach ($filters as $filter) { if (is_callable($filter)) { - // 调用函数过滤 + // 调用函数或者方法过滤 $value = call_user_func($filter, $value); } else { - $begin = substr($filter, 0, 1); - if (in_array($begin, ['/', '#', '~']) && $begin == $end = substr($filter, -1)) { + if (strpos($filter,'/')) { // 正则过滤 if (!preg_match($filter, $value)) { // 匹配不成功返回默认值 @@ -973,7 +976,7 @@ class Request * @param string $value * @return void */ - private function filterExp(&$value) + 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)) { @@ -1033,11 +1036,15 @@ class Request } else { $param = $this->$type; } - if (isset($param[$name])) { - return ($checkEmpty && '' === $param[$name]) ? false : true; - } else { - return false; - } + // 按.拆分成多维数组进行判断 + foreach (explode('.', $name) as $val) { + if (isset($param[$val])) { + $param = $param[$val]; + } else { + return false; + } + } + return ($checkEmpty && '' === $param) ? false : true; } /** diff --git a/library/think/Validate.php b/library/think/Validate.php index 02f4386e..37f11f56 100644 --- a/library/think/Validate.php +++ b/library/think/Validate.php @@ -551,7 +551,7 @@ class Validate $result = is_array($value); break; case 'file': - $file = Input::file($value); + $file = Request::instance()->file($value); $result = !empty($file); break; default: @@ -602,7 +602,7 @@ class Validate */ protected function fileExt($value, $rule) { - $file = Input::file($value); + $file = Request::instance()->file($value); if (empty($file)) { return false; } @@ -630,7 +630,7 @@ class Validate */ protected function fileMime($value, $rule) { - $file = Input::file($value); + $file = Request::instance()->file($value); if (empty($file)) { return false; } @@ -658,7 +658,7 @@ class Validate */ protected function fileSize($value, $rule) { - $file = Input::file($value); + $file = Request::instance()->file($value); if (empty($file)) { return false; } diff --git a/tests/thinkphp/library/think/inputTest.php b/tests/thinkphp/library/think/inputTest.php deleted file mode 100644 index 608d888f..00000000 --- a/tests/thinkphp/library/think/inputTest.php +++ /dev/null @@ -1,194 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Input测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -use think\Input; - -class inputTest extends \PHPUnit_Framework_TestCase -{ - - public function testInputName() - { - $input = ['a' => 'a', 'b' => ['c' => [' one ', 'two']]]; - $this->assertEquals($input, Input::data($input)); - $this->assertEquals($input['a'], Input::data($input, 'a')); - $this->assertEquals('one', Input::data($input, 'b.c.0/s', 'default', 'trim')); - } - - public function testDefaultValue() - { - $input = ['a' => 'test']; - $default = 'default'; - $this->assertEquals($default, Input::data($input, 'b', $default)); - $this->assertEquals($default, Input::get('a', $default)); - } - - public function testStringFilter() - { - $input = ['a' => ' test ', 'b' => ' test<> ']; - $filters = 'trim'; - $this->assertEquals('test', Input::data($input, 'a', '', $filters)); - $filters = 'trim,htmlspecialchars'; - $this->assertEquals('test<>', Input::data($input, 'b', '', $filters)); - } - - public function testArrayFilter() - { - $input = ['a' => ' test ', 'b' => ' test<> ']; - $filters = ['trim']; - $this->assertEquals('test', Input::data($input, 'a', '', $filters)); - $filters = ['trim', 'htmlspecialchars']; - $this->assertEquals('test<>', Input::data($input, 'b', '', $filters)); - } - - public function testFilterExp() - { - $src = 'EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN'; - $regexs = explode('|', $src); - $data = Input::data($regexs); - foreach ($regexs as $key => $value) { - $expected = $value . ' '; - $this->assertEquals($expected, $data[$key]); - } - } - - public function testFiltrateWithRegex() - { - $input = ['a' => 'test1', 'b' => '_test2', 'c' => '']; - $filters = '/^test/'; - $this->assertEquals('test1', Input::data($input, 'a', '', $filters)); - $default = 'default value'; - $this->assertEquals($default, Input::data($input, 'b', $default, $filters)); - $filters = '/.+/'; - $this->assertEquals('default value', Input::data($input, 'c', $default, $filters)); - } - - public function testFiltrateWithFilterVar() - { - $email = 'abc@gmail.com'; - $error = 'not email'; - $default = false; - $input = ['a' => $email, 'b' => $error]; - $filters = FILTER_VALIDATE_EMAIL; - $this->assertEquals($email, Input::data($input, 'a', '', $filters)); - $this->assertFalse(Input::data($input, 'b', $default, $filters)); - $filters = 'validate_email'; - $this->assertFalse(Input::data($input, 'b', $default, $filters)); - } - - public function testAllInput() - { - $input = [ - 'a' => ' trim ', - 'b' => 'htmlspecialchars<>', - 'c' => ' trim htmlspecialchars<> ', - 'd' => 'eXp', - 'e' => 'NEQ', - 'f' => 'gt', - ]; - $filters = 'htmlspecialchars,trim'; - $excepted = [ - 'a' => 'trim', - 'b' => 'htmlspecialchars<>', - 'c' => 'trim htmlspecialchars<>', - 'd' => 'eXp ', - 'e' => 'NEQ ', - 'f' => 'gt ', - ]; - $this->assertEquals($excepted, Input::data($input, '', '', $filters)); - } - - public function testTypeCast() - { - $_POST = [ - 'a' => [1, 2, 3], - 'b' => '1000', - 'c' => '3.14', - 'd' => 'test boolean', - ]; - $this->assertEquals([1, 2, 3], Input::post('a/a')); - $this->assertEquals(1000, Input::post('b/d')); - $this->assertEquals(3.14, Input::post('c/f')); - $this->assertEquals(true, Input::post('d/b')); - } - - public function testHasValue() - { - $_GET['name'] = 'value'; - $_GET['config']['name'] = 'value'; - $this->assertEquals(true, Input::get('?name')); - $this->assertEquals(false, Input::get('?id')); - $this->assertEquals(true, Input::get('?config.name')); - $this->assertEquals(false, Input::get('?config.id')); - } - - public function testSuperglobals() - { - Input::setFilter('trim'); - $_GET['get'] = 'get value '; - $this->assertEquals('get value', Input::get('get')); - $_POST['post'] = 'post value '; - $this->assertEquals('post value', Input::post('post')); - - $_SERVER['REQUEST_METHOD'] = 'POST'; - $this->assertEquals('post value', Input::param('post')); - $this->assertEquals(null, Input::param('get')); - $_SERVER['REQUEST_METHOD'] = 'GET'; - $this->assertEquals('get value', Input::param('get')); - $this->assertEquals(null, Input::param('post')); - $this->assertEquals(null, Input::param('put')); - $_REQUEST = array_merge($_GET, $_POST); - $this->assertEquals('get value', Input::request('get')); - - //session_start(); - $_SESSION['test'] = 'session value '; - $this->assertEquals('session value', Input::session('test')); - //session_destroy(); - - $_COOKIE['cookie'] = 'cookie value '; - $this->assertEquals('cookie value', Input::cookie('cookie')); - - $_SERVER['REQUEST_METHOD'] = 'GET '; - $this->assertEquals('GET', Input::server('REQUEST_METHOD')); - - $GLOBALS['total'] = 1000; - $this->assertEquals(1000, Input::globals('total')); - - $this->assertEquals('testing', Input::env('APP_ENV')); - - //$_SERVER['PATH_INFO'] = 'path/info'; - //$path = $_SERVER['PATH_INFO'] ? explode('/', $_SERVER['PATH_INFO'])[0] : ''; - //$this->assertEquals($path, Input::path('0', '')); - - $_FILES = ['file' => ['name' => 'test.png', 'type' => 'image/png', 'tmp_name' => '/tmp/php5Wx0aJ', 'error' => 0, 'size' => 15726]]; - $this->assertEquals(null, Input::file('file.type')); - - } - - public function testFilterMerge() - { - Input::setFilter('htmlspecialchars'); - $input = ['a' => ' test<> ', 'b' => '']; - $this->assertEquals(' test<> ', Input::data($input, 'a', '', '')); - $filters = ['trim']; - $this->assertEquals('test<>', Input::data($input, 'a', '', $filters)); - $this->assertEquals('test<>', Input::data($input, 'a', '', $filters, true)); - $filters = 'stripslashes'; - $this->assertEquals("<bar />", Input::data($input, 'b', '', $filters, true)); - } - -}