response.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php namespace Laravel;
  2. class Response {
  3. /**
  4. * The content of the response.
  5. *
  6. * @var mixed
  7. */
  8. public $content;
  9. /**
  10. * The HTTP status code of the response.
  11. *
  12. * @var int
  13. */
  14. public $status;
  15. /**
  16. * The response headers.
  17. *
  18. * @var array
  19. */
  20. public $headers = array();
  21. /**
  22. * HTTP status codes.
  23. *
  24. * @var array
  25. */
  26. protected $statuses = array(
  27. 100 => 'Continue',
  28. 101 => 'Switching Protocols',
  29. 200 => 'OK',
  30. 201 => 'Created',
  31. 202 => 'Accepted',
  32. 203 => 'Non-Authoritative Information',
  33. 204 => 'No Content',
  34. 205 => 'Reset Content',
  35. 206 => 'Partial Content',
  36. 207 => 'Multi-Status',
  37. 300 => 'Multiple Choices',
  38. 301 => 'Moved Permanently',
  39. 302 => 'Found',
  40. 303 => 'See Other',
  41. 304 => 'Not Modified',
  42. 305 => 'Use Proxy',
  43. 307 => 'Temporary Redirect',
  44. 400 => 'Bad Request',
  45. 401 => 'Unauthorized',
  46. 402 => 'Payment Required',
  47. 403 => 'Forbidden',
  48. 404 => 'Not Found',
  49. 405 => 'Method Not Allowed',
  50. 406 => 'Not Acceptable',
  51. 407 => 'Proxy Authentication Required',
  52. 408 => 'Request Timeout',
  53. 409 => 'Conflict',
  54. 410 => 'Gone',
  55. 411 => 'Length Required',
  56. 412 => 'Precondition Failed',
  57. 413 => 'Request Entity Too Large',
  58. 414 => 'Request-URI Too Long',
  59. 415 => 'Unsupported Media Type',
  60. 416 => 'Requested Range Not Satisfiable',
  61. 417 => 'Expectation Failed',
  62. 422 => 'Unprocessable Entity',
  63. 423 => 'Locked',
  64. 424 => 'Failed Dependency',
  65. 500 => 'Internal Server Error',
  66. 501 => 'Not Implemented',
  67. 502 => 'Bad Gateway',
  68. 503 => 'Service Unavailable',
  69. 504 => 'Gateway Timeout',
  70. 505 => 'HTTP Version Not Supported',
  71. 507 => 'Insufficient Storage',
  72. 509 => 'Bandwidth Limit Exceeded'
  73. );
  74. /**
  75. * Create a new response instance.
  76. *
  77. * @param mixed $content
  78. * @param int $status
  79. * @param array $headers
  80. * @return void
  81. */
  82. public function __construct($content, $status = 200, $headers = array())
  83. {
  84. $this->status = $status;
  85. $this->content = $content;
  86. $this->headers = $headers;
  87. }
  88. /**
  89. * Create a new response instance.
  90. *
  91. * <code>
  92. * // Create a response instance with string content
  93. * return Response::make(json_encode($user));
  94. *
  95. * // Create a response instance with a given status
  96. * return Response::make('Not Found', 404);
  97. *
  98. * // Create a response with some custom headers
  99. * return Respone::make(json_encode($user), 200, array('content-type' => 'application/json'));
  100. * </code>
  101. *
  102. * @param mixed $content
  103. * @param int $status
  104. * @param array $headers
  105. * @return Response
  106. */
  107. public static function make($content, $status = 200, $headers = array())
  108. {
  109. return new static($content, $status, $headers);
  110. }
  111. /**
  112. * Create a new response instance containing a view.
  113. *
  114. * <code>
  115. * // Create a response instance with a view
  116. * return Response::view('home.index');
  117. *
  118. * // Create a response instance with a view and data
  119. * return Response::view('home.index', array('name' => 'Taylor'));
  120. * </code>
  121. *
  122. * @param string $view
  123. * @param array $data
  124. * @return Response
  125. */
  126. public static function view($view, $data = array())
  127. {
  128. return new static(View::make($view, $data));
  129. }
  130. /**
  131. * Create a new response instance containing a named view.
  132. *
  133. * <code>
  134. * // Create a response with the "layout" named view
  135. * return Response::of('layout');
  136. *
  137. * // Create a response with the "layout" named view and data
  138. * return Response::of('layout', array('name' => 'Taylor'));
  139. * </code>
  140. *
  141. * @param string $name
  142. * @param array $data
  143. * @return Response
  144. */
  145. public static function of($name, $data = array())
  146. {
  147. return new static(View::of($name, $data));
  148. }
  149. /**
  150. * Create a new error response instance.
  151. *
  152. * The response status code will be set using the specified code.
  153. *
  154. * Note: The specified error code should correspond to a view in your views/error directory.
  155. *
  156. * <code>
  157. * // Create a 404 response
  158. * return Response::error('404');
  159. *
  160. * // Create a 404 response with data
  161. * return Response::error('404', array('message' => 'Not Found'));
  162. * </code>
  163. *
  164. * @param int $code
  165. * @param array $data
  166. * @return Response
  167. */
  168. public static function error($code, $data = array())
  169. {
  170. return new static(View::make('error/'.$code, $data), $code);
  171. }
  172. /**
  173. * Create a new download response instance.
  174. *
  175. * <code>
  176. * // Create a download response to a given file
  177. * return Response::download('path/to/file.jpg');
  178. *
  179. * // Create a download response with a given file name
  180. * return Response::download('path/to/file.jpg', 'your_file.jpg');
  181. * </code>
  182. *
  183. * @param string $path
  184. * @param string $name
  185. * @param array $headers
  186. * @return Response
  187. */
  188. public static function download($path, $name = null, $headers = array())
  189. {
  190. if (is_null($name)) $name = basename($path);
  191. $headers = array_merge(array(
  192. 'Content-Description' => 'File Transfer',
  193. 'Content-Type' => File::mime(File::extension($path)),
  194. 'Content-Disposition' => 'attachment; filename="'.$name.'"',
  195. 'Content-Transfer-Encoding' => 'binary',
  196. 'Expires' => 0,
  197. 'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
  198. 'Pragma' => 'public',
  199. 'Content-Length' => File::size($path),
  200. ), $headers);
  201. return new static(File::get($path), 200, $headers);
  202. }
  203. /**
  204. * Get the evaluated string contents of the response.
  205. *
  206. * @return string
  207. */
  208. public function render()
  209. {
  210. return ($this->content instanceof View) ? $this->content->render() : (string) $this->content;
  211. }
  212. /**
  213. * Send the response to the browser.
  214. *
  215. * All of the response headers will be sent to the browser first, followed by
  216. * the content of the response instance, which will be evaluated and rendered
  217. * by the render method.
  218. *
  219. * @return void
  220. */
  221. public function send()
  222. {
  223. if ( ! headers_sent()) $this->headers();
  224. echo $this->render();
  225. }
  226. /**
  227. * Send all of the response headers to the browser.
  228. *
  229. * The developer may set response headers using the "header" method. All of
  230. * the headers set by the developer will be automatically sent to the browser
  231. * when the response is sent via the "send" method. There is no need to call
  232. * this method before calling the "send" method.
  233. *
  234. * The protocol and status header will be set automatically, as well as the
  235. * content-type and charset, unless those headers have been set explicitly.
  236. * The content-type charset used will be the application encoding.
  237. *
  238. * @return void
  239. */
  240. public function headers()
  241. {
  242. if ( ! isset($this->headers['Content-Type']))
  243. {
  244. $encoding = Config::$items['application']['encoding'];
  245. $this->header('Content-Type', "text/html; charset={$encoding}");
  246. }
  247. header(Request::protocol().' '.$this->status.' '.$this->statuses[$this->status]);
  248. foreach ($this->headers as $name => $value)
  249. {
  250. header($name.': '.$value, true);
  251. }
  252. }
  253. /**
  254. * Add a header to the response.
  255. *
  256. * <code>
  257. * // Add a header to a response instance
  258. * return Response::make('foo')->header('content-type', 'application/json');
  259. * </code>
  260. *
  261. * @param string $name
  262. * @param string $value
  263. * @return Response
  264. */
  265. public function header($name, $value)
  266. {
  267. $this->headers[$name] = $value;
  268. return $this;
  269. }
  270. /**
  271. * Set the response status code.
  272. *
  273. * @param int $status
  274. * @return Response
  275. */
  276. public function status($status)
  277. {
  278. $this->status = $status;
  279. return $this;
  280. }
  281. /**
  282. * Magic Method for handling the dynamic creation of Responses containing named views.
  283. *
  284. * <code>
  285. * // Create a response instance with the "layout" named view
  286. * return Response::of_layout();
  287. *
  288. * // Create a response instance with a named view and data
  289. * return Response::of_layout(array('name' => 'Taylor'));
  290. * </code>
  291. */
  292. public static function __callStatic($method, $parameters)
  293. {
  294. if (strpos($method, 'of_') === 0)
  295. {
  296. return static::with(substr($method, 3), Arr::get($parameters, 0, array()));
  297. }
  298. }
  299. }