🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] * * * * * # 1 网络响应 >>网络响应,用来对服务器输出内容的操作。 >tp5内置了各种格式的网络响应。如view,json,xml,redirect等 >网络响应 主要包括网络响应信息的设置与网络响应的发送。 ### $response->__construct() >>创建网络响应对象 ~~~ public function __construct($data = '', $code = 200, array $header = [], $options = []) { $this->data($data); $this->header = $header; $this->code = $code; if (!empty($options)) { $this->options = array_merge($this->options, $options); } $this->contentType($this->contentType, $this->charset); } ~~~ >主要设置:网络响应的数据内容,网络响应头部信息,网络响应状态码,以及网络响应类型。 ### Reponse::create() >>创建不同类型的响应对象 ~~~ public static function create($data = '', $type = '', $code = 200, array $header = [], $options = []) { $type = empty($type) ? 'null' : strtolower($type); $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst($type); if (class_exists($class)) { $response = new $class($data, $code, $header, $options); } else { $response = new static($data, $code, $header, $options); } return $response; } ~~~ >根据类型参数,创建不同类型的响应对象。具体类型的网络响应对象实现在\response\目录下。 # 2 网络响应信息 >>网络对象可以获取和设置网络响应信息 ## 2-1 设置响应对象信息 ### $response->data() >>设置网络响应数据 ~~~ public function data($data) { $this->data = $data; return $this; } ~~~ ### $response->header() >>设置网络响应头 ~~~ public function header($name, $value = null) { if (is_array($name)) { $this->header = array_merge($this->header, $name); } else { $this->header[$name] = $value; } return $this; } ~~~ ### $response->code() >>设置网络响应状态码 ~~~ public function code($code) { $this->code = $code; return $this; } ~~~ ### $response->content() >> 设置页面输出内容 ~~~ public function content($content) { if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([ $content, '__toString', ]) ) { throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content))); } $this->content = (string) $content; return $this; } ~~~ ### $response->lastModified() ~~~ public function lastModified($time) { $this->header['Last-Modified'] = $time; return $this; } ~~~ ### $response->expires() ~~~ public function expires($time) { $this->header['Expires'] = $time; return $this; } ~~~ ### $response->eTag() ~~~ public function eTag($eTag) { $this->header['ETag'] = $eTag; return $this; } ~~~ ### $response->cacheControl() ~~~ public function cacheControl($cache) { $this->header['Cache-control'] = $cache; return $this; } ~~~ ### $response->contentType() ~~~ public function contentType($contentType, $charset = 'utf-8') { $this->header['Content-Type'] = $contentType . '; charset=' . $charset; return $this; } ~~~ ## 2-2 获取响应对象信息 ### $response->getHeader() >>获取响应对象 头部信息 ~~~ public function getHeader($name = '') { return !empty($name) ? $this->header[$name] : $this->header; } ~~~ ### $response->getData() >>获取响应对象 原始数据 ~~~ public function getData() { return $this->data; } ~~~ ### $response->getContent() >>获取响应对象 页面内容 ~~~ public function getContent() { if (null == $this->content) { $content = $this->output($this->data); if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([ $content, '__toString', ]) ) { throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content))); } $this->content = (string) $content; } return $this->content; } ~~~ ### $response->getCode() >>获取响应对象 状态码 ~~~ public function getCode() { return $this->code; } ~~~ ### $response->output() >>不同类型响应对象对数据的封装处理 # 3 网络响应发送 >> 网络响应发送接口,将网络响应信息发送到客户端。 ### $response->send() ~~~ public function send() { // 处理输出数据 $data = $this->getContent(); // Trace调试注入 if (Env::get('app_trace', Config::get('app_trace'))) { Debug::inject($this, $data); } if (!headers_sent() && !empty($this->header)) { // 发送状态码 http_response_code($this->code); // 发送头部信息 foreach ($this->header as $name => $val) { header($name . ':' . $val); } } echo $data; if (function_exists('fastcgi_finish_request')) { // 提高页面响应 fastcgi_finish_request(); } } ~~~ >首先输出网络响应状态码, 然后输出网络响应头部信息, 最后输出网络响应的数据内容。 >其中网络响应内容由不同响应对象进行封装处理,封装方法见下面的 网络响应类型 # 4 网络响应类型 >tp5内置json,jsonp,redirect,view,xml等响应类型 ## 4-1 json响应类型 ### $jsonresponse->output() ~~~ protected function output($data) { // 返回JSON数据格式到客户端 包含状态信息 $data = json_encode($data, $this->options['json_encode_param']); if ($data === false) { throw new \InvalidArgumentException(json_last_error_msg()); } return $data; } ~~~ ## 4-2 jsonp响应类型 ### $jsonpresponse->output() ~~~ protected function output($data) { // 返回JSON数据格式到客户端 包含状态信息 [当url_common_param为false时是无法获取到$_GET的数据的,故使用Request来获取<xiaobo.sun@qq.com>] $var_jsonp_handler = Request::instance()->param($this->options['var_jsonp_handler'], ""); $handler = !empty($var_jsonp_handler) ? $var_jsonp_handler : $this->options['default_jsonp_handler']; $data = json_encode($data, $this->options['json_encode_param']); if ($data === false) { throw new \InvalidArgumentException(json_last_error_msg()); } $data = $handler . '(' . $data . ');'; return $data; } ~~~ ## 4-3 redirect响应类型 >> redirect响应类型,主要对数据封装为跳转url地址。 ### $redirectresponse->output() >>redirect响应类型封装接口 ~~~ protected function output($data) { $this->header['Location'] = $this->getTargetUrl(); return; } ~~~ ### $redirectresponse->with() >>使用session在跳转url之间进行传值 ~~~ public function with($name, $value = null) { if (is_array($name)) { foreach ($name as $key => $val) { Session::set($key, $val); } } else { Session::set($name, $value); } return $this; } ~~~ ### $redirectresponse->remember() >>使用session存储当前跳转url ~~~ public function remember() { Session::set('redirect_url', Request::instance()->url()); } ~~~ ### $redirectresponse->restore() >>跳转到上次存储的url ~~~ public function restore() { if (Session::has('redirect_url')) { $this->data = Session::get('redirect_url'); Session::delete('redirect_url'); } } ~~~ ## 4-4 view响应类型 >>view响应对象数据封装。 ### $viewresponse->output() >>生成模板内容 ~~~ protected function output($data) { // 渲染模板输出 return ViewTemplate::instance(Config::get('template'), Config::get('view_replace_str')) ->fetch($data, $this->vars, $this->replace); } ~~~ ### $viewresponse->assign() >>设置视图模板变量 ~~~ public function assign($name, $value = '') { if (is_array($name)) { $this->vars = array_merge($this->vars, $name); return $this; } else { $this->vars[$name] = $value; } return $this; } ~~~ ### $viewresponse->getVars() >>获取视图模板变量 ~~~ public function getVars($name = null) { if (is_null($name)) { return $this->vars; } else { return isset($this->vars[$name]) ? $this->vars[$name] : null; } } ~~~ ### $viewresponse->replace() >>视图内容替换 ~~~ public function replace($content, $replace = '') { if (is_array($content)) { $this->replace = array_merge($this->replace, $content); } else { $this->replace[$content] = $replace; } return $this; } ~~~ ## 4-5 xml响应类型 ### $xmlresponse->output() >>封装为xml接口 ~~~ protected function output($data) { // XML数据转换 return $this->xmlEncode($data, $this->options['root_node'], $this->options['item_node'], $this->options['root_attr'], $this->options['item_key'], $this->options['encoding']); } ~~~ ### $xmlresponse->xmlEncode() >>封装为xml格式 ~~~ protected function xmlEncode($data, $root, $item, $attr, $id, $encoding) { if (is_array($attr)) { $array = []; foreach ($attr as $key => $value) { $array[] = "{$key}=\"{$value}\""; } $attr = implode(' ', $array); } $attr = trim($attr); $attr = empty($attr) ? '' : " {$attr}"; $xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>"; $xml .= "<{$root}{$attr}>"; $xml .= $this->dataToXml($data, $item, $id); $xml .= "</{$root}>"; return $xml; } ~~~ ### $xmlresponse->dataToXml() >>数据为xml格式 ~~~ protected function dataToXml($data, $item, $id) { $xml = $attr = ''; foreach ($data as $key => $val) { if (is_numeric($key)) { $id && $attr = " {$id}=\"{$key}\""; $key = $item; } $xml .= "<{$key}{$attr}>"; $xml .= (is_array($val) || is_object($val)) ? $this->dataToXml($val, $item, $id) : $val; $xml .= "</{$key}>"; } return $xml; } ~~~