🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] * * * * * ## 1 输入输出 ### 0 输入输出概览 ![](https://box.kancloud.cn/2016-03-16_56e9270eb3e7b.jpg) ### 1 Url输入 Url是客户端对服务器/应用业务的请求 通过路由解析生成对应用业务的请求 普通输入数据侧重于在应用业务中的操作 Url输入侧重于对应用业务的请求连接 ### 2 狭义的数据输入输出 >[info] 1 客户端的数据输入 浏览器/APP等发送给服务器的数据 >[info] 2 输出数据到客户端 服务器响应发送给浏览器/APP的数据 ### 3 广义的数据输入输出 >[info] 1 狭义的输入输出 * * * * * >[info] 2 广义输入: (应用业务中可用) 服务器/框架变量 日志/缓存/数据库数据 * * * * * >[info] 3 广义输出: (应用业务输出数据) 日志/缓存记录 模板/数据库数据 ## 2 Url输入 思路见 [心:url路由详解](http://www.kancloud.cn/zmwtp/tp5/127349) ## 3 输入读取 ### 输入数据的读取:think\Input.php >[info] 输入数据读取核心函数 data() **data()在其他类型输入数据读取函数中调用** `public static function data($input, $name = '', $default = null, $filter = null, $merge = false)` > $input:输入数据源 > $name:输入数据键名 > $default:默认输入数据值 > $filter:输入数据过滤器 > $merge:输入数据是否合并 ~~~ if (0 === strpos($name, '?')) { return self::has(substr($name, 1), $input); } ~~~ 如果$name包含?,则调用self::has()检查是否有输入数据键名。 `if (!empty($input)) {}else{}` 检查输入数据源, 如果输入数据源为不为空,读取输入数据 如果输入数据源为空,返回默认值$default `$data = $input;` 将$input数据源放入到$data变量,避免影响数据源 `$name = (string) $name;` 将$name键名转换为字符串 `list($name, $type) = static::parseName($name);` 调用self::parseName()将$name解析到$name,$type变量中 `foreach (explode('.', $name) as $val) {}` 将$name以符号"."分割为数组,并遍历键名。 ~~~ if (isset($data[$val])) { $data = $data[$val]; } ~~~ 如果输入数据源$data中有对应键名$val。 获取对应数据$data[$val]并保存到$data, **这里是多维数据读取的一个技巧** ~~~ else { return $default; } ~~~ 如果输入数据源$data中没有对应键名$val 返回默认值$dafault `$filters = static::parseFilter($filter, $merge);` 调用self::parseFilter()生成数据解析器$filter ~~~ $filters[] = $default; ~~~ 添加$dafault到过滤器中。 ~~~ if (is_array($data)) { array_walk_recursive($data, 'self::filter', $filters); } else { self::filter($data, $name ?: 0, $filters); } ~~~ 对输入数据源$data进行过滤$filter处理 ~~~ if (isset($type) && $data !== $default) { static::typeCast($data, $type); } ~~~ 如果$name中解析到$type参数, 则调用self::typeCast()进行类型转换 ~~~ else { $data = $default; } ~~~ 数据源$input为空时,返回默认值 ~~~ return $data; ~~~ 返回获取的数据, 由此可知$name为空时, 返回过滤后的数据源$input * * * * * >[info] 狭义输入数据读取操作(调用self::data()读取对应数据): get() post() put() delete() param() request() session() cookie() `$_GET数据读取:public static function get($name = '', $default = null, $filter = null, $merge = false)` `$_POST数据读取:public static function post($name = '', $default = null, $filter = null, $merge = false)` `$_PUT数据读取:public static function put($name = '', $default = null, $filter = null, $merge = false)` `$_DELETE数据读取:public static function delete($name = '', $default = null, $filter = null, $merge = false)` `多功能数据读取:public static function param($name = '', $default = null, $filter = null, $merge = false)` `$_REQUEST数据读取:public static function request($name = '', $default = null, $filter = null, $merge = false)` `上传文件$_FILE数据读取:public static function file($name = '', $default = null, $filter = null, $merge = false)` `$_SESSION数据读取:public static function session($name = '', $default = null, $filter = null, $merge = false)` `$_COOKIE数据读取:public static function cookie($name = '', $default = null, $filter = null, $merge = false)` * * * * * >[info] 广义输入数据读取操作(调用self::data()读取对应数据): server() globals() env() path() `$_SERVER数据读取:public static function server($name = '', $default = null, $filter = null, $merge = false)` `$GLOBALS数据读取:public static function globals($name = '', $default = null, $filter = null, $merge = false)` `$_ENV数据读取:public static function env($name = '', $default = null, $filter = null, $merge = false)` `PATH_INFO数据读取:public static function path($name = '', $default = null, $filter = null, $merge = false)` > $name:输入数据键名 > $default:输入数据默认值 > $filter:输入数据过滤处理 > $merge:输入数据是否合并 * * * * * >[info] 其他操作 has() setFilter() filterExp() `检查数据键名存在:public static function has($name, $data)` `设置数据过滤器:public static function setFilter($name)` `过滤表单表达式:public static function filterExp(&$value)` ### 服务器/框架变量 >[info] 服务器全局变量:直接使用变量名即可 ~~~ MODULE_NAME CONTROLLER_NAME ~~~ >[info] 服务器配置读取:think\Config::get() ~~~ Config::get() ~~~ ## 4 输出数据 ### 输出数据到客户端 think\Response.php >[info] 数据输出操作 `发送字符串数据到客户端:public static function send($data = '', $type = '', $return = false)` > $data:待组合的数据 > $type:数据组合格式 > $return:数据返回还是输出 `$type = strtolower($type ?: self::$type);` 输出数据类型解析 ~~~ $headers = [ 'json' => 'application/json', 'xml' => 'text/xml', 'html' => 'text/html', 'jsonp' => 'application/javascript', 'script' => 'application/javascript', 'text' => 'text/plain', ]; if (!headers_sent() && !headers_list() && isset($headers[$type])) { header('Content-Type:' . $headers[$type] . '; charset=utf-8'); } ~~~ 根据$type,设置输出数据头header中的Content-Type `$data = $data ?: self::$data;` 输出数据准备 ~~~ if (is_callable(self::$tramsform)) { $data = call_user_func_array(self::$tramsform, [$data]); } ~~~ 检查数据格式是否需要转换 ~~~ switch ($type) { case 'json': $data = json_encode($data, JSON_UNESCAPED_UNICODE); break; case 'jsonp': $handler = !empty($_GET[Config::get('var_jsonp_handler')]) ? $_GET[Config::get('var_jsonp_handler')] : Config::get('default_jsonp_handler'); $data = $handler . '(' . json_encode($data, JSON_UNESCAPED_UNICODE) . ');'; break; case '': case 'html': case 'text': break; default: APP_HOOK && Hook::listen('return_data', $data); } ~~~ 根据$type合成不同的输出字符串内容 ~~~ if ($return) { return $data; } ~~~ 检查是否返回数据 `echo $data;` 输出合成的字符串到客户端 `self::isExit() && exit();` 检查是否退出脚本 * * * * * `输出API格式数据到客户端:public static function result($data, $code = 0, $msg = '', $type = '')` > $data:待输出数据 > $code:api状态编码 > $mmsg:输出提示信息 > $type:输出数据类型 ~~~ $result = [ 'code' => $code, 'msg' => $msg, 'time' => NOW_TIME, 'data' => $data, ]; ~~~ 合成输出数据 ~~~ if ($type) { self::type($type); } ~~~ 设置输出数据类型 `return $result;` 返回api数据 * * * * * >[info] 输出数据与格式设置 `设置待输出数据:public static function data($data)` `设置数据转换方法:public static function tramsform($callback)` `设置输出数据格式:public static function type($type = null)` `设置脚本是否终止:public static function isExit($exit = null)` >[info] 根据状态输出 `输出成功信息:public static function success($msg = '', $data = '', $url = null, $wait = 3)` `输出错误信息:public static function error($msg = '', $data = '', $url = null, $wait = 3)` `跳转指定链接:public static function redirect($url, $params = [])` * * * * * ### 输出生成模板:think\View.php 思路见 [模板详解](http://www.kancloud.cn/zmwtp/tp5/127351) * * * * * ### 输出生成日志:think\Log.php 思路见 [日志详解](http://www.kancloud.cn/zmwtp/tp5/127953) * * * * * ### 输出生成缓存:think\Cache.php 思路见 [缓存详解](http://www.kancloud.cn/zmwtp/tp5/127954) * * * * * ### 输出数据到数据库:think\Model.php 思路见 [模型详解](http://www.kancloud.cn/zmwtp/tp5/127352) * * * * * ## 5 框架输入输出示例 >[info] 调用Input::filterExp()过滤输入数据 ~~~ thinkphp\start.php: private static function bindParams($reflect, $vars) { $args = []; $type = key($vars) === 0 ? 1 : 0; if ($reflect->getNumberOfParameters() > 0) { $params = $reflect->getParameters(); foreach ($params as $param) { $name = $param->getName(); if (1 == $type && !empty($vars)) { $args[] = array_shift($vars); } elseif (0 == $type && isset($vars[$name])) { $args[] = $vars[$name]; } elseif ($param->isDefaultValueAvailable()) { $args[] = $param->getDefaultValue(); } else { throw new Exception('method param miss:' . $name, 10004); } } array_walk_recursive($args, 'think\\Input::filterExp'); } return $args; } ~~~ >[info] 调用Response::send()输出数据到客户端。 ~~~ public static function run() { .... switch (self::$dispatch['type']) { case 'redirect': header('Location: ' . self::$dispatch['url'], true, self::$dispatch['status']); break; case 'module': $data = self::module(self::$dispatch['module'], $config); break; case 'controller': $data = Loader::action(self::$dispatch['controller'], self::$dispatch['params']); break; case 'method': $data = self::invokeMethod(self::$dispatch['method'], self::$dispatch['params']); break; case 'function': $data = self::invokeFunction(self::$dispatch['function'], self::$dispatch['params']); break; default: throw new Exception('dispatch type not support', 10008); } APP_HOOK && Hook::listen('app_end', $data); if (Config::get('response_auto_output')) { return Response::send($data, Response::type(), Config::get('response_return')); } } ~~~