Contents
1️⃣ PHP 本体の設定 ― php.ini の主要ディレクティブ
| ディレクティブ | 目的 | 推奨値 (例) |
|---|---|---|
log_errors |
エラーログ出力を有効化 | On |
error_log |
ログファイルの保存先 (絶対パス) | /var/log/php/error.log (Linux)C:\\php\\logs\\error.log(Windows) |
display_errors |
エラーを画面に表示するか | 本番: Off、開発: On |
error_reporting |
どのエラーレベルを対象にするか | E_ALL(開発)E_ALL & ~E_DEPRECATED & ~E_STRICT(本番) |
設定例(Linux 用)
|
1 2 3 4 5 6 |
; php.ini(または conf.d/*.ini)に追加 log_errors = On error_log = /var/log/php/error.log display_errors = Off ; 本番環境では必ずオフ error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT |
公式マニュアル
-log_errors・error_log: https://www.php.net/manual/en/errorfunc.configuration.php#ini.log-errors
-display_errors: https://www.php.net/manual/ja/errorfunc.configuration.php#ini.display-errors
-error_reporting: https://www.php.net/manual/ja/errorfunc.configuration.php#ini.error-reporting
2️⃣ ログファイルの配置と OS 権限
2‑1. Linux(Ubuntu/Debian 系)
|
1 2 3 4 5 6 7 8 9 10 11 |
# ① ディレクトリ作成 sudo mkdir -p /var/log/php # ② 所有者を Web サーバー実行ユーザーに変更 (Apache の場合 www-data、Nginx+PHP‑FPM は www-data) sudo chown www-data:www-data /var/log/php # ③ ディレクトリ権限は 0755、ファイルは 0644 が基本 sudo chmod 0755 /var/log/php sudo touch /var/log/php/error.log sudo chmod 0644 /var/log/php/error.log |
- ポイント
chmod 0755は「所有者が書き込み可、他は読み取り・実行可」なのでディレクトリ探索に必要です。- ファイル単位で
0644にすれば、Web サーバー以外のユーザーからの書き込みを防げます。
2‑2. Windows(IIS)
- エクスプローラーで
C:\php\logsを作成。 - フォルダーの [プロパティ] → [セキュリティ] にて、使用するアプリケーションプール ID(例:
IIS AppPool\MyAppPool)またはIUSRに「書き込み」権限を付与。 php.iniではバックスラッシュを 二重にエスケープ することを忘れずに。
|
1 2 |
error_log = "C:\\php\\logs\\error.log" |
2‑3. SELinux / AppArmor の考慮
- SELinux:
setsebool -P httpd_unified 1または対象ディレクトリにポリシー例外を追加。 - AppArmor:
/etc/apparmor.d/usr.sbin.php-fpmに"/var/log/php/** rw,"を追記し、systemctl reload apparmor。
3️⃣ コードからログ出力を制御するテクニック
3‑1. ランタイムで設定を書き換える (ini_set)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php // 開発時だけ詳細ログを有効化 if (getenv('APP_ENV') === 'development') { ini_set('log_errors', '1'); ini_set('display_errors', '1'); ini_set('error_log', __DIR__ . '/logs/dev.log'); } // 本番環境では画面表示をオフに else { ini_set('display_errors', '0'); } ?> |
3‑2. error_log() の活用例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php // カスタムフォーマットでログを書き込む $context = [ 'user_id' => $userId ?? null, 'uri' => $_SERVER['REQUEST_URI'], 'ip' => $_SERVER['REMOTE_ADDR'] ?? '', ]; $msg = sprintf( "[%s] %s - %s", date('c'), // ISO8601 タイムスタンプ $context['uri'], $context['user_id'] ? "User {$context['user_id']} error" : 'Anonymous request' ); error_log($msg, 3, __DIR__ . '/logs/custom.log'); ?> |
- 第2引数
3は「ファイルへ直接書き込む」モード。 - 複数行の構造化ログが必要なら JSON にシリアライズして出力すると、後続の Logstash/Fluentd との相性が良くなります。
3‑3. Monolog で高度なロギング
|
1 2 |
composer require monolog/monolog |
|
1 2 3 4 5 6 7 8 9 10 |
<?php use Monolog\Logger; use Monolog\Handler\StreamHandler; $log = new Logger('app'); $log->pushHandler(new StreamHandler(__DIR__.'/logs/monolog.log', Logger::DEBUG)); $log->error('Invalid parameter', ['user_id' => $userId, 'param' => $input]); ?> |
メリット
- ログレベル(debug、info、warning、error…)の細分化
- 複数ハンドラ(ファイル・syslog・Slack 等)への同時出力が可能
4️⃣ 環境別ベストプラクティス ― 開発 / 本番 / Docker
| 環境 | php.ini の要点 |
補足 |
|---|---|---|
| 開発(ローカル) | display_errors = Onlog_errors = Onerror_reporting = E_ALLerror_log = /path/to/dev/error.log |
IDE と同時にファイルを tail すれば即座に原因把握が可能 |
| 本番(物理/仮想サーバ) | display_errors = Offlog_errors = Onerror_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICTerror_log = /var/log/php/error.log |
ログは外部 SIEM へ転送(例: Filebeat → Elasticsearch) |
| Docker コンテナ | error_log = /proc/self/fd/2(stderr) |
Docker の標準ロギングドライバが自動収集。環境変数で上書き可能にすると柔軟性が向上 |
4‑1. Dockerfile とエントリポイント例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Dockerfile FROM php:8.3-fpm # 必要な拡張をインストール(例:pdo_mysql) RUN docker-php-ext-install pdo_mysql # カスタム設定ファイルをコピー COPY ./conf/php.ini /usr/local/etc/php/conf.d/custom.ini # エントリポイントスクリプトを配置 COPY ./docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD ["php-fpm"] |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# docker-entrypoint.sh(抜粋) #!/bin/sh set -e if [ "$APP_ENV" = "production" ]; then # 本番は stderr に出力 php -d display_errors=Off -d error_log=/proc/self/fd/2 else # 開発はローカルファイルへ php -d display_errors=On -d error_log=/var/log/php/dev.log fi exec "$@" |
PHP_INI_SCAN_DIRを利用すれば、conf.d/ 配下に複数の設定ファイルを分割管理でき、コンテナ起動時に自動でマージされます。
5️⃣ トラブルシューティングフロー
- ログファイルが生成されているか
-
ls -l /var/log/php/error.log(Linux)やエクスプローラーで確認。 -
書き込み権限は正しいか
- Linux:
stat -c "%U %A" /var/log/php/error.log→ 所有者が Web サーバーユーザーか、パーミッションがrw-か。 -
Windows: 「プロパティ → セキュリティ」で対象ユーザーに「書き込み」権限があるか。
-
SELinux / AppArmor の制約
bash
# SELinux が拒否している場合は audit.log に記録される
ausearch -m avc -ts recent | audit2allow -w -a -
必要に応じて
setseboolかカスタムポリシーで例外を付与。 -
パスのエスケープミス(Windows)
-
error_log = "C:\php\logs\error.log"→ バックスラッシュが1つだけだと文字列が途中で切れる。必ず"C:\\php\\logs\\error.log"と記述。 -
リアルタイム確認コマンド
| OS | コマンド |
|---|---|
| Linux | tail -F /var/log/php/error.log (ログローテーション対応) |
| macOS | 同上(BSD版 tail -f でも可) |
| Windows PowerShell | Get-Content -Path C:\php\logs\error.log -Wait |
- PHP‑FPM のエラーログ
conf
; php-fpm.conf (global)
error_log = /var/log/php/fpm_error.log
log_level = notice systemd管理下ならjournalctl -u php-fpm -fで一元閲覧できる。
📌 まとめ(ポイントだけ)
- php.ini の主要ディレクティブは必ず明示的に設定し、公式マニュアルのリンクを添えておく。
- ログ保存先は 絶対パス とし、OS の所有者・権限を正しく付与する(Linux は
www-data、Windows はアプリプール ID)。 - ランタイムで
ini_set()やerror_log()を使い、モジュール単位の細かい制御や JSON/Monolog で構造化ログを実現。 - 環境別(開発/本番/Docker)に設定を分け、Docker では stderr 出力+環境変数で切り替えると運用が楽になる。
- トラブル時は「ファイル・権限」「SELinux/AppArmor」「パスエスケープ」の順にチェックし、
tail -FやGet-Content -Waitでリアルタイム監視する。
これらのベストプラクティスを導入すれば、PHP 8.3 のエラーログは確実に取得でき、障害対応やパフォーマンスチューニングが格段にスムーズになります。