0

私は Slim/3.3.0 用のカスタム エラー ハンドラを作成しており、同じコードを再利用してエラーと例外の両方を処理する価値があるかどうかを判断しようとしています。ErrorExceptionそのために、エラーをインスタンスに変換するカスタム エラー ハンドラを定義しました。

require __DIR__ . '/../vendor/autoload.php';

set_error_handler (function ($errno, $errstr, $errfile, $errline) {
    if (!(error_reporting() & $errno)) {
        return true; // Do not run built-in handler
    }
    throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
});

$app = new \Slim\App(['settings' => ['displayErrorDetails' => false]]);
$container = $app->getContainer();
// [...]
$container['errorHandler'] = function (Slim\Container $c) {
    return new App\Handlers\Error($c->logger, $c['settings']['displayErrorDetails']);
};

その後、キャッチされていない例外をログに記録したり、一般的な「エラーが発生しました」ページを好みに合わせて表示したりできます (これまでのところ、非常に良い)。

E_WARNINGしかし、マイナーな問題 ( 、など) を別の方法で処理したいと考えていますE_NOTICE。すべてを中止して一般的なエラー ページ テンプレートを表示する代わりに、実行を継続したり、エラー メッセージをインラインで表示したりしたいと考えています(PHP がデフォルト)そしてここで私は迷子になりました。インライン部分の表示は簡単ですが、私のスクリプトはすぐに中止されます。

namespace App\Handlers;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

final class Error extends \Slim\Handlers\Error
{
    public function __invoke(Request $request, Response $response, \Exception $e)
    {
        if ($this->displayErrorDetails) {
            $response->write($e);
        } else {
            $this->saveToLog($e);
            $response->write('[ERROR]');
        }

        if ($this->isFatal($e)) {
            // Aborts scripts and displays error page (OK)
            return parent::__invoke($request, $response, $e);
        } else {
            // Seems to abort script (nothing else is shown from this poing)
            return $response;
        }
    }
}

...この方法でテストします:

$app->get('/warning-test', function (Request $request, Response $response) {
    $this->logger->info("Loading {$_SERVER['REQUEST_URI']}");
    $response->write('<h1>Warning test page</h1>');
    $response->write('<p>About to generate a warning:</p>');
    $this->logger->info("Generating warning...");
    1/0;
    $this->logger->info("Warning generated");

    $response->write('<p>This should display as well.</p>');
    // ... but it doesn't. Probably because Response is immutable and my copy
    // was superseded by a clone

    return $response;
});

私のオプションは何ですか?

4

1 に答える 1

1

このset_error_handler()関数は 2 番目のパラメーターとしてエラーの種類を受け取るためE_ERROR、カスタム エラー ハンドラーのみを使用するように指定できます。

$errorTypes = E_ERROR;
set_error_handler (function ($errno, $errstr, $errfile, $errline) {
    if (!(error_reporting() & $errno)) {
        return true; // Do not run built-in handler
    }
    throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
}, $errorTypes);

通知や警告を自分で処理したい場合は、基本的に通常のルートをキャンセルしてエラー応答のみを取るため、例外をスローすることはできません。次のように例外をスローせずにこれを行うことができます。

$errorTypes = E_WARNING | E_NOTICE;
set_error_handler (function ($errno, $errstr, $errfile, $errline) {
    if (!(error_reporting() & $errno)) {
        return true; // Do not run built-in handler
    }
    \App\Handlers\Error::setNoticeOrWarning($errno, $errstr, $errfile, $errline);
}, $errorTypes);

その後、後でミドルウェアでこれを確認して表示できます。

于 2016-08-30T15:03:06.970 に答える