Yii2での例外のキャッチと処理

Yii2では、デフォルトで、すべての例外が処理されます。これには特別なハンドラーが責任を負います。 要求の処理中に悪い状況が発生した場合(たとえば、クライアントから誤ったデータが送信された場合)、例外がスローされます。 ハンドラーはヒューマノイド応答を形成します。



興味深いことに、この場合、「警告:キャッチされなかった例外」エラーはエラーログに表示されません。 すべての例外がフレームワークによってキャッチされているという印象を受けるかもしれません。 しかし、これはそうではありません。 しばらく前に、プロジェクトに監視ツール(この場合はNew Relic)をインストールしました。このツールは、スローされたすべての例外に関する情報をエラーで表示します(「警告:キャッチされなかった例外」と同様)。 これには何か関係がありました。



以下に、最終的に選択した例外処理スキームについて説明します。 他の誰かが重宝する可能性があります。





処理された例外がキャッチされないと見なされる理由



Yii2では、エラーハンドラーはset_exception_handler()関数によって設定されます。 この関数は、キャッチされない例外のハンドラーを定義します。 同時に、例外は処理されますが、まだキャッチされていません。 例外をキャッチするには、それらを明示的にキャッチして、try-catchで呼び出しをラップする必要があります。 各コントローラーの各アクションで、私は本当にこれをしたくありませんでした。 単一の傍受ポイントがあると便利です。



Yii2では、判明しているように、既製のオプションがあります。例外yii \ base \ ExitException (またはその子孫)をスローすると、そのような例外はフレームワークによって処理されます。 明確にするために、これはApplication :: run()でどのように行われるかです:



public function run() { try { $this->state = self::STATE_BEFORE_REQUEST; $this->trigger(self::EVENT_BEFORE_REQUEST); $this->state = self::STATE_HANDLING_REQUEST; $response = $this->handleRequest($this->getRequest()); $this->state = self::STATE_AFTER_REQUEST; $this->trigger(self::EVENT_AFTER_REQUEST); $this->state = self::STATE_SENDING_RESPONSE; $response->send(); $this->state = self::STATE_END; return $response->exitStatus; } catch (ExitException $e) { $this->end($e->statusCode, isset($response) ? $response : null); return $e->statusCode; } }
      
      







「良い」および「悪い」例外



2つのケースでリクエストの処理を完了するために、例外をスローすると便利です。

  1. 何も壊れていない場合は、ちょっとした誤解があります。クライアントに対するWebベースのリクエストが急増したか、それほど重要ではないリクエストデータはありませんでした。
  2. 何かが壊れている場合。


前者の場合、イベントをエラーとして記録する必要はなく、対処する必要はありません。

2番目のケースでは、何が起こったのかを知り、問題に対処するために、問題を記録する必要があります。



最初のケースでは、yii \ base \ ExitExceptionから継承したクラスを作成しました。 スクリプトの結果が空白ページではないように、例外で直接応答が生成されます。



 <?php namespace app\components; use yii; use yii\base\ExitException; /** * ,       yii\base\Application */ class GoodException extends ExitException { /** *  * @param string $name  (    ) * @param string $message     * @param int $code   * @param int $status   * @param \Exception $previous   */ public function __construct($name, $message = null, $code = 0, $status = 500, \Exception $previous = null) { #   $view = yii::$app->getView(); $response = yii::$app->getResponse(); $response->data = $view->renderFile('@app/views/exception.php', [ 'name' => $name, 'message' => $message, ]); #    (-  500-) $response->setStatusCode($status); parent::__construct($status, $message, $code, $previous); } }
      
      





また、別のビューを作成しました。

 <?php /* @var $this yii\web\View */ /* @var $name string */ /* @var $message string */ /* @var $exception Exception */ use yii\helpers\Html; $this->title = $name; ?> <?php $this->beginContent('@app/views/layouts/main.php'); ?> <div class="site-error"> <h1><?= Html::encode($this->title) ?></h1> <div class="alert alert-danger"> <?= nl2br(Html::encode($message)) ?> </div> <p> The above error occurred while the Web server was processing your request. </p> <p> Please contact us if you think this is a server error. Thank you. </p> </div> <?php $this->endContent(); ?>
      
      







合計



したがって、「文化的」例外をスローするには、次のように記述します。

 #  ,    throw new GoodException('', '   ');
      
      





そのような例外がキャッチされ、きちんとした応答がクライアントに返されます。 このようなイベントはエラーログに記録されません。



他のすべての例外は、明示的にキャッチしない限り、キャッチされません。 そして、それらはエラーに陥ります。 つまり 2番目の場合、次のように記述できます

 throw new yii\base\ErrorException('  ');
      
      






All Articles