// +---------------------------------------------------------------------- namespace think; class Response { // 输出类型的实例化对象 protected static $instance = []; // 输出数据的转换方法 protected $transform; // 输出数据 protected $data; // 输出类型 protected $type; // 当前的contentType protected $contentType; // 可用的输出类型 protected $contentTypes = [ 'json' => 'application/json', 'xml' => 'text/xml', 'html' => 'text/html', 'jsonp' => 'application/javascript', 'script' => 'application/javascript', 'text' => 'text/plain', ]; // 输出参数 protected $options = []; // header参数 protected $header = []; /** * 架构函数 * @access public * @param mixed $data 输出数据 * @param string $type 输出类型 * @param array $options 输出参数 */ public function __construct($data = [], $type = '', $options = []) { $this->data = $data; $this->type = strtolower($type ?: (IS_AJAX ? 'json' : 'html')); if (isset($this->contentTypes[$this->type])) { $this->contentType($this->contentTypes[$this->type]); } if(!empty($options)){ $this->options = array_merge($this->options, $options); } // 方便获取某个类型的实例 self::$instance[$this->type] = $this; } /** * 创建Response对象 * @access public * @param mixed $data 输出数据 * @param string $type 输出类型 * @param array $options 输出参数 */ public static function create($data = [], $type = '', $options = []) { $type = strtolower($type ?: (IS_AJAX ? 'json' : 'html')); if (!isset(self::$instance[$type])) { $class = (isset($options['namespace']) ? $options['namespace'] : '\\think\\response\\') . ucfirst($type); if (class_exists($class)) { $response = new $class($data, $type, $options); } else { $response = new static($data, $type, $options); } self::$instance[$type] = $response; } return self::$instance[$type]; } /** * 发送数据到客户端 * @access public * @param mixed $data 数据 * @return mixed */ public function send($data = []) { $data = $data ?: $this->data; if (isset($this->contentType)) { $this->contentType($this->contentType); } if (is_callable($this->transform)) { $data = call_user_func_array($this->transform, [$data]); } defined('RESPONSE_TYPE') or define('RESPONSE_TYPE',$this->type); // 处理输出数据 $data = $this->output($data); // 监听response_data Hook::listen('response_data', $data, $this); // 发送头部信息 if (!headers_sent() && !empty($this->header)) { // 发送状态码 if (isset($this->header['status'])) { http_response_code($this->header['status']); unset($this->header['status']); } foreach ($this->header as $name => $val) { header($name . ':' . $val); } } if (is_scalar($data)) { echo $data; } elseif (!is_null($data)) { throw new Exception('不支持的数据类型输出:' . gettype($data)); } if (function_exists('fastcgi_finish_request')) { // 提高页面响应 fastcgi_finish_request(); } return $data; } /** * 处理数据 * @access protected * @param mixed $data 要处理的数据 * @return mixed */ protected function output($data) { return $data; } /** * 转换控制器输出的数据 * @access public * @param mixed $callback 调用的转换方法 * @return $this */ public function transform($callback) { $this->transform = $callback; return $this; } /** * 输出的参数 * @access public * @param mixed $options 输出参数 * @return $this */ public function options($options = []) { $this->options = array_merge($this->options, $options); return $this; } /** * 输出数据设置 * @access public * @param mixed $data 输出数据 * @return $this */ public function data($data) { $this->data = $data; return $this; } /** * 返回封装后的API数据到客户端 * @access public * @param mixed $data 要返回的数据 * @param integer $code 返回的code * @param string $msg 提示信息 * @return mixed */ public function result($data, $code = 0, $msg = '') { $result = [ 'code' => $code, 'msg' => $msg, 'time' => NOW_TIME, 'data' => $data, ]; return $this->data($result); } /** * 设置响应头 * @access public * @param string $name 参数名 * @param string $value 参数值 * @return $this */ public function header($name, $value) { $this->header[$name] = $value; return $this; } /** * 发送HTTP Location * @param string $url Location地址 * @return $this */ public function location($url) { $this->header['Location'] = $url; return $this; } /** * 发送HTTP状态 * @param integer $code 状态码 * @return $this */ public function code($code) { $this->header['status'] = $code; return $this; } /** * LastModified * @param string $time * @return $this */ public function lastModified($time) { $this->header['Last-Modified'] = $time; return $this; } /** * Expires * @param string $time * @return $this */ public function expires($time) { $this->header['Expires'] = $time; return $this; } /** * ETag * @param string $etag * @return $this */ public function eTag($etag) { $this->header['etag'] = $etag; return $this; } /** * 页面缓存控制 * @param string $cache 状态码 * @return $this */ public function cacheControl($cache) { $this->header['Cache-control'] = $cache; return $this; } /** * 页面输出类型 * @param string $contentType 输出类型 * @param string $charset 输出编码 * @return $this */ public function contentType($contentType, $charset = 'utf-8') { $this->header['Content-Type'] = $contentType . '; charset=' . $charset; return $this; } /** * 获取头部信息 * @param string $name 头部名称 * @return mixed */ public function getHeader($name = '') { return !empty($name) ? $this->header[$name] : $this->header; } /** * 获取数据 * @return mixed */ public function getData() { return $this->data; } /** * 获取输出类型 * @return string */ public function getType() { return $this->type; } }