このリポジトリは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();