例外処理の正しい方法は何ですか?


20

Joomlaコアでは、次のような呼び出しがまだ多くあります。

    // Check for errors.
    if (count($errors = $this->get('Errors')))
    {
        JError::raiseError(500, implode("\n", $errors));
        return false;
    }

しかし、JErrorはPlatformリリース12.1から非推奨になりました。したがって、標準のPHP例外をどのように使用する必要があります。


1
違いは、JErrorからPHPエラーに移行することは、残念なことにワンクリックプロセスではありません。したがって、例外が発生することが確実な場合は、以下の回答のようにtry / catchステートメントを実行してください。JErrorが発生することが確実な場合は、上記と同様のコードを実行する必要があります。)
ジョージウィルソン14

回答:


17

@DmitryRekunが言ったように、良い議論がここにあります。このすべてで考慮すべき重要な点は、どのタイプのエラーがあるかです。

エラーには2つのタイプがあります。

  1. 回復可能
  2. 回復不能。

私は次のように要約する傾向があります:

Can I still show the page that was requested, even though this error occurred?
  • はい?-回復可能
  • いや?-回復不能

今、私たちは何を扱っているかを知っています。あなたは何をするべきか?

エラーが回復不能な場合は、要求されたページに進むのではなく、エラーページリダイレクトします。次のように簡単です。

throw new Exception(JText::_('COM_MYCOMP_ERROR_MESSAGE_NOT_FOUND'), 404);

Exceptionは、メッセージとコードの2つのパラメーターを取るクラスです。シナリオに適合する場合は、HTTP応答コードを使用することをお勧めします。

エラーが回復可能な場合、リクエストしたページを表示したまま、エンドユーザーにメッセージを表示したいだけです。これは通常、アプリケーションのメッセージを「エンキュー」する必要があることを意味します。

JFactory::getApplication()->enqueueMessage($error, 'error');

enqueueMessageエラーメッセージとメッセージタイプの2つのパラメーターを取ります。詳細はこちら(下部)。


少なくとも私にとってはかなり頻繁に発生する3番目の状況もあります。Joomlaは、さまざまなエラー(データベースクエリエラーなど)に対して例外をスローします。これは、Joomlaがこのエラーは回復不能であると考えていることを意味します。ただし、とにかく続行したい場合があります。(たとえば、拡張機能の更新時にテーブルを変更している場合、ALTERクエリを実行するだけで、テーブルが以前に変更されている場合は例外がスローされます。)

その場合、try ... catchセクションで例外をスローする可能性のあるコードをラップする必要があります。

try {
    // exception generating code
    throw new Exception('Normally you would have other code that calls a class that throws the exception', 500);
} catch (Exception $e) {
    $msg = $e->getMessage(); // Returns "Normally you would have other code...
    $code = $e->getCode(); // Returns '500';
    JFactory::getApplication()->enqueueMessage($msg, 'error'); // commonly to still display that error
}

あなたがしていることは、回復不可能なエラーを「キャッチ」し、システムに強制的に回復させ、要求されたページを表示し続けることに注意してください。


これをすべて追加すると、ケースは回復不能なエラーになるはずです。(後で「falseを返す」ので、これを知っています。そのため、おそらく続行する予定はなく、機能をあきらめます。)

したがって、これを次のように書き換えます。

// Check for errors.
if (count($errors = $this->get('Errors')))
{
    throw new Exception(implode("\n", $errors), 500);
    return false; // you can remove this too, technically since the exception will take you out of this function.
}

いい答えだ!しかし$this->get('Errors')、これも非推奨であるため、私は依存しません。
ドミトリーRekun 14

失敗したアサーション、つまり内部エラーに関するコメントはありますか?アサーションの失敗時にプログラムをすぐに停止させたい-これを行うJoomla固有の方法はありますか?場合は現時点で私がアサートハンドラを登録しJDEBUGていますtrue
オルレハーステット

12

エラーの管理方法は次のとおりです。

ビューまたはコントローラー

try
{
    $this->item = $this->get('Item');
}
catch (Exception $e)
{
    if ($e->getCode() == 404)
    {
        // Not found
        throw new Exception($e->getMessage(), 404);
    }

    // Generic errors
    JFactory::getApplication()->enqueueMessage(JText::_('COM_MYCOMP_ERROR_OCCURRED'), 'error');
}

たとえば、モデルから404コードを取得した場合(たとえば):

if (empty($data))
{
    throw new Exception(JText::_('COM_MYCOMP_ERROR_MESSAGE_NOT_FOUND'), 404);
}

次に、ビューまたはコントローラーでキャッチし、Joomlaが処理して404ページを表示するもう1つの例外をスローします。その他の場合、一般的なエラーメッセージをユーザーに表示するだけです。

また、エラー処理に関するこの興味深い議論を読んでください


4

このようなコードブロックのほとんどenqueueMessageは、実際にはエラーに作用せず、単にJErrorそれらを出力するために使用されるため、単純に置き換えることができます。

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.