ErrorAction.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\web;
  8. use Yii;
  9. use yii\base\Action;
  10. use yii\base\Exception;
  11. use yii\base\UserException;
  12. /**
  13. * ErrorAction displays application errors using a specified view.
  14. *
  15. * To use ErrorAction, you need to do the following steps:
  16. *
  17. * First, declare an action of ErrorAction type in the `actions()` method of your `SiteController`
  18. * class (or whatever controller you prefer), like the following:
  19. *
  20. * ```php
  21. * public function actions()
  22. * {
  23. * return [
  24. * 'error' => ['class' => 'yii\web\ErrorAction'],
  25. * ];
  26. * }
  27. * ```
  28. *
  29. * Then, create a view file for this action. If the route of your error action is `site/error`, then
  30. * the view file should be `views/site/error.php`. In this view file, the following variables are available:
  31. *
  32. * - `$name`: the error name
  33. * - `$message`: the error message
  34. * - `$exception`: the exception being handled
  35. *
  36. * Finally, configure the "errorHandler" application component as follows,
  37. *
  38. * ```php
  39. * 'errorHandler' => [
  40. * 'errorAction' => 'site/error',
  41. * ]
  42. * ```
  43. *
  44. * @author Qiang Xue <qiang.xue@gmail.com>
  45. * @author Dmitry Naumenko <d.naumenko.a@gmail.com>
  46. * @since 2.0
  47. */
  48. class ErrorAction extends Action
  49. {
  50. /**
  51. * @var string the view file to be rendered. If not set, it will take the value of [[id]].
  52. * That means, if you name the action as "error" in "SiteController", then the view name
  53. * would be "error", and the corresponding view file would be "views/site/error.php".
  54. */
  55. public $view;
  56. /**
  57. * @var string the name of the error when the exception name cannot be determined.
  58. * Defaults to "Error".
  59. */
  60. public $defaultName;
  61. /**
  62. * @var string the message to be displayed when the exception message contains sensitive information.
  63. * Defaults to "An internal server error occurred.".
  64. */
  65. public $defaultMessage;
  66. /**
  67. * @var \Exception the exception object, normally is filled on [[init()]] method call.
  68. * @see [[findException()]] to know default way of obtaining exception.
  69. * @since 2.0.11
  70. */
  71. protected $exception;
  72. /**
  73. * {@inheritdoc}
  74. */
  75. public function init()
  76. {
  77. $this->exception = $this->findException();
  78. if ($this->defaultMessage === null) {
  79. $this->defaultMessage = Yii::t('yii', 'An internal server error occurred.');
  80. }
  81. if ($this->defaultName === null) {
  82. $this->defaultName = Yii::t('yii', 'Error');
  83. }
  84. }
  85. /**
  86. * Runs the action.
  87. *
  88. * @return string result content
  89. */
  90. public function run()
  91. {
  92. Yii::$app->getResponse()->setStatusCodeByException($this->exception);
  93. if (Yii::$app->getRequest()->getIsAjax()) {
  94. return $this->renderAjaxResponse();
  95. }
  96. return $this->renderHtmlResponse();
  97. }
  98. /**
  99. * Builds string that represents the exception.
  100. * Normally used to generate a response to AJAX request.
  101. * @return string
  102. * @since 2.0.11
  103. */
  104. protected function renderAjaxResponse()
  105. {
  106. return $this->getExceptionName() . ': ' . $this->getExceptionMessage();
  107. }
  108. /**
  109. * Renders a view that represents the exception.
  110. * @return string
  111. * @since 2.0.11
  112. */
  113. protected function renderHtmlResponse()
  114. {
  115. return $this->controller->render($this->view ?: $this->id, $this->getViewRenderParams());
  116. }
  117. /**
  118. * Builds array of parameters that will be passed to the view.
  119. * @return array
  120. * @since 2.0.11
  121. */
  122. protected function getViewRenderParams()
  123. {
  124. return [
  125. 'name' => $this->getExceptionName(),
  126. 'message' => $this->getExceptionMessage(),
  127. 'exception' => $this->exception,
  128. ];
  129. }
  130. /**
  131. * Gets exception from the [[yii\web\ErrorHandler|ErrorHandler]] component.
  132. * In case there is no exception in the component, treat as the action has been invoked
  133. * not from error handler, but by direct route, so '404 Not Found' error will be displayed.
  134. * @return \Exception
  135. * @since 2.0.11
  136. */
  137. protected function findException()
  138. {
  139. if (($exception = Yii::$app->getErrorHandler()->exception) === null) {
  140. $exception = new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
  141. }
  142. return $exception;
  143. }
  144. /**
  145. * Gets the code from the [[exception]].
  146. * @return mixed
  147. * @since 2.0.11
  148. */
  149. protected function getExceptionCode()
  150. {
  151. if ($this->exception instanceof HttpException) {
  152. return $this->exception->statusCode;
  153. }
  154. return $this->exception->getCode();
  155. }
  156. /**
  157. * Returns the exception name, followed by the code (if present).
  158. *
  159. * @return string
  160. * @since 2.0.11
  161. */
  162. protected function getExceptionName()
  163. {
  164. if ($this->exception instanceof Exception) {
  165. $name = $this->exception->getName();
  166. } else {
  167. $name = $this->defaultName;
  168. }
  169. if ($code = $this->getExceptionCode()) {
  170. $name .= " (#$code)";
  171. }
  172. return $name;
  173. }
  174. /**
  175. * Returns the [[exception]] message for [[yii\base\UserException]] only.
  176. * For other cases [[defaultMessage]] will be returned.
  177. * @return string
  178. * @since 2.0.11
  179. */
  180. protected function getExceptionMessage()
  181. {
  182. if ($this->exception instanceof UserException) {
  183. return $this->exception->getMessage();
  184. }
  185. return $this->defaultMessage;
  186. }
  187. }