Symfony 2で例外を使用する

少し前まで、Symfonyで例外を使用するというトピックについて同僚と話しました。 インターネット上の情報の概要。 フレームワークのウェブサイトは、ドキュメントのトピックがあまり深く開示されておらず、多くのシステム機能が舞台裏に残っていることを示しました。 この投稿では、このギャップを少し埋めて、フレームワークのコードを掘り下げて見つけたものを共有することにしました。



例外キャッチの仕組み


ツールを正しく使用するには、その機能を理解することが重要です。 Webを介した一般的なリクエストの場合の例外処理については、 こちらをご覧ください 。 非常に便利なHttpExceptionInterfaceがそこに記載されています。これについては以下で説明します。



この投稿には、symfony 2.xコードとそのコンポーネントを掘り下げた人向けの啓示はありません。 このような読者は、この投稿を安全にスキップできます。





誰が例外を「キャッチ」するか


開発者が自分で例外をキャッチしなかった場合、 HttpKernelそれらをキャッチします 。つまり、handleExceptionメソッドです。 実際、このメソッドはディスパッチャを介してイベントをトリガーするだけで、すべての関連サービスに緊急事態を通知します。 次に、フレームワークがいくつかのタイプの例外をどのように処理するかを見ていきます。



コンソールコマンドで例外が発生するとどうなりますか? 同じことについて。 Applicationクラスで例外がキャッチされた後、ConsoleEvents :: EXCEPTIONおよびConsoleEvents :: TERMINATEの2つのイベントがディスパッチされます。 処理の原則は、Web上と同じです。 例外はイベントを発生させ、ディスパッチャはそれらを送信し、リスナーは自分の仕事をします。 たとえば、コマンドの実行中にエラーが発生した場合にトランザクションをロールバックし、エラー処理とメインコマンドコードを混在させることはできません。



組み込みの例外ハンドラー


デフォルトでは、Symfony 2はセキュリティ例外(AuthenticationException、AccessDeniedException、LogoutException)およびHttpExceptionInterfaceを実装する例外を処理できます。



システム例外の詳細をご覧ください。


HttpExceptionInterface-compatible-例外により、http応答とそのヘッダーのステータスコードを調整できます。これは、例外的な状況でエラーコードをリダイレクトまたは明確にするのに役立ちます。



興味深いことに、この例外の処理はEventDispatcherを介して行われませんが、HttpKernelで直接保護されます...



$response = $event->getResponse(); // the developer asked for a specific status code if ($response->headers->has('X-Status-Code')) { $response->setStatusCode($response->headers->get('X-Status-Code')); $response->headers->remove('X-Status-Code'); } elseif (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { // ensure that we actually have an error response if ($e instanceof HttpExceptionInterface) { // keep the HTTP status code and headers $response->setStatusCode($e->getStatusCode()); $response->headers->add($e->getHeaders()); } else { $response->setStatusCode(500); } }
      
      







...このように、このような例外をスローすると、500コードの代わりに402のようなものをクライアントに転送できます。これはさまざまなAPIを書くときに便利です、またコードのほぼどこからでもリダイレクトを開始できます、これは確かに便利ですしかし、常に良いとは限りません。 TwigExtensionやモデルのビジネスロジックなどから、リダイレクトの開始を誰もが理解することはまずありません。 このタイプの例外は、サーバーの応答のコンテンツには影響せず、ヘッダーのみに影響することが重要です。



また、フレームワークコードには、3種類の例外を処理できるセキュリティ例外ハンドラがあります。



AuthenticationException -SecurityBundleおよびSecurity Componentで処理されるさまざまなタイプの他の多くの例外の親。 登録されたユーザーのみが使用できるアクションが、ログインしていないユーザーによって試行された場合、この例外をスローします。



例外ハンドラは、認証を開始しようとすることでそれに応答します。 最も一般的なケースでは、リクエストされたページの代わりに、ユーザーに認証フォームを提供します。

プロジェクトでセキュリティレイヤーが正しく構成されている場合、この例外を自分自身またはその子孫でスローする必要はほとんどありません。 SecurityBundleは独自に対処し、だれも出入りさせないようにします。



AccessDeniedException-この例外はAuthenticationExceptionと似ていますが、ユーザー権限が要件を満たしていない場合に発生するはずです。 たとえば、権限のないユーザーが管理パネルにアクセスしようとしています。 例外が発生した場合、ユーザーには、権限の欠如に関するメッセージが記載されたページが表示されます(著者は、彼がネイティブではないことを望んでいます-シンフォニー)。 また、この例外を使用して、たとえば、ユーザーが記憶Cookieを介して許可されていて、そのユーザーであることをもう一度確認したい場合、再許可のためにユーザーを送信できます。

前の例外と同様に、自分でそれを捨てる必要はほとんどありません。シンフォニーを委任する方が良いですが、それでも、そのようなアクションが開発者にとって有用な場合がより一般的であるように思われます。



LogoutExceptionは、ログアウト中の例外です。 たとえば、間違ったフォームトークンやセッションの問題。 この例外のハンドラーは何もせず、ログに書き込みます。



HttpExceptionとは異なり、セキュリティ例外は標準的なリスナーによって処理され、フレームワークのアーキテクチャに有機的に適合します。

ドキュメントのヒントにもかかわらず、標準アセンブリ2.5にはシステム例外ハンドラが見つかりませんでした。



結論の代わりに


開発者は、いつものように、多くのことができます。 独自のタイプの例外とそれらのリスナーを追加することで、ほぼすべての望ましい動作を実現できます。 たとえば、ビジネスロジックのエラーは、特定の環境では単純にログに書き込まれ、別の環境では単純にログパネルまたはオブジェクトエディターにユーザーを転送して、その欠点を排除することができます。

正直に言うと、この著者はまだ練習をしていませんが、これが必要なタスクを想像できます。



開発者がすべきでないことを正確に言うことができます。 既存のフレームワークハンドラーの機能を複製せず、その機能を無視しないでください。 書き込み中に1つまたは別のコードの実行を中断するだけでよい場合でも、さまざまな例外に対して個別のクラスを拒否しないでください。 その後、論理的に分離された例外により、複雑な問題を簡単に解決できます。



All Articles