LoginSignup
30
20

More than 5 years have passed since last update.

set_error_handlerは局所的にも使える

Last updated at Posted at 2017-05-19

set_error_handler って何?

この辺読んでね。

set_error_handler にまつわる杞憂

ありがちな心配?

  • ライブラリ側で勝手にこれ使うと,元のアプリケーション側で設定されてるハンドラを吹き飛ばしてしまうんじゃ?
  • restore_error_handler を呼んでも,結局エラーハンドラが無かった状態に戻るだけでは?
exif_*ってデータ次第でエラー発生するしエラーハンドラ使いたいけどライブラリ関数側で使うとなぁ…もう@演算子でいいや…
function read_image_metadata(string $filename)
{
    if (false === $type = @exif_imagetype($filename)) {
        throw new \RuntimeException(error_get_last()['message']);
    }
    if ($type !== IMAGETYPE_JPEG) {
        return [];
    }
    if (false === $data = @exif_read_data($filename)) {
        throw new \RuntimeException(error_get_last()['message']);
    }
    return $data;
}

そんなことはない!

set_error_handlerはスタッカブルであるため,リストアするとちゃんと直前に設定されていたエラーハンドラに戻してくれる。

finallyで自動的にリストアさせる
function read_image_metadata(string $filename)
{
    set_error_handler(function($severity, $message) {
        throw new \RuntimeException($message);
    });
    try {
        $type = exif_imagetype($filename);
        if ($type !== IMAGETYPE_JPEG) {
            return [];
        }
        return exif_read_data($filename);
    } finally {
        restore_error_handler();
    }
}

若干関数呼び出しのオーバーヘッドがあるが,書きやすくすることも可能だ。

関数で共通化する
function handle_error(callable $function, ...$args)
{
    set_error_handler(function($severity, $message) {
        throw new \RuntimeException($message);
    });
    try {
        return $function(...$args);
    } finally {
        restore_error_handler();
    }
}

function read_image_metadata(string $filename)
{
    return handle_error(function () use ($filename) {
        $type = exif_imagetype($filename);
        if ($type !== IMAGETYPE_JPEG) {
            return [];
        }
        return exif_read_data($filename);
    });
}
30
20
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
30
20