1

CodeIgniterを使用してRESTfulAPIをホストしていますが、予期されたステータスコードを返さないAPI応答をキャプチャしたいと思います。これはおそらく例で最も簡単に説明できます。一般的に、私のコードは次のようになります。

function post_comment()
{
     $comment = $_POST['comment'];
     $result = do_something_with_comment($comment);

     if ($result === true)
     {
         return_json_response(200, 'OK!');
     }
     else
     {
         return_json_response(400, 'Something terrible happened...');
     }
}

200または400のいずれかを返すことは完全に有効です。私の問題は、do_something_with_comment()に致命的なエラーが発生した場合、またはdo_something_with_comment()内に印刷デバッグを残した場合にエラーをキャプチャする方法です。前者の場合、return_json_response()に到達することはありません。後者の場合、私はそれに到達しますが、画面のデバッグはJSON応答を破壊します。

予期しない出力または終了をキャプチャするために、これを囲む汎用ラッパーを作成する方法はありますか?

4

2 に答える 2

2

一般的に、次のことができます。

可能な限り例外/例外処理を使用する

PHPエラーを例外に変換するカスタムエラーハンドラーを登録します。たとえば、これをconfig/config.phpの先頭に配置します。

function my_error_handler($errno, $errstr, $errfile, $errline)
{
    if (!(error_reporting() & $errno))
    {
        // This error code is not included in error_reporting
        return;
    }
    log_message('error', "$errstr @$errfile::$errline($errno)" );
    throw new ErrorException( $errstr, $errno, 0, $errfile, $errline );
}
set_error_handler("my_error_handler");

キャッチされなかった例外ハンドラーを登録し、config/config.phpにこのようなものを入れます

function my_exception_handler($exception)
{
    echo '<pre>';
    print_r($exception);
    echo '</pre>';
    header( "HTTP/1.0 500 Internal Server Error" );
}
set_exception_handler("my_exception_handler");

編集

終了ハンドラーを設定します。

function my_fatal_handler()
{
    $errfile = "unknown file";
    $errstr  = "Fatal error";
    $errno   = E_CORE_ERROR;
    $errline = 0;
    $error = error_get_last();
    if ( $error !== NULL )
    {
        echo '<pre>';
        print_r($error);
        echo '</pre>';
        header( "HTTP/1.0 500 Internal Server Error" );
    }
}
register_shutdown_function("my_fatal_handler");

アサーションを例外に変換するカスタムアサーションハンドラーを設定し、config/config.phpに次のようなものを配置します。

function my_assert_handler($file, $line, $code)
{
    log_message('debug', "assertion failed @$file::$line($code)" );
    throw new Exception( "assertion failed @$file::$line($code)" );
}
assert_options(ASSERT_ACTIVE,     1);
assert_options(ASSERT_WARNING,    0);
assert_options(ASSERT_BAIL,       0);
assert_options(ASSERT_QUIET_EVAL, 0);
assert_options(ASSERT_CALLBACK, 'my_assert_handler');

次に、これがあなたの答えです、あなたのコントローラーでこのようなラッパーを使用してください

public function controller_method( )
{
    try
    {
        // normal flow
    }
    catch( Exception $e )
    {
        log_message( 'error', $e->getMessage( ) . ' in ' . $e->getFile() . ':' . $e->getLine() );
        // on error
    }
}

全体を好みに合わせて調整およびカスタマイズできます。

お役に立てれば。

編集

また、CIshow_errorメソッドをインターセプトする必要があります。これをapplication/core/MY_exceptions.phpに配置します。

class MY_Exceptions extends CI_Exceptions
{
    function show_error($heading, $message, $template = 'error_general', $status_code = 500)
    {
        log_message( 'debug', print_r( $message, TRUE ) );
        throw new Exception(is_array($message) ? $message[1] : $message, $status_code );
    }
}

また、application / config / database.phpでこの設定をFALSEのままにして、データベースエラーを例外に変換します。

$db['default']['db_debug'] = TRUE;

CIには、例外処理など、いくつかの(非常に)弱点がありますが、これはそれを修正するのに大いに役立ちます。

于 2013-02-26T09:48:27.620 に答える
1

すべてのスクリプトに独自のクロージングハンドラーを設定できる関数register_shutdown_function()があります。そこで必要なことをするだけです。

ところで:スクリプトをできるだけ防弾にします。スクリプトに致命的なエラー、segfaults、またはそのようなランタイムエラーが発生することはありません。クライアントにとって無効であっても、すべての応答は要求処理のコンテキストで有効です。Symfony2フレームワーク、または単にそのHttpKernel / HttpFoundationコンポーネントを見てみることをお勧めします。これらのコンポーネントは、このプロセスを使いやすいインターフェイスで非常にうまくラップしているからです。

于 2013-02-26T03:15:18.473 に答える