Response.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 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\Redirect as RedirectResponse;
  13. class Response
  14. {
  15. /**
  16. * 原始数据
  17. * @var mixed
  18. */
  19. protected $data;
  20. /**
  21. * 应用对象实例
  22. * @var App
  23. */
  24. protected $app;
  25. /**
  26. * 当前contentType
  27. * @var string
  28. */
  29. protected $contentType = 'text/html';
  30. /**
  31. * 字符集
  32. * @var string
  33. */
  34. protected $charset = 'utf-8';
  35. /**
  36. * 状态码
  37. * @var integer
  38. */
  39. protected $code = 200;
  40. /**
  41. * 是否允许请求缓存
  42. * @var bool
  43. */
  44. protected $allowCache = true;
  45. /**
  46. * 输出参数
  47. * @var array
  48. */
  49. protected $options = [];
  50. /**
  51. * header参数
  52. * @var array
  53. */
  54. protected $header = [];
  55. /**
  56. * 输出内容
  57. * @var string
  58. */
  59. protected $content = null;
  60. /**
  61. * 架构函数
  62. * @access public
  63. * @param mixed $data 输出数据
  64. * @param int $code
  65. * @param array $header
  66. * @param array $options 输出参数
  67. */
  68. public function __construct($data = '', $code = 200, array $header = [], $options = [])
  69. {
  70. $this->data($data);
  71. if (!empty($options)) {
  72. $this->options = array_merge($this->options, $options);
  73. }
  74. $this->contentType($this->contentType, $this->charset);
  75. $this->code = $code;
  76. $this->app = Container::get('app');
  77. $this->header = array_merge($this->header, $header);
  78. }
  79. /**
  80. * 创建Response对象
  81. * @access public
  82. * @param mixed $data 输出数据
  83. * @param string $type 输出类型
  84. * @param int $code
  85. * @param array $header
  86. * @param array $options 输出参数
  87. * @return Response
  88. */
  89. public static function create($data = '', $type = '', $code = 200, array $header = [], $options = [])
  90. {
  91. $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst(strtolower($type));
  92. if (class_exists($class)) {
  93. return new $class($data, $code, $header, $options);
  94. }
  95. return new static($data, $code, $header, $options);
  96. }
  97. /**
  98. * 发送数据到客户端
  99. * @access public
  100. * @return void
  101. * @throws \InvalidArgumentException
  102. */
  103. public function send()
  104. {
  105. // 监听response_send
  106. $this->app['hook']->listen('response_send', $this);
  107. // 处理输出数据
  108. $data = $this->getContent();
  109. // Trace调试注入
  110. if ('cli' != PHP_SAPI && $this->app['env']->get('app_trace', $this->app->config('app.app_trace'))) {
  111. $this->app['debug']->inject($this, $data);
  112. }
  113. if (200 == $this->code && $this->allowCache) {
  114. $cache = $this->app['request']->getCache();
  115. if ($cache) {
  116. $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
  117. $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
  118. $this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
  119. $this->app['cache']->tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]);
  120. }
  121. }
  122. if (!headers_sent() && !empty($this->header)) {
  123. // 发送状态码
  124. http_response_code($this->code);
  125. // 发送头部信息
  126. foreach ($this->header as $name => $val) {
  127. header($name . (!is_null($val) ? ':' . $val : ''));
  128. }
  129. }
  130. $this->sendData($data);
  131. if (function_exists('fastcgi_finish_request')) {
  132. // 提高页面响应
  133. fastcgi_finish_request();
  134. }
  135. // 监听response_end
  136. $this->app['hook']->listen('response_end', $this);
  137. // 清空当次请求有效的数据
  138. if (!($this instanceof RedirectResponse)) {
  139. $this->app['session']->flush();
  140. }
  141. }
  142. /**
  143. * 处理数据
  144. * @access protected
  145. * @param mixed $data 要处理的数据
  146. * @return mixed
  147. */
  148. protected function output($data)
  149. {
  150. return $data;
  151. }
  152. /**
  153. * 输出数据
  154. * @access protected
  155. * @param string $data 要处理的数据
  156. * @return void
  157. */
  158. protected function sendData($data)
  159. {
  160. echo $data;
  161. }
  162. /**
  163. * 输出的参数
  164. * @access public
  165. * @param mixed $options 输出参数
  166. * @return $this
  167. */
  168. public function options($options = [])
  169. {
  170. $this->options = array_merge($this->options, $options);
  171. return $this;
  172. }
  173. /**
  174. * 输出数据设置
  175. * @access public
  176. * @param mixed $data 输出数据
  177. * @return $this
  178. */
  179. public function data($data)
  180. {
  181. $this->data = $data;
  182. return $this;
  183. }
  184. /**
  185. * 是否允许请求缓存
  186. * @access public
  187. * @param bool $cache 允许请求缓存
  188. * @return $this
  189. */
  190. public function allowCache($cache)
  191. {
  192. $this->allowCache = $cache;
  193. return $this;
  194. }
  195. /**
  196. * 设置响应头
  197. * @access public
  198. * @param string|array $name 参数名
  199. * @param string $value 参数值
  200. * @return $this
  201. */
  202. public function header($name, $value = null)
  203. {
  204. if (is_array($name)) {
  205. $this->header = array_merge($this->header, $name);
  206. } else {
  207. $this->header[$name] = $value;
  208. }
  209. return $this;
  210. }
  211. /**
  212. * 设置页面输出内容
  213. * @access public
  214. * @param mixed $content
  215. * @return $this
  216. */
  217. public function content($content)
  218. {
  219. if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
  220. $content,
  221. '__toString',
  222. ])
  223. ) {
  224. throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
  225. }
  226. $this->content = (string) $content;
  227. return $this;
  228. }
  229. /**
  230. * 发送HTTP状态
  231. * @access public
  232. * @param integer $code 状态码
  233. * @return $this
  234. */
  235. public function code($code)
  236. {
  237. $this->code = $code;
  238. return $this;
  239. }
  240. /**
  241. * LastModified
  242. * @access public
  243. * @param string $time
  244. * @return $this
  245. */
  246. public function lastModified($time)
  247. {
  248. $this->header['Last-Modified'] = $time;
  249. return $this;
  250. }
  251. /**
  252. * Expires
  253. * @access public
  254. * @param string $time
  255. * @return $this
  256. */
  257. public function expires($time)
  258. {
  259. $this->header['Expires'] = $time;
  260. return $this;
  261. }
  262. /**
  263. * ETag
  264. * @access public
  265. * @param string $eTag
  266. * @return $this
  267. */
  268. public function eTag($eTag)
  269. {
  270. $this->header['ETag'] = $eTag;
  271. return $this;
  272. }
  273. /**
  274. * 页面缓存控制
  275. * @access public
  276. * @param string $cache 缓存设置
  277. * @return $this
  278. */
  279. public function cacheControl($cache)
  280. {
  281. $this->header['Cache-control'] = $cache;
  282. return $this;
  283. }
  284. /**
  285. * 设置页面不做任何缓存
  286. * @access public
  287. * @return $this
  288. */
  289. public function noCache()
  290. {
  291. $this->header['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0';
  292. $this->header['Pragma'] = 'no-cache';
  293. return $this;
  294. }
  295. /**
  296. * 页面输出类型
  297. * @access public
  298. * @param string $contentType 输出类型
  299. * @param string $charset 输出编码
  300. * @return $this
  301. */
  302. public function contentType($contentType, $charset = 'utf-8')
  303. {
  304. $this->header['Content-Type'] = $contentType . '; charset=' . $charset;
  305. return $this;
  306. }
  307. /**
  308. * 获取头部信息
  309. * @access public
  310. * @param string $name 头部名称
  311. * @return mixed
  312. */
  313. public function getHeader($name = '')
  314. {
  315. if (!empty($name)) {
  316. return isset($this->header[$name]) ? $this->header[$name] : null;
  317. }
  318. return $this->header;
  319. }
  320. /**
  321. * 获取原始数据
  322. * @access public
  323. * @return mixed
  324. */
  325. public function getData()
  326. {
  327. return $this->data;
  328. }
  329. /**
  330. * 获取输出数据
  331. * @access public
  332. * @return mixed
  333. */
  334. public function getContent()
  335. {
  336. if (null == $this->content) {
  337. $content = $this->output($this->data);
  338. if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
  339. $content,
  340. '__toString',
  341. ])
  342. ) {
  343. throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content)));
  344. }
  345. $this->content = (string) $content;
  346. }
  347. return $this->content;
  348. }
  349. /**
  350. * 获取状态码
  351. * @access public
  352. * @return integer
  353. */
  354. public function getCode()
  355. {
  356. return $this->code;
  357. }
  358. public function __debugInfo()
  359. {
  360. $data = get_object_vars($this);
  361. unset($data['app']);
  362. return $data;
  363. }
  364. }