この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:8
ページ更新者:T
更新日時:2026-06-11 07:12:00

タイトル: エラーログ出力関数
SEOタイトル: PHP エラーログ出力 (error_log / Monolog / Laravel Log) 完全ガイド

この記事の要点
  • PHP の最も基本的なログ関数は error_log($message)。第 2 引数で出力先を切替
  • error_log($msg, 0): php.ini の error_log / 1: メール / 3: 指定ファイル / 4: SAPI ロガー
  • php.ini の log_errors = On + error_log = /var/log/php.log でエラーを集約
  • プロジェクト用途は Monolog (Composer) や PSR-3 LoggerInterface
  • Laravel は Log::info / warning / error / debug + config/logging.php で channel 管理

error_log 関数の基本

PHP 標準で提供される最も基本のログ関数。引数の渡し方で出力先が変わります。

// 1) 第 2 引数省略 / 0: php.ini の error_log 設定先へ
error_log("Something happened");

// 2) 第 2 引数 = 3: 指定パスにファイル追記 (★最頻出)
error_log("[" . date('c') . "] user_id=$id failed\n", 3, '/var/log/app/error.log');

// 3) 第 2 引数 = 1: メール送信
error_log("Critical error", 1, "admin@example.com");

// 4) 第 2 引数 = 4: SAPI モジュールに送る (mod_php なら Apache のエラーログ)
error_log("Send to SAPI", 4);
第 2 引数出力先備考
0 (省略時既定)php.ini の error_log / SAPI のエラーログ本番では既定で運用
1メール送信第 4 引数で追加ヘッダ。SMTP 設定が必要
3第 3 引数で指定したファイルに追記★ 任意のパスへログを出す定番
4SAPI ロガーPHP 7.4+。Apache/Nginx のエラーログへ

php.ini の設定

; php.ini
log_errors = On                          ; エラーをログに記録
error_log = /var/log/php/error.log       ; 既定の出力先
error_reporting = E_ALL                  ; 何を記録するか
display_errors = Off                     ; ★ 本番では Off
display_startup_errors = Off
log_errors_max_len = 1024                ; 1 件あたりの最大バイト

; ログローテーション (logrotate 例)
; /etc/logrotate.d/php
;   /var/log/php/error.log {
;       daily
;       rotate 30
;       compress
;       missingok
;       notifempty
;       postrotate
;           kill -USR1 `cat /run/php-fpm.pid` || true
;       endscript
;   }

error_log で出力した内容を確認

# リアルタイム監視
tail -f /var/log/php/error.log

# 直近 100 行
tail -n 100 /var/log/php/error.log

# キーワードでフィルタ
grep -i "PDOException" /var/log/php/error.log

# Apache / nginx のエラーログ (error_log で第 2 引数 4 / 0 のときの行き先候補)
tail -f /var/log/apache2/error.log
tail -f /var/log/nginx/error.log

# PHP-FPM のエラーログ
tail -f /var/log/php-fpm/error.log

関連関数

関数用途
error_log()ログメッセージを出力
error_reporting()記録するエラーレベルを実行時に変更
set_error_handler()独自のエラーハンドラを設定
set_exception_handler()未捕捉例外のハンドラ
register_shutdown_function()致命的エラー時に動かす後処理
debug_backtrace()スタックトレースを取得
trigger_error()独自のエラーを発生させる (E_USER_NOTICE/WARNING/ERROR)
syslog()OS の syslog に送信 (openlog() とセット)

独自エラーハンドラと例外ハンドラ

// すべての PHP エラーを error_log に送る
set_error_handler(function ($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        return false;   // 抑制レベルなら無視
    }
    error_log("[ERROR] $message at $file:$line");
    return true;
});

// 未捕捉例外
set_exception_handler(function (Throwable $e) {
    error_log(sprintf(
        "[EXCEPTION] %s: %s\n%s",
        get_class($e),
        $e->getMessage(),
        $e->getTraceAsString()
    ));
    http_response_code(500);
    echo 'Internal Server Error';
});

// 致命的エラー (Out of memory 等) の最終手段
register_shutdown_function(function () {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        error_log("[FATAL] {$err['message']} at {$err['file']}:{$err['line']}");
    }
});

syslog 出力

openlog("myapp", LOG_PID | LOG_PERROR, LOG_LOCAL0);
syslog(LOG_WARNING, "Suspicious login from " . $_SERVER['REMOTE_ADDR']);
syslog(LOG_ERR, "Database connection failed");
closelog();

// /var/log/syslog や /var/log/messages に流れる
// rsyslog で /var/log/myapp.log にルーティング可能

Monolog (PSR-3 準拠の定番ロガー)

本格運用ではほぼ Monolog が使われます。多彩な出力先 (file / stream / syslog / Slack / Mail / Sentry / Elasticsearch) と整形ハンドラを持ちます。

composer require monolog/monolog
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\SlackWebhookHandler;
use Monolog\Formatter\LineFormatter;

$logger = new Logger('app');

// 日次ローテーション
$rotate = new RotatingFileHandler('/var/log/app/app.log', 30, Logger::DEBUG);
$rotate->setFormatter(new LineFormatter(
    "[%datetime%] %level_name%: %message% %context% %extra%\n",
    'Y-m-d H:i:s'
));
$logger->pushHandler($rotate);

// エラーは Slack にも
$logger->pushHandler(new SlackWebhookHandler(
    'https://hooks.slack.com/services/...',
    '#alerts',
    'AppBot',
    true,
    null,
    false,
    false,
    Logger::ERROR
));

// 使い方
$logger->info('user logged in', ['user_id' => 42]);
$logger->warning('slow query', ['ms' => 1200, 'sql' => $sql]);
$logger->error('payment failed', ['order_id' => $orderId, 'reason' => $e->getMessage()]);

PSR-3 LoggerInterface

PHP-FIG が定めた標準ロガーインタフェース。Monolog も Laravel Log もこれに準拠しているため、フレームワーク非依存のライブラリは LoggerInterface を依存性注入で受け取るのが定番。

use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

class PaymentService {
    public function __construct(private LoggerInterface $logger = new NullLogger()) {}

    public function charge(int $amount): void {
        $this->logger->info('charging', ['amount' => $amount]);
        try {
            // ...
        } catch (\Throwable $e) {
            $this->logger->error('charge failed', ['exception' => $e]);
            throw $e;
        }
    }
}

// 8 つのレベル (debug, info, notice, warning, error, critical, alert, emergency)
$logger->debug('verbose');
$logger->info('normal');
$logger->notice('something noticeable');
$logger->warning('not an error, but...');
$logger->error('error happened');
$logger->critical('critical state');
$logger->alert('alert!');
$logger->emergency('system is down');

Laravel の Log ファサード

use Illuminate\Support\Facades\Log;

Log::debug('debug message');
Log::info('user signed in', ['id' => $user->id]);
Log::warning('disk almost full');
Log::error('DB connection lost', ['exception' => $e]);
Log::critical('out of memory');

// 特定チャンネルに直接
Log::channel('slack')->error('payment failed');
Log::channel('daily')->info('cron finished');

// 複数チャンネルへ同時に
Log::stack(['daily', 'slack'])->error('Critical: ...');

// 文脈付き (リクエスト ID 等を全ログに付与)
Log::withContext([
    'request_id' => request()->header('X-Request-Id'),
    'user_id' => auth()->id(),
]);
Log::info('order created');   // 上記 context が自動で乗る

Laravel config/logging.php の例

return [
    'default' => env('LOG_CHANNEL', 'stack'),

    'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['daily', 'slack'],
        ],

        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
            'days' => 14,
        ],

        'slack' => [
            'driver' => 'slack',
            'url' => env('LOG_SLACK_WEBHOOK_URL'),
            'username' => 'Laravel Log',
            'emoji' => ':boom:',
            'level' => 'critical',
        ],

        'syslog' => [
            'driver' => 'syslog',
            'level' => 'debug',
        ],

        'stderr' => [
            'driver' => 'monolog',
            'handler' => Monolog\Handler\StreamHandler::class,
            'with' => ['stream' => 'php://stderr'],
        ],
    ],
];

本番運用の注意

  • 個人情報 / 機密情報を出さない: メアド、パスワード、クレカ番号、秘密鍵
  • ローテーション必須: RotatingFileHandler / logrotate / Laravel daily ドライバ
  • ログレベルを分ける: 本番は INFO 以上、開発は DEBUG
  • 監視を入れる: ERROR 以上を Slack 通知 / Sentry / CloudWatch Logs Insights
  • 構造化ログを推奨: $logger->info('message', $context) の context で集計が楽に
  • display_errors = Off: 本番ではブラウザに出さない

FAQ

Q: error_log がどこに書かれているか分からない
A: php -i | grep error_log または phpinfo() で確認。空欄なら SAPI 既定 (Apache/Nginx のエラーログ) に流れます。

Q: error_log でファイルにパーミッションエラー
A: Web プロセス (apache / www-data / php-fpm) に対象ディレクトリの書き込み権限が必要。chown www-data:www-data /var/log/app

Q: Monolog と Laravel Log どちらを使うべき?
A: Laravel プロジェクトなら Log ファサードで十分 (内部 Monolog)。素の PHP やライブラリでは PSR-3 ベースで Monolog を直接注入。