LoginSignup
37
37

More than 5 years have passed since last update.

set_error_handler と ErrorException を組み合わせると幸せになるかも

Last updated at Posted at 2012-12-26

set_error_handler() のコールバック関数でエラー情報を一旦 ErrorException にしておくと、いろいろ恩恵が得られるというお話。

<?php

// ErrorExceptionをもう少し便利にしたクラス
class MyErrorException extends ErrorException
{
    protected static $severities = [
        E_ERROR             => 'ERROR',
        E_WARNING           => 'WARNING',
        E_PARSE             => 'PARSING ERROR',
        E_NOTICE            => 'NOTICE',
        E_CORE_ERROR        => 'CORE ERROR',
        E_CORE_WARNING      => 'CORE WARNING',
        E_COMPILE_ERROR     => 'COMPILE ERROR',
        E_COMPILE_WARNING   => 'COMPILE WARNING',
        E_USER_ERROR        => 'USER ERROR',
        E_USER_WARNING      => 'USER WARNING',
        E_USER_NOTICE       => 'USER NOTICE',
        E_STRICT            => 'STRICT NOTICE',
        E_RECOVERABLE_ERROR => 'RECOVERABLE ERROR',
        E_DEPRECATED        => 'DEPRECATED',
        E_USER_DEPRECATED   => 'USER DEPRECATED',
    ];

    /**
     * return full exception message
     * @return string
     */
    public function getFullMessage()
    {
        return sprintf('%s: %s in %s on line %u', $this->getSeverityString(), $this->getMessage(), $this->getFile(), $this->getLine());
    }

    /**
     * return the exception severity as string
     * @return string
     */
    public function getSeverityString()
    {
        return $this->_severityToString($this->getSeverity());
    }

    /**
     * return severity as string
     * @param int $severity
     * @return string
     */
    protected function _severityToString($severity)
    {
        if ( array_key_exists($severity, static::$severities) === true )
        {
            return static::$severities[$severity];
        }

        return 'UNKNOWN ERROR('.$severity.')';
    }
}

// エラーハンドラーの登録
set_error_handler(function($severity, $message, $file, $line) {

    // 一度例外オブジェクトにすると、エラーをオブジェクト指向的に扱えます。
    // 例外オブジェクトですが必ずしも throw する必要はないです。
    $errorException = new MyErrorException($message, 0, $severity, $file, $line);

    // ErrorExceptionを継承したクラスを使うこともできます。
    echo $errorException->getFullMessage(), PHP_EOL;

    // オブジェクトを文字列にキャストすると、バックトレースもできます。
    echo $errorException;

    // 任意のファイルに書き込んだりとか。
    error_log($errorException, 3, '/tmp/error_log');

    // オブザーバパターンを使って、オブザーバに知らせるとか。
    observe_error($errorException);

    // 例外を投げて処理を中断したり。
    throw $errorException;
});

// オブザーバ
function observe_error(ErrorException $errorException) {
    // ErrorException を使えば、コールバック関数側で、引数に型を指定できるので、契約プログラミング(Programming By Contract)的な安心感があります。
    // function($severity, $message, $file, $line) {} のような引数いっぱいのコールバックを書かなくてよくなります。

    // ErrorExceptionの処理が続く...
}


// エラーを起こす
trigger_error('エラーだよ!');
37
37
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
37