[PHP]trigger_error関数でカスタムエラー・警告を発生させる方法を徹底解説

PHP

PHPで例外(Exception)を使ったエラーハンドリングはもはや標準的な手法ですが、それ以前から存在する「ユーザー定義エラー」という仕組みをご存知でしょうか。trigger_error() を使うと、PHP組み込みのエラーシステムに乗せる形で、独自のエラーメッセージや警告を発生させることができます。

ライブラリの非推奨警告、設定ミスの通知、ログとの連携など、例外とは違った使い道があります。この記事では trigger_error() の基本仕様から実践的な活用パターン、例外との使い分けまで詳しく解説します。

関数概要

項目内容
関数名trigger_error()(エイリアス:user_error()
読み方トリガーエラー
分類エラー処理関数
対応バージョンPHP 4以降(全バージョンで使用可能)
引数エラーメッセージ(必須)、エラーレベル(省略可)
戻り値bool(true)
名前空間グローバル関数
関連拡張モジュール標準で組み込み(拡張モジュール不要)

構文

trigger_error(string $message, int $error_level = E_USER_NOTICE): bool

第1引数にはエラーメッセージの文字列を、第2引数には発生させるエラーのレベル(重要度)を指定します。第2引数は以下の3種類のいずれかを指定できます(PHPの組み込みエラーレベルのうち、ユーザーが意図的に発生させられるものに限定されています)。

定数重要度意味
E_USER_NOTICE低(デフォルト)軽微な通知。処理は継続される
E_USER_WARNING警告。処理は継続されるが注意が必要
E_USER_ERROR致命的エラー。スクリプトの実行が停止する
E_USER_DEPRECATED非推奨の使用方法であることの通知(PHP 5.3以降)

基本的な使い方

<?php
function divide(int $a, int $b): float
{
    if ($b === 0) {
        trigger_error('ゼロで除算しようとしました', E_USER_WARNING);
        return 0.0;
    }
    return $a / $b;
}

$result = divide(10, 0);
echo "結果: {$result}" . PHP_EOL;

実行結果:

Warning: ゼロで除算しようとしました in /path/to/script.php on line 6
結果: 0

trigger_error() を呼んでも、E_USER_WARNINGE_USER_NOTICE の場合はプログラムの実行が継続される点が、後述する E_USER_ERROR との大きな違いです。

処理の流れ

trigger_error("メッセージ", レベル)
        │
        ▼
   PHPの標準エラーハンドラ
   (または set_error_handler() で
    登録した独自のハンドラ)
        │
        ├─→ E_USER_NOTICE / E_USER_WARNING / E_USER_DEPRECATED
        │     → エラーメッセージを出力(またはログに記録)
        │     → 処理はそのまま継続される
        │
        └─→ E_USER_ERROR
              → エラーメッセージを出力
              → スクリプトの実行がそこで停止する

実践的なコード例

例1:非推奨になった関数の使用を警告する

<?php
class LegacyApiClient
{
    public function fetchDataOldWay(string $url): string
    {
        trigger_error(
            'fetchDataOldWay()は非推奨です。fetchData()を使用してください。',
            E_USER_DEPRECATED
        );
        return $this->fetchData($url);
    }

    public function fetchData(string $url): string
    {
        return "データ取得: {$url}";
    }
}

$client = new LegacyApiClient();
echo $client->fetchDataOldWay('https://api.example.com') . PHP_EOL;

実行結果:

Deprecated: fetchDataOldWay()は非推奨です。fetchData()を使用してください。 in /path/to/script.php on line 6
データ取得: https://api.example.com

ライブラリやフレームワークの開発で、古いメソッドを段階的に廃止していく際の通知として E_USER_DEPRECATED がよく使われます。

例2:設定値の異常を警告として記録する

<?php
class ConfigValidator
{
    public function validate(array $config): array
    {
        $defaults = ['timeout' => 30, 'retry' => 3];

        foreach ($defaults as $key => $defaultValue) {
            if (!isset($config[$key])) {
                trigger_error(
                    "設定キー '{$key}' が見つからないため、デフォルト値 {$defaultValue} を使用します。",
                    E_USER_NOTICE
                );
                $config[$key] = $defaultValue;
            }
        }

        return $config;
    }
}

$validator = new ConfigValidator();
$config = $validator->validate(['timeout' => 60]);

print_r($config);

実行結果:

Notice: 設定キー 'retry' が見つからないため、デフォルト値 3 を使用します。 in /path/to/script.php on line 10
Array
(
    [timeout] => 60
    [retry] => 3
)

致命的ではないが「気づいてほしい」設定の問題を通知する際に E_USER_NOTICE が適しています。

例3:set_error_handler()と組み合わせてログに記録する

<?php
class ErrorLogger
{
    private array $logs = [];

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

    public function handle(int $errno, string $errstr): bool
    {
        $levelNames = [
            E_USER_NOTICE    => 'NOTICE',
            E_USER_WARNING   => 'WARNING',
            E_USER_ERROR     => 'ERROR',
            E_USER_DEPRECATED => 'DEPRECATED',
        ];

        $levelName = $levelNames[$errno] ?? 'UNKNOWN';
        $this->logs[] = "[{$levelName}] {$errstr}";

        // trueを返すとPHPの標準エラーハンドラの処理をスキップする
        return true;
    }

    public function getLogs(): array
    {
        return $this->logs;
    }
}

$logger = new ErrorLogger();
$logger->register();

trigger_error('在庫が残りわずかです', E_USER_NOTICE);
trigger_error('APIのレスポンスが遅延しています', E_USER_WARNING);

restore_error_handler();

print_r($logger->getLogs());

実行結果:

Array
(
    [0] => [NOTICE] 在庫が残りわずかです
    [1] => [WARNING] APIのレスポンスが遅延しています
]

set_error_handler() と組み合わせることで、trigger_error() で発生させたメッセージを画面出力ではなく独自のログファイルや監視システムに送る、といった柔軟な制御が可能になります。

例4:致命的エラーで処理を強制停止させる

<?php
class CriticalResourceChecker
{
    public function checkDiskSpace(int $freeSpaceMb): void
    {
        if ($freeSpaceMb < 100) {
            trigger_error(
                "ディスク空き容量が危険なレベルです(残り{$freeSpaceMb}MB)。処理を中止します。",
                E_USER_ERROR
            );
        }
        echo "ディスク容量チェックOK。処理を続行します。" . PHP_EOL;
    }
}

$checker = new CriticalResourceChecker();
$checker->checkDiskSpace(50);

echo "この行は実行されません。" . PHP_EOL;

実行結果:

Fatal error: ディスク空き容量が危険なレベルです(残り50MB)。処理を中止します。 in /path/to/script.php on line 7

E_USER_ERROR を指定すると、その時点でスクリプトの実行が完全に停止します。これより後ろのコード(echo "この行は実行されません。"を含む)は一切実行されません。

注意:PHP 8.0以降では多くの内部エラーが Error / TypeError などの例外として扱われるようになりました。新規開発で「処理を止めたい」場合は、trigger_error(..., E_USER_ERROR) よりも throw new RuntimeException(...) のように例外をスローするほうが、try-catch での柔軟な制御ができるため一般的に推奨されます。

例5:APIのバリデーションエラーを警告として収集する

<?php
class ApiRequestValidator
{
    public function validate(array $data): bool
    {
        $isValid = true;

        if (empty($data['email'])) {
            trigger_error('emailパラメータが指定されていません。', E_USER_WARNING);
            $isValid = false;
        }

        if (isset($data['age']) && $data['age'] < 0) {
            trigger_error('ageパラメータには0以上の値を指定してください。', E_USER_WARNING);
            $isValid = false;
        }

        return $isValid;
    }
}

$validator = new ApiRequestValidator();
$result = $validator->validate(['age' => -5]);

var_dump($result);

実行結果:

Warning: emailパラメータが指定されていません。 in /path/to/script.php on line 7
Warning: ageパラメータには0以上の値を指定してください。 in /path/to/script.php on line 11
bool(false)

複数のバリデーションエラーをすべて警告として出しつつ、戻り値で全体の成否も返す、というハイブリッドな設計です。

例6:error_reporting()のレベルによる出力制御を確認する

<?php
class NoticeEmitter
{
    public function emit(): void
    {
        trigger_error('これはNOTICEレベルのメッセージです。', E_USER_NOTICE);
    }
}

$emitter = new NoticeEmitter();

echo "--- E_ALL の場合 ---" . PHP_EOL;
error_reporting(E_ALL);
$emitter->emit();

echo "--- E_ALL & ~E_NOTICE & ~E_USER_NOTICE の場合 ---" . PHP_EOL;
error_reporting(E_ALL & ~E_NOTICE & ~E_USER_NOTICE);
$emitter->emit();
echo "(NOTICEレベルが抑制されているため、上記のメッセージは表示されません)" . PHP_EOL;

実行結果:

--- E_ALL の場合 ---
Notice: これはNOTICEレベルのメッセージです。 in /path/to/script.php on line 6
--- E_ALL & ~E_NOTICE & ~E_USER_NOTICE の場合 ---
(NOTICEレベルが抑制されているため、上記のメッセージは表示されません)

trigger_error() で発生させたメッセージが実際に画面に表示されるかどうかは、error_reporting() の設定や display_errors の設定に依存します。本番環境では通常、画面表示は無効化されログにのみ記録される設定が推奨されます。

例7:デバッグ情報を含めたコンテキスト付きエラー

<?php
class DataProcessor
{
    public function process(array $items): array
    {
        $results = [];

        foreach ($items as $index => $item) {
            if (!is_numeric($item)) {
                trigger_error(
                    sprintf(
                        '配列のインデックス%dに数値以外の値「%s」が含まれています。スキップします。',
                        $index,
                        var_export($item, true)
                    ),
                    E_USER_WARNING
                );
                continue;
            }
            $results[] = $item * 2;
        }

        return $results;
    }
}

$processor = new DataProcessor();
$result = $processor->process([1, 2, 'abc', 4, null]);

print_r($result);

実行結果:

Warning: 配列のインデックス2に数値以外の値「'abc'」が含まれています。スキップします。 in /path/to/script.php on line 12
Warning: 配列のインデックス4に数値以外の値「NULL」が含まれています。スキップします。 in /path/to/script.php on line 12
Array
(
    [0] => 2
    [1] => 4
    [2] => 8
)

エラーメッセージに発生箇所のコンテキスト(インデックス番号や該当データの中身)を含めておくと、後からログを見返した際の原因特定がしやすくなります。

関連関数との比較

関数/構文役割処理継続の可否
trigger_error()ユーザー定義のエラー・警告を発生させるレベルによる(NOTICE/WARNINGは継続、ERRORは停止)
throw new Exception()例外をスローするtry-catchで捕捉されなければ停止
set_error_handler()エラー発生時の処理をカスタマイズするハンドラの実装次第
error_log()メッセージをログファイルやシステムログに記録する常に継続(出力に影響しない)
assert()開発時の前提条件チェック設定により例外化・警告いずれも可能
die() / exit()即座にスクリプトを終了する常に停止

trigger_error() の大きな特徴は、PHPの標準エラーシステムに統合されるという点です。error_log() のように直接ログに書き込むわけではなく、set_error_handler() で登録したハンドラを経由させたり、error_reporting() の設定でレベルごとに出力を制御したりできる柔軟性があります。一方、現代的なPHP開発では、回復可能なエラー処理には例外(throw)を使い、trigger_error() は「警告・非推奨通知」のような軽量な用途に限定するという使い分けが一般的です。

よくある落とし穴・注意点

  1. E_USER_ERROR はtry-catchで捕捉できない 一見「エラーを発生させる」という名前から例外のように扱えそうに思えますが、E_USER_ERROR は従来型のPHPエラーであり、try-catch で捕捉することはできません(PHP 7以降であれば、set_error_handler() で例外に変換することは可能です)。確実に捕捉可能なエラーハンドリングが必要な場合は、throw new Exception() を使うべきです。
  2. 本番環境でメッセージが画面に表示されてしまうリスク display_errors が有効な本番環境で trigger_error() を多用すると、内部のロジックやファイルパスなどの情報がユーザーに見えてしまう可能性があります。本番環境では display_errorsOff にし、log_errorsOn にしてログにのみ記録する構成が推奨されます。
  3. 戻り値は常にtrueであり、エラーの成否を表すものではない trigger_error() の戻り値は常に true(エラーが正しく発生した場合)であり、処理の成否を判定するためのものではありません。if (trigger_error(...)) のような使い方は意味を持たないため注意してください。
  4. 第2引数に指定できるレベルは4種類のみ E_WARNINGE_NOTICE のような「PHP内部が発生させるレベル」を trigger_error() の第2引数に直接指定することはできません。指定可能なのは E_USER_NOTICEE_USER_WARNINGE_USER_ERRORE_USER_DEPRECATED の4つ(ユーザー定義用に用意されたもの)のみです。
  5. PHP 8系での例外中心の設計トレンドとの兼ね合い PHP 7以降、多くの内部的なエラーが Error クラス(TypeErrorValueErrorなど)の例外として再設計されました。新規プロジェクトでは、回復可能なエラーロジックの多くを例外ベースで設計するのが主流になりつつあり、trigger_error() は「ライブラリの非推奨化通知」など限定的な用途で使われることが多くなっています。プロジェクトの設計方針に応じて、例外と使い分けることが重要です。

まとめ

ポイント内容
役割ユーザー定義のエラー・警告・通知を発生させる
引数第1引数:メッセージ(必須)、第2引数:エラーレベル(省略可)
戻り値bool(常にtrue)
指定可能なレベルE_USER_NOTICE, E_USER_WARNING, E_USER_ERROR, E_USER_DEPRECATED
処理継続NOTICE/WARNING/DEPRECATEDは継続、ERRORは停止
よく組み合わせる関数set_error_handler(), error_reporting()
主な用途非推奨警告、設定値の異常通知、軽量なバリデーション警告
注意点try-catchで捕捉不可、本番環境での情報漏えいリスク

trigger_error() は例外ほど厳格な制御は持たないものの、PHPの標準エラーシステムに統合された軽量な通知手段として、特に「非推奨警告」や「致命的ではないが気づいてほしい問題」を伝える場面で今でも活躍しています。例外との役割の違いを理解し、プロジェクトの設計方針に合わせて適切に使い分けましょう。

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