[PHP]set_error_handler()完全解説|カスタムエラーハンドラの実装とエラー処理の実践パターン

PHP

はじめに

PHPのデフォルトエラーハンドラは、エラーをブラウザやログに出力するだけです。本番環境でユーザーにエラー詳細を見せてしまったり、エラーをデータベースやSlackに通知できなかったりと、そのままでは不十分な場面が多くあります。

set_error_handler() は、PHPのエラー処理を自分で実装したカスタム関数に差し替えるための関数です。エラーの種類・メッセージ・発生場所を受け取り、ログ記録・通知・フォールバック処理など自由な後処理を実装できます。try-catch では捕捉できないNotice・Warning・Deprecatedといった非致命的エラーをハンドリングする唯一の手段でもあります。


関数の概要

項目内容
関数名set_error_handler()
所属PHP エラー処理関数
導入バージョンPHP 4.0.1以降
PHP 8.x対応済み

構文

set_error_handler(?callable $callback, int $error_levels = E_ALL): callable|null

パラメータ

パラメータ説明
$callbackcallable|nullカスタムハンドラ関数。null を渡すとデフォルトに戻す
$error_levelsintハンドラを適用するエラーレベル(ビットマスク)。デフォルトは E_ALL

戻り値

  • 以前に設定されていたハンドラ(callable)を返します
  • 以前のハンドラがない場合は null を返します

コールバック関数のシグネチャ

function errorHandler(
    int    $errno,    // エラーレベル定数(E_WARNING など)
    string $errstr,   // エラーメッセージ
    string $errfile,  // エラー発生ファイル
    int    $errline   // エラー発生行番号
): bool

戻り値の意味

戻り値動作
truePHP のデフォルトエラーハンドラを呼ばない(ハンドル済みとみなす)
falsePHP のデフォルトエラーハンドラを引き続き呼ぶ

ハンドリングできるエラーレベル

定数説明
E_ERROR1致命的エラー(ハンドラでは捕捉不可)
E_WARNING2警告(実行は継続)
E_NOTICE8注意(未定義変数など)
E_USER_ERROR256trigger_error() によるユーザー定義エラー
E_USER_WARNING512trigger_error() によるユーザー定義警告
E_USER_NOTICE1024trigger_error() によるユーザー定義通知
E_DEPRECATED8192非推奨機能の使用
E_ALL32767すべてのエラー

⚠️ E_ERROR / E_PARSE / E_CORE_ERROR / E_COMPILE_ERRORset_error_handler() では捕捉できません。これらは register_shutdown_function() + error_get_last() で対処します。


基本的な使い方

<?php
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
    echo "[エラー] [{$errno}] {$errstr} in {$errfile}:{$errline}\n";
    return true; // デフォルトハンドラを呼ばない
});

// テスト
trigger_error('テストエラー', E_USER_WARNING);
echo "処理継続中\n";

/*
出力例:
[エラー] [512] テストエラー in /path/to/script.php:8
処理継続中
*/

実践的なクラスベースの使用例

例1:ログファイル記録エラーハンドラクラス

<?php
/**
 * エラーを構造化してログファイルに記録するエラーハンドラクラス
 * 環境(本番・開発)に応じてエラー表示とログ記録を切り替える
 */
class FileLoggingErrorHandler
{
    private string $logFile;
    private bool   $displayErrors;
    private array  $levelNames = [
        E_ERROR           => 'ERROR',
        E_WARNING         => 'WARNING',
        E_NOTICE          => 'NOTICE',
        E_USER_ERROR      => 'USER_ERROR',
        E_USER_WARNING    => 'USER_WARNING',
        E_USER_NOTICE     => 'USER_NOTICE',
        E_DEPRECATED      => 'DEPRECATED',
        E_USER_DEPRECATED => 'USER_DEPRECATED',
        E_STRICT          => 'STRICT',
    ];

    public function __construct(
        string $logFile      = '/var/log/app/php_errors.log',
        bool   $displayErrors = false
    ) {
        $this->logFile      = $logFile;
        $this->displayErrors = $displayErrors;
    }

    /**
     * このハンドラを登録する
     */
    public function register(int $errorLevels = E_ALL): ?callable
    {
        return set_error_handler([$this, 'handle'], $errorLevels);
    }

    /**
     * エラーハンドラ本体
     */
    public function handle(int $errno, string $errstr, string $errfile, int $errline): bool
    {
        // error_reporting() で抑制されているエラーは無視(@ 演算子対応)
        if (!(error_reporting() & $errno)) {
            return false;
        }

        $levelName = $this->levelNames[$errno] ?? "E_{$errno}";
        $timestamp = date('Y-m-d H:i:s');
        $shortFile = basename($errfile);

        $entry = sprintf(
            "[%s] [%s] %s in %s:%d\n",
            $timestamp,
            $levelName,
            $errstr,
            $shortFile,
            $errline
        );

        // ログファイルに記録
        $this->writeLog($entry);

        // 開発環境ではブラウザにも表示
        if ($this->displayErrors) {
            echo "<pre style='color:red'>{$entry}</pre>";
        }

        // E_USER_ERROR は処理を止める
        if ($errno === E_USER_ERROR) {
            exit(1);
        }

        return true;
    }

    private function writeLog(string $entry): void
    {
        $dir = dirname($this->logFile);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        file_put_contents($this->logFile, $entry, FILE_APPEND | LOCK_EX);
    }
}

$handler = new FileLoggingErrorHandler(
    logFile:      '/tmp/app_errors.log',
    displayErrors: true
);
$handler->register();

trigger_error('データベース接続に失敗しました', E_USER_WARNING);
trigger_error('非推奨の関数を使用しています', E_USER_DEPRECATED);

/*
出力例:
[2025-09-01 12:00:00] [USER_WARNING] データベース接続に失敗しました in script.php:XX
[2025-09-01 12:00:00] [USER_DEPRECATED] 非推奨の関数を使用しています in script.php:XX
*/

例2:エラーを例外に変換するハンドラクラス

<?php
/**
 * PHP の Warning・Notice・Deprecated などを
 * ErrorException に変換して try-catch で捕捉できるようにするクラス
 *
 * PHP 8.0以降の一部 Warning は自動的に例外になるが、
 * それ以外のエラーレベルにはこのハンドラが有効
 */
class ErrorToExceptionConverter
{
    /** 例外に変換するエラーレベル */
    private int $convertLevels;

    public function __construct(
        int $convertLevels = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
    ) {
        $this->convertLevels = $convertLevels;
    }

    /**
     * このハンドラを登録する
     */
    public function register(): ?callable
    {
        return set_error_handler([$this, 'handle']);
    }

    /**
     * エラーを ErrorException に変換して投げる
     */
    public function handle(int $errno, string $errstr, string $errfile, int $errline): bool
    {
        // @ 演算子で抑制されているエラーは変換しない
        if (!(error_reporting() & $errno)) {
            return false;
        }

        // 対象レベルのみ変換する
        if (!($errno & $this->convertLevels)) {
            return false; // デフォルトハンドラに委譲
        }

        throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
    }

    /**
     * ハンドラ登録を解除してデフォルトに戻す
     */
    public function unregister(): void
    {
        restore_error_handler();
    }
}

$converter = new ErrorToExceptionConverter();
$converter->register();

try {
    // 未定義変数への参照(通常は Notice)→ ErrorException に変換される
    $value = $undefinedVariable ?? null; // PHP 8 では ?? で Notice を抑制可能
    trigger_error('存在しないキーへのアクセス', E_USER_WARNING);
} catch (\ErrorException $e) {
    echo "捕捉した例外: [{$e->getSeverity()}] {$e->getMessage()}\n";
    echo "  発生場所: {$e->getFile()}:{$e->getLine()}\n";
}

/*
出力例:
捕捉した例外: [512] 存在しないキーへのアクセス
  発生場所: /path/to/script.php:XX
*/

例3:エラーレベル別の通知振り分けクラス

<?php
/**
 * エラーの重大度に応じてログ・メール・Slack などへ振り分けるクラス
 * 致命的なエラーだけ即時通知し、軽微なエラーはログにまとめる
 */
class TieredErrorNotifier
{
    private array $handlers = [];
    private array $buffer   = [];

    public function __construct()
    {
        // デフォルトハンドラを設定
        $this->handlers['critical'] = [$this, 'notifyCritical'];
        $this->handlers['warning']  = [$this, 'bufferWarning'];
        $this->handlers['info']     = [$this, 'logInfo'];
    }

    public function register(): ?callable
    {
        return set_error_handler([$this, 'handle']);
    }

    public function handle(int $errno, string $errstr, string $errfile, int $errline): bool
    {
        if (!(error_reporting() & $errno)) {
            return false;
        }

        $context = [
            'errno'   => $errno,
            'message' => $errstr,
            'file'    => $errfile,
            'line'    => $errline,
            'time'    => microtime(true),
        ];

        match (true) {
            in_array($errno, [E_ERROR, E_USER_ERROR], true)
                => ($this->handlers['critical'])($context),
            in_array($errno, [E_WARNING, E_USER_WARNING], true)
                => ($this->handlers['warning'])($context),
            default
                => ($this->handlers['info'])($context),
        };

        return true;
    }

    private function notifyCritical(array $ctx): void
    {
        echo "🚨 [CRITICAL] {$ctx['message']} in {$ctx['file']}:{$ctx['line']}\n";
        // 実際には mail() や Slack Webhook で即時通知する
        // mail('admin@example.com', '致命的エラー', $ctx['message']);
    }

    private function bufferWarning(array $ctx): void
    {
        $this->buffer[] = $ctx;
        echo "⚠️ [WARNING] {$ctx['message']} (バッファリング: " . count($this->buffer) . "件)\n";
    }

    private function logInfo(array $ctx): void
    {
        $levelName = $this->levelName($ctx['errno']);
        echo "ℹ️ [{$levelName}] {$ctx['message']}\n";
    }

    /**
     * バッファリングされた Warning をまとめて通知する
     */
    public function flushBuffer(): void
    {
        if (empty($this->buffer)) {
            return;
        }
        echo "\n=== バッファリング済み WARNING: " . count($this->buffer) . "件 ===\n";
        foreach ($this->buffer as $i => $ctx) {
            printf("  #%d %s in %s:%d\n", $i + 1, $ctx['message'], basename($ctx['file']), $ctx['line']);
        }
        $this->buffer = [];
    }

    private function levelName(int $errno): string
    {
        return [
            E_NOTICE          => 'NOTICE',
            E_USER_NOTICE     => 'USER_NOTICE',
            E_DEPRECATED      => 'DEPRECATED',
            E_USER_DEPRECATED => 'USER_DEPRECATED',
            E_STRICT          => 'STRICT',
        ][$errno] ?? "E_{$errno}";
    }
}

$notifier = new TieredErrorNotifier();
$notifier->register();

trigger_error('設定ファイルが読み込めません', E_USER_WARNING);
trigger_error('非推奨のAPIを使用しています', E_USER_DEPRECATED);
trigger_error('キャッシュの書き込みに失敗', E_USER_WARNING);

$notifier->flushBuffer();

/*
出力例:
⚠️ [WARNING] 設定ファイルが読み込めません (バッファリング: 1件)
ℹ️ [USER_DEPRECATED] 非推奨のAPIを使用しています
⚠️ [WARNING] キャッシュの書き込みに失敗 (バッファリング: 2件)

=== バッファリング済み WARNING: 2件 ===
  #1 設定ファイルが読み込めません in script.php:XX
  #2 キャッシュの書き込みに失敗 in script.php:XX
*/

例4:エラーハンドラのスタック管理クラス

<?php
/**
 * set_error_handler() / restore_error_handler() を使って
 * 複数のエラーハンドラをスタック管理するクラス
 *
 * 特定の処理ブロックだけ別のハンドラを適用し、
 * ブロック終了後は元のハンドラに自動で戻す
 */
class ErrorHandlerStack
{
    private array $stack = [];

    /**
     * 新しいハンドラをスタックに積む
     */
    public function push(callable $handler, int $levels = E_ALL): void
    {
        $previous = set_error_handler($handler, $levels);
        $this->stack[] = [
            'handler'  => $handler,
            'previous' => $previous,
            'levels'   => $levels,
        ];
        echo "ハンドラを追加: スタック深さ " . count($this->stack) . "\n";
    }

    /**
     * 最後に積んだハンドラを取り出して元に戻す
     */
    public function pop(): void
    {
        if (empty($this->stack)) {
            return;
        }
        restore_error_handler();
        array_pop($this->stack);
        echo "ハンドラを復元: スタック深さ " . count($this->stack) . "\n";
    }

    /**
     * スコープ付きでハンドラを適用するユーティリティ
     * コールバック終了後に自動で pop する
     */
    public function withHandler(callable $handler, callable $scope, int $levels = E_ALL): mixed
    {
        $this->push($handler, $levels);
        try {
            return $scope();
        } finally {
            $this->pop(); // 例外が発生しても必ず復元
        }
    }

    public function depth(): int
    {
        return count($this->stack);
    }
}

$stack = new ErrorHandlerStack();

// 通常のハンドラを登録
$stack->push(function (int $errno, string $errstr): bool {
    echo "  [通常ハンドラ] {$errstr}\n";
    return true;
});

trigger_error('通常のエラー', E_USER_NOTICE);

// 特定ブロックだけ別ハンドラを使う
$result = $stack->withHandler(
    handler: function (int $errno, string $errstr): bool {
        echo "  [特殊ハンドラ] {$errstr}\n";
        return true;
    },
    scope: function (): string {
        trigger_error('特殊ブロック内のエラー', E_USER_WARNING);
        return '処理完了';
    }
);

trigger_error('ブロック後のエラー', E_USER_NOTICE);
$stack->pop();

echo "スコープの戻り値: {$result}\n";

/*
出力例:
ハンドラを追加: スタック深さ 1
  [通常ハンドラ] 通常のエラー
ハンドラを追加: スタック深さ 2
  [特殊ハンドラ] 特殊ブロック内のエラー
ハンドラを復元: スタック深さ 1
  [通常ハンドラ] ブロック後のエラー
ハンドラを復元: スタック深さ 0
スコープの戻り値: 処理完了
*/

例5:致命的エラーも捕捉するシャットダウンハンドラ組み合わせクラス

<?php
/**
 * set_error_handler() では捕捉できない致命的エラー(E_ERROR など)を
 * register_shutdown_function() + error_get_last() で補完するクラス
 *
 * 両者を組み合わせてほぼすべてのエラーを一元管理する
 */
class ComprehensiveErrorHandler
{
    private array  $errorLog   = [];
    private bool   $registered = false;

    public function register(): void
    {
        if ($this->registered) {
            return;
        }

        // 通常エラーのハンドラ(E_ERROR など致命的エラーは除く)
        set_error_handler([$this, 'handleError']);

        // 未捕捉例外のハンドラ
        set_exception_handler([$this, 'handleException']);

        // 致命的エラーのハンドラ(シャットダウン時に確認)
        register_shutdown_function([$this, 'handleShutdown']);

        $this->registered = true;
        echo "包括的エラーハンドラ登録完了\n";
    }

    /**
     * 通常エラーハンドラ(Warning / Notice / Deprecated など)
     */
    public function handleError(int $errno, string $errstr, string $errfile, int $errline): bool
    {
        if (!(error_reporting() & $errno)) {
            return false;
        }

        $this->record('error', $errno, $errstr, $errfile, $errline);

        if ($errno === E_USER_ERROR) {
            $this->sendErrorResponse(500, '内部サーバーエラーが発生しました');
            exit(1);
        }

        return true;
    }

    /**
     * 未捕捉例外ハンドラ
     */
    public function handleException(\Throwable $e): void
    {
        $this->record('exception', $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
        $this->sendErrorResponse(500, '予期しないエラーが発生しました');
        exit(1);
    }

    /**
     * 致命的エラーのシャットダウンハンドラ
     */
    public function handleShutdown(): void
    {
        $error = error_get_last();

        // 致命的エラーレベルのみ対処
        $fatalLevels = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR;
        if ($error !== null && ($error['type'] & $fatalLevels)) {
            $this->record('fatal', $error['type'], $error['message'], $error['file'], $error['line']);
            echo "🚨 致命的エラー: {$error['message']} in {$error['file']}:{$error['line']}\n";
        }

        // バッファリングされたエラーを最終出力
        $this->flushLog();
    }

    private function record(string $kind, int $code, string $msg, string $file, int $line): void
    {
        $entry = [
            'kind'    => $kind,
            'code'    => $code,
            'message' => $msg,
            'file'    => basename($file),
            'line'    => $line,
            'time'    => date('H:i:s'),
        ];
        $this->errorLog[] = $entry;
        echo "[{$entry['time']}] [{$kind}:{$code}] {$msg} ({$entry['file']}:{$line})\n";
    }

    private function sendErrorResponse(int $statusCode, string $message): void
    {
        if (!headers_sent()) {
            http_response_code($statusCode);
            header('Content-Type: application/json');
        }
        // echo json_encode(['error' => $message]);
    }

    private function flushLog(): void
    {
        if (count($this->errorLog) > 0) {
            echo "\n合計 " . count($this->errorLog) . " 件のエラーを記録しました\n";
        }
    }

    public function getErrorLog(): array
    {
        return $this->errorLog;
    }
}

$handler = new ComprehensiveErrorHandler();
$handler->register();

trigger_error('設定値が不正です', E_USER_WARNING);
trigger_error('非推奨メソッドを呼び出しました', E_USER_DEPRECATED);

// 未定義の定数参照(E_WARNING)
// echo UNDEFINED_CONST;

/*
出力例:
包括的エラーハンドラ登録完了
[12:00:00] [error:512] 設定値が不正です (script.php:XX)
[12:00:00] [error:16384] 非推奨メソッドを呼び出しました (script.php:XX)

合計 2 件のエラーを記録しました
*/

例6:テスト環境でのエラー検証クラス

<?php
/**
 * ユニットテストでエラーが正しく発生しているかを検証するクラス
 * set_error_handler() でエラーをキャプチャしてアサーションに使用する
 */
class ErrorCapture
{
    private array  $captured  = [];
    private bool   $capturing = false;
    private ?callable $previous = null;

    /**
     * エラーキャプチャを開始する
     */
    public function start(int $levels = E_ALL): void
    {
        $this->captured  = [];
        $this->capturing = true;

        $this->previous = set_error_handler(
            function (int $errno, string $errstr, string $errfile, int $errline): bool {
                $this->captured[] = [
                    'errno'   => $errno,
                    'message' => $errstr,
                    'file'    => $errfile,
                    'line'    => $errline,
                ];
                return true; // デフォルトハンドラを呼ばない
            },
            $levels
        );
    }

    /**
     * エラーキャプチャを停止して元のハンドラに戻す
     */
    public function stop(): array
    {
        restore_error_handler();
        $this->capturing = false;
        return $this->captured;
    }

    /**
     * キャプチャしたエラーを検証する
     */
    public function assertCaptured(int $expectedErrno, string $expectedMessage = ''): void
    {
        foreach ($this->captured as $error) {
            if ($error['errno'] === $expectedErrno) {
                if ($expectedMessage === '' || str_contains($error['message'], $expectedMessage)) {
                    echo "✅ エラー捕捉確認: [{$error['errno']}] {$error['message']}\n";
                    return;
                }
            }
        }
        throw new \AssertionError(
            "期待するエラー [{$expectedErrno}] '{$expectedMessage}' が発生しませんでした。\n"
            . "実際に発生したエラー: " . json_encode($this->captured, JSON_UNESCAPED_UNICODE)
        );
    }

    public function assertNone(): void
    {
        if (!empty($this->captured)) {
            throw new \AssertionError(
                "エラーが発生しないことを期待しましたが "
                . count($this->captured) . " 件発生しました"
            );
        }
        echo "✅ エラーなし確認: PASS\n";
    }

    public function assertCount(int $expected): void
    {
        $actual = count($this->captured);
        if ($actual !== $expected) {
            throw new \AssertionError("エラー件数: 期待={$expected}, 実際={$actual}");
        }
        echo "✅ エラー件数確認: {$actual}件\n";
    }

    public function getCaptured(): array
    {
        return $this->captured;
    }
}

// テスト利用例
function validateAge(int $age): bool
{
    if ($age < 0) {
        trigger_error("年齢は0以上である必要があります: {$age}", E_USER_WARNING);
        return false;
    }
    if ($age > 150) {
        trigger_error("年齢が現実的ではありません: {$age}", E_USER_NOTICE);
    }
    return true;
}

$capture = new ErrorCapture();

// 正常系テスト
$capture->start();
validateAge(25);
$capture->stop();
$capture->assertNone();

// 異常系テスト
$capture->start();
validateAge(-5);
$errors = $capture->stop();
$capture->assertCaptured(E_USER_WARNING, '年齢は0以上');
$capture->assertCount(1);

/*
出力例:
✅ エラーなし確認: PASS
✅ エラー捕捉確認: [512] 年齢は0以上である必要があります: -5
✅ エラー件数確認: 1件
*/

set_error_handler() と set_exception_handler() の使い分け

┌─────────────────────────────────────────────────────┐
│             PHP のエラー体系                          │
├──────────────────────┬──────────────────────────────┤
│ エラー(Error)       │ 例外(Exception / Throwable) │
│ E_WARNING            │ throw new RuntimeException    │
│ E_NOTICE             │ throw new InvalidArgument     │
│ E_USER_ERROR         │ TypeError(PHP 7以降)         │
│ E_DEPRECATED         │ Error(PHP 7以降)             │
├──────────────────────┼──────────────────────────────┤
│ set_error_handler()  │ set_exception_handler()       │
│ で捕捉               │ で捕捉                         │
└──────────────────────┴──────────────────────────────┘

致命的エラー(E_ERROR / E_PARSE):
  → register_shutdown_function() + error_get_last() で対処

@ 演算子との連携

<?php
set_error_handler(function (int $errno, string $errstr): bool {
    echo "ハンドラ呼び出し: {$errstr}\n";
    return true;
});

// @ でエラーを抑制すると error_reporting() が 0 になる
// → ハンドラ内で error_reporting() & $errno が 0 になるためスキップ可能
$result = @file_get_contents('/nonexistent/file');
// ハンドラは呼ばれない(抑制されている)

// @ なしだと呼ばれる
$result2 = file_get_contents('/nonexistent/file');
// → ハンドラ呼び出し: ...

関連関数との比較

関数役割
set_error_handler()Warning / Notice などのエラーをカスタムハンドラで処理
set_exception_handler()未捕捉の例外をカスタムハンドラで処理
register_shutdown_function()スクリプト終了時に処理を実行(致命的エラーに対処)
error_get_last()最後に発生したエラー情報を取得(shutdown 内で使用)
restore_error_handler()直前のエラーハンドラに戻す
trigger_error()ユーザー定義エラーを発生させる(テストやライブラリ内で使用)
error_reporting()報告するエラーレベルを取得・設定する

よくある落とし穴

<?php
// ❌ NG:E_ERROR・E_PARSE は set_error_handler() では捕捉できない
set_error_handler(function ($errno, $errstr): bool {
    echo "捕捉: {$errstr}\n";
    return true;
});
// undeclared_function(); // E_ERROR → ハンドラは呼ばれない・スクリプト終了

// ✅ 致命的エラーは register_shutdown_function() で対処する
register_shutdown_function(function (): void {
    $error = error_get_last();
    if ($error && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR))) {
        echo "致命的エラー検出: {$error['message']}\n";
    }
});
<?php
// ❌ よくある誤解:@ 演算子でエラーを抑制してもハンドラが常に呼ばれると思っている
set_error_handler(function ($errno, $errstr): bool {
    // error_reporting() を確認しないと @ 抑制エラーも処理してしまう
    echo "エラー: {$errstr}\n";
    return true;
});

// ✅ @ 演算子に対応するには error_reporting() のチェックが必要
set_error_handler(function ($errno, $errstr): bool {
    if (!(error_reporting() & $errno)) {
        return false; // 抑制されているのでスキップ
    }
    echo "エラー: {$errstr}\n";
    return true;
});
<?php
// ❌ NG:set_error_handler() の戻り値(以前のハンドラ)を捨てると復元できない
set_error_handler($myHandler); // 以前のハンドラを保存しない

// ✅ 以前のハンドラを保存して必要なら restore する
$previous = set_error_handler($myHandler);
// ... 処理 ...
restore_error_handler(); // または set_error_handler($previous);

まとめ

項目内容
関数名set_error_handler(?callable $callback, int $error_levels = E_ALL): callable|null
主な用途Warning / Notice / Deprecated などのエラーをカスタム処理する
捕捉できないエラーE_ERROR / E_PARSE / E_CORE_ERROR(shutdown + error_get_last() で補完)
戻り値以前のハンドラ(callable)または null
@ 演算子対応ハンドラ内で error_reporting() & $errno をチェックする
ハンドラの復元restore_error_handler() または set_error_handler(null)
例外との連携ErrorException を throw することで try-catch で捕捉可能にできる

set_error_handler() は PHP のエラー処理基盤を自分でコントロールするための中核関数です。ログ記録・例外変換・通知振り分け・テスト用キャプチャといった用途に合わせてカスタマイズし、set_exception_handler()register_shutdown_function() と組み合わせることで、あらゆるエラーを漏れなくハンドリングできる堅牢なエラー処理基盤を構築できます。


参考リンク

タイトルとURLをコピーしました