このリポジトリはPHP Webアプリフレームワークである、LaravelのLTSバージョンである5.5の公式英文ドキュメントを日本語へ翻訳しています。
This project is maintained by okinaka
新しいLaravelプロジェクトを開始する時点で、エラーと例外の処理は既に設定済みです。App\Exceptions\Handler
クラスはアプリケーションで発生する全例外をログし、ユーザーへ表示するためのクラスです。このドキュメントでは、このクラスの詳細を確認していきます。
パワフルで様々なログハンドラをサポートしているMonologをLaravelはログに利用しています。単一ログファイルへのログ、一定期間ごとのログファイル切り替え、システムログへのエラー情報の書き込みを選べるように、Laravelはハンドラをあらかじめ準備しています。
アプリケーションエラー発生時にユーザーに対し表示する詳細の表示量は、config/app.php
設定ファイルのdebug
設定オプションで決定します。デフォルト状態でこの設定オプションは、.env
ファイルで指定されるAPP_DEBUG
環境変数の値を反映します。
local環境ではAPP_DEBUG
環境変数をtrue
に設定すべきでしょう。実働環境ではこの値をいつもfalse
にすべきです。実働環境でこの値をtrue
にしてしまうと、アプリケーションのエンドユーザーへ、セキュリティリスクになりえる設定情報を表示するリスクを犯すことになります。
Laravelはデフォルトで、単一ファイル(single
)、日別ファイル(daily
)、 システムログ(syslog
)、エラーログ(errorlog
)ログモードへのログ情報書き込みをサポートしています。Laravelが使用するストレージ機構の設定は、config/app.php
設定ファイルのlog
オプションを変更します。たとえば単一ファイルではなく、日別のログファイルを使用したい場合、app
設定ファイルのlog
の値に、daily
を設定してください。
'log' => 'daily'
daily
ログモード使用時にLaravelはデフォルトで、5日分のログファイルだけを残します。保存しておくファイルの数を調整したいときは、app
設定ファイルのlog_max_files
設定値を変更してください。
'log_max_files' => 30
Monologでは、異なった重大さのレベルのログを扱えます。Laravelはデフォルトで全ログレベルをストレージに書き込みます。しかし、実働環境ではapp.php
設定ファイルのlog_level
オプションへ、ログすべき最低の重大さレベルを指定したいことでしょう。
このオプションを一度設定すると、Laravelは指定された重大さ以上の全レベルをログします。たとえば、log_level
にerror
を設定すると、error、critical、alert、emergencyメッセージがログされます。
'log_level' => env('APP_LOG_LEVEL', 'error'),
{tip} Monologは次のレベルを取り扱います:
debug
、info
、notice
、warning
、error
、critical
、alert
、emergency
Monologがアプリケーションのために設定している内容を完全にコントロールしたければ、アプリケーションのconfigureMonologUsing
メソッドを使ってください。このメソッドはbootstrap/app.php
ファイルの中の$app
変数が返される直前に呼びださなくてはなりません。
$app->configureMonologUsing(function ($monolog) {
$monolog->pushHandler(...);
});
return $app;
Monologはデフォルトで、production
やlocal
のような現在の環境に合わせた名前でインスタンス化されます。この値を変えるには、app.php
設定ファイルに、log_channel
オプションを追加してください。
'log_channel' => env('APP_LOG_CHANNEL', 'my-app-name'),
全例外はApp\Exceptions\Handler
クラスで処理されます。このクラスはreport
とrender
二つのメソッドで構成されています。両メソッドの詳細を見ていきましょう。report
メソッドは例外をログするか、BugSnagやSentryのような外部サービスに送信するために使います。デフォルト状態のreport
メソッドは、ただ渡された例外をベースクラスに渡し、そこで例外はログされます。しかし好きなように例外をログすることが可能です。
たとえば異なった例外を別々の方法レポートする必要がある場合、PHPのinstanceof
比較演算子を使ってください。
/**
* 例外をレポート、もしくはログする
*
* ここは例外をSentryやBugsnagなどへ送るために適した場所
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
if ($exception instanceof CustomException) {
//
}
return parent::report($exception);
}
report
ヘルパ場合により、例外をレポートする必要があるが、現在のリクエストの処理を継続したい場合があります。report
ヘルパ関数により、エラーページをレンダすること無く、例外ハンドラのreport
メソッドを使用し、例外を簡単にレポートできます。
public function isValid($value)
{
try {
// 値の確認…
} catch (Exception $e) {
report($e);
return false;
}
}
例外ハンドラの$dontReport
プロパティは、ログしない例外のタイプの配列で構成します。たとえば、404エラー例外と同様に、他のタイプの例外もログしたくない場合です。必要に応じてこの配列へ、他の例外を付け加えてください。
/**
* レポートしない例外のリスト
*
* @var array
*/
protected $dontReport = [
\Illuminate\Auth\AuthenticationException::class,
\Illuminate\Auth\Access\AuthorizationException::class,
\Symfony\Component\HttpKernel\Exception\HttpException::class,
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Illuminate\Validation\ValidationException::class,
];
render
メソッドは与えられた例外をブラウザーに送り返すHTTPレスポンスへ変換することに責任を持っています。デフォルトで例外はベースクラスに渡され、そこでレスポンスが生成されます。しかし例外のタイプをチェックし、お好きなようにレスポンスを返してかまいません。
/**
* HTTPレスポンスへ例外をレンダー
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $exception);
}
例外ハンドラの中のreport
とrender
メソッドの中で、例外のタイプをチェックする代わりに、自身のカスタム例外でreport
とrender
メソッドを定義できます。これらのメソッドが存在すると、フレームワークにより自動的に呼び出されます。
<?php
namespace App\Exceptions;
use Exception;
class RenderException extends Exception
{
/**
* 例外のレポート
*
* @return void
*/
public function report()
{
//
}
/**
* 例外をHTTPレスポンスへレンダ
*
* @param \Illuminate\Http\Request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
return response(...);
}
}
例外の中にはサーバでのHTTPエラーコードを表しているものがあります。たとえば「ページが見つかりません」エラー(404)や「未認証エラー」(401)、開発者が生成した500エラーなどです。アプリケーションのどこからでもこの種のレスポンスを生成するには、abortヘルパを使用します。
abort(404);
abort
ヘルパは即座に例外を発生させ、その例外は例外ハンドラによりレンダーされることになります。オプションとしてレスポンスのテキストを指定することもできます。
abort(403, 'Unauthorized action.');
様々なHTTPステータスコードごとに、Laravelはカスタムエラーページを簡単に返せます。たとえば404 HTTPステータスコードに対してカスタムエラーページを返したければ、resources/views/errors/404.blade.php
を作成してください。このファイルはアプリケーションで起こされる全404エラーに対し動作します。ビューはこのディレクトリに置かれ、対応するHTTPコードと一致した名前にしなくてはなりません。abort
ヘルパが生成するHttpException
インスタンスは、$exception
変数として渡されます。
<h2></h2>
Laravelのログ機能は、強力なMonologライブラリーのシンプルな上位レイヤーを提供します。Laravelはデフォルトで、アプリケーションの日別ログファイルをstorage/logs
ディレクトリへ作成するように設定されています。ログへ情報を書き込むにはLog
ファサードを使います。
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 指定ユーザーのプロフィールを表示
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
Log::info('ユーザーのプロフィール表示。 ID:'.$id);
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
ログはRFC 5424で定義されているemergency、alert、critical、error、warning、notice、info 、debugの8レベルをサポートしています。
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
ログメソッドにはコンテキストデータを配列で渡すこともできます。このコンテキストデータはログメッセージと一緒に整形され、表示されます。
Log::info('User failed to login.', ['id' => $user->id]);
Monologはログに使用できる様々な追加のハンドラを提供しています。必要であれば、Laravelが裏で使用しているMonologインスタンスへアクセスすることもできます。
$monolog = Log::getMonolog();