Response.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. use think\response\Json as JsonResponse;
  13. use think\response\Jsonp as JsonpResponse;
  14. use think\response\Redirect as RedirectResponse;
  15. use think\response\View as ViewResponse;
  16. use think\response\Xml as XmlResponse;
  17. class Response
  18. {
  19. // 原始数据
  20. protected $data;
  21. // 当前的contentType
  22. protected $contentType = 'text/html';
  23. // 字符集
  24. protected $charset = 'utf-8';
  25. //状态
  26. protected $code = 200;
  27. // 输出参数
  28. protected $options = [];
  29. // header参数
  30. protected $header = [];
  31. protected $content = null;
  32. /**
  33. * 架构函数
  34. * @access public
  35. * @param mixed $data 输出数据
  36. * @param int $code
  37. * @param array $header
  38. * @param array $options 输出参数
  39. */
  40. public function __construct($data = '', $code = 200, array $header = [], $options = [])
  41. {
  42. $this->data($data);
  43. $this->header = $header;
  44. $this->code = $code;
  45. if (!empty($options)) {
  46. $this->options = array_merge($this->options, $options);
  47. }
  48. $this->contentType($this->contentType, $this->charset);
  49. }
  50. /**
  51. * 创建Response对象
  52. * @access public
  53. * @param mixed $data 输出数据
  54. * @param string $type 输出类型
  55. * @param int $code
  56. * @param array $header
  57. * @param array $options 输出参数
  58. * @return Response|JsonResponse|ViewResponse|XmlResponse|RedirectResponse|JsonpResponse
  59. */
  60. public static function create($data = '', $type = '', $code = 200, array $header = [], $options = [])
  61. {
  62. $type = empty($type) ? 'null' : strtolower($type);
  63. $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst($type);
  64. if (class_exists($class)) {
  65. $response = new $class($data, $code, $header, $options);
  66. } else {
  67. $response = new static($data, $code, $header, $options);
  68. }
  69. return $response;
  70. }
  71. /**
  72. * 发送数据到客户端
  73. * @access public
  74. * @return mixed
  75. * @throws \InvalidArgumentException
  76. */
  77. public function send()
  78. {
  79. // 处理输出数据
  80. $data = $this->getContent();
  81. // Trace调试注入
  82. if (Env::get('app_trace', Config::get('app_trace'))) {
  83. Debug::inject($this, $data);
  84. }
  85. if (200 == $this->code) {
  86. $cache = Request::instance()->getCache();
  87. if ($cache) {
  88. $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
  89. $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
  90. $this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
  91. Cache::set($cache[0], [$data, $this->header], $cache[1]);
  92. }
  93. }
  94. if (!headers_sent() && !empty($this->header)) {
  95. // 发送状态码
  96. http_response_code($this->code);
  97. // 发送头部信息
  98. foreach ($this->header as $name => $val) {
  99. header($name . ':' . $val);
  100. }
  101. }
  102. echo $data;
  103. if (function_exists('fastcgi_finish_request')) {
  104. // 提高页面响应
  105. fastcgi_finish_request();
  106. }
  107. // 监听response_end
  108. Hook::listen('response_end', $this);
  109. // 清空当次请求有效的数据
  110. if (!($this instanceof RedirectResponse)) {
  111. Session::flush();
  112. }
  113. }
  114. /**
  115. * 处理数据
  116. * @access protected
  117. * @param mixed $data 要处理的数据
  118. * @return mixed
  119. */
  120. protected function output($data)
  121. {
  122. return $data;
  123. }
  124. /**
  125. * 输出的参数
  126. * @access public
  127. * @param mixed $options 输出参数
  128. * @return $this
  129. */
  130. public function options($options = [])
  131. {
  132. $this->options = array_merge($this->options, $options);
  133. return $this;
  134. }
  135. /**
  136. * 输出数据设置
  137. * @access public
  138. * @param mixed $data 输出数据
  139. * @return $this
  140. */
  141. public function data($data)
  142. {
  143. $this->data = $data;
  144. return $this;
  145. }
  146. /**
  147. * 设置响应头
  148. * @access public
  149. * @param string|array $name 参数名
  150. * @param string $value 参数值
  151. * @return $this
  152. */
  153. public function header($name, $value = null)
  154. {
  155. if (is_array($name)) {
  156. $this->header = array_merge($this->header, $name);
  157. } else {
  158. $this->header[$name] = $value;
  159. }
  160. return $this;
  161. }
  162. /**
  163. * 设置页面输出内容
  164. * @param $content
  165. * @return $this
  166. */
  167. public function content($content)
  168. {
  169. if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
  170. $content,
  171. '__toString',
  172. ])
  173. ) {
  174. throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
  175. }
  176. $this->content = (string) $content;
  177. return $this;
  178. }
  179. /**
  180. * 发送HTTP状态
  181. * @param integer $code 状态码
  182. * @return $this
  183. */
  184. public function code($code)
  185. {
  186. $this->code = $code;
  187. return $this;
  188. }
  189. /**
  190. * LastModified
  191. * @param string $time
  192. * @return $this
  193. */
  194. public function lastModified($time)
  195. {
  196. $this->header['Last-Modified'] = $time;
  197. return $this;
  198. }
  199. /**
  200. * Expires
  201. * @param string $time
  202. * @return $this
  203. */
  204. public function expires($time)
  205. {
  206. $this->header['Expires'] = $time;
  207. return $this;
  208. }
  209. /**
  210. * ETag
  211. * @param string $eTag
  212. * @return $this
  213. */
  214. public function eTag($eTag)
  215. {
  216. $this->header['ETag'] = $eTag;
  217. return $this;
  218. }
  219. /**
  220. * 页面缓存控制
  221. * @param string $cache 状态码
  222. * @return $this
  223. */
  224. public function cacheControl($cache)
  225. {
  226. $this->header['Cache-control'] = $cache;
  227. return $this;
  228. }
  229. /**
  230. * 页面输出类型
  231. * @param string $contentType 输出类型
  232. * @param string $charset 输出编码
  233. * @return $this
  234. */
  235. public function contentType($contentType, $charset = 'utf-8')
  236. {
  237. $this->header['Content-Type'] = $contentType . '; charset=' . $charset;
  238. return $this;
  239. }
  240. /**
  241. * 获取头部信息
  242. * @param string $name 头部名称
  243. * @return mixed
  244. */
  245. public function getHeader($name = '')
  246. {
  247. if (!empty($name)) {
  248. return isset($this->header[$name]) ? $this->header[$name] : null;
  249. } else {
  250. return $this->header;
  251. }
  252. }
  253. /**
  254. * 获取原始数据
  255. * @return mixed
  256. */
  257. public function getData()
  258. {
  259. return $this->data;
  260. }
  261. /**
  262. * 获取输出数据
  263. * @return mixed
  264. */
  265. public function getContent()
  266. {
  267. if (null == $this->content) {
  268. $content = $this->output($this->data);
  269. if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
  270. $content,
  271. '__toString',
  272. ])
  273. ) {
  274. throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
  275. }
  276. $this->content = (string) $content;
  277. }
  278. return $this->content;
  279. }
  280. /**
  281. * 获取状态码
  282. * @return integer
  283. */
  284. public function getCode()
  285. {
  286. return $this->code;
  287. }
  288. }