====== Apricot ログとエラー処理 ====== --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-07-29// [[apricot:usage:ja|Apricot ドキュメント に戻る]] 目次 * [[apricot:usage:ja:features|Apricot 特徴と概要]] * [[apricot:usage:ja:config|Apricot 配置と構成]] * Apricot ログとエラー処理 * [[apricot:usage:ja:http|Apricot リクエストとレスポンス]] * [[apricot:usage:ja:frontend|Apricot フロントエンド]] * [[apricot:usage:ja:database|Apricot データベース]] * [[apricot:usage:ja:model|Apricot モデルとサービス]] * [[apricot:usage:ja:middleware|Apricot ミドルウェア]] * [[apricot:usage:ja:controller|Apricot コントローラ]] * [[apricot:usage:ja:validation|Apricot バリデーション]] * [[apricot:usage:ja:provider|Apricot サービスプロバイダー]] * [[apricot:usage:ja:authentication|Apricot ユーザ認証]] * [[apricot:usage:ja:utility|Apricot ユーティリティ]] ---- ===== ロギング ===== ロギングは、[[https://github.com/Seldaek/monolog|monolog]]をラップした ''Apricot\Log'' シングルトンが担当します。機能的には monolog と同じですが、[[https://www.php-fig.org/psr/psr-3/|PSR-3]]に従って使います。 使用法: **Log::{メソッド}** ^メソッド^機能^ |emergency(string $message, array $context = [])|emergencyレベルのログ| |alert(string $message, array $context = [])|alertレベルのログ| |critical(string $message, array $context = [])|criticalレベルのログ| |error(string $message, array $context = [])|errorレベルのログ| |warning(string $message, array $context = [])|warningレベルのログ| |notice(string $message, array $context = [])|noticeレベルのログ| |info(string $message, array $context = [])|infoレベルのログ| |debug(string $message, array $context = [])|debugレベルのログ| |log($level, string $message, array $context = [])|任意レベルのログ| 使用例: use Apricot\Log; Log::exception('error',$e); \\ ==== 設定ファイル ==== ロギングには以下の設定ファイルが存在します。 {{fa>folder-open-o}} ** /your-project/config/setting ** env('LOG_NAME',env('APP_NAME')), 'path' => env('LOG_PATH',var_dir('logs')), 'level'=> env('LOG_LEVEL','debug'), 'max_files'=> 0, ]; * name --- ログの名前 (初期設定は、環境変数APP_NAME(無ければAPP_NAME)の値) * path --- ログの出力パス (初期設定は、var/logs/) * level --- ログの出力レベル (初期設定は、'debug') * max_files --- ログファイルの最大保存数 (初期設定は、0(無制限)) \\ ===== デバッグ出力 ===== Apricotではオンサイトでのデバッグ出力機能を実現するために、[[https://github.com/maximebf/php-debugbar|php-debugbar]]を採用しています。そして、Apricotのコアでは、php-debugbarが提供している ''\DebugBar\StandardDebugBar'' クラスをカスタマイズした ''Apricot\Derivations\StandardDebugBar'' を作り、この機能をアプリケーションに提供しています。 ==== DebugBarクラス ==== ''DebugBar'' クラスはカスタマイズされた''StandardDebugBar''をラップしたシングルトンで、アプリケーションにデバック出力機能を提供しています。 使用法: **DebugBar::{メソッド}** ^メソッド^機能^ |renderHead():string|HTMLヘッダー用のレンダリング文字列を返す| |render():mixed|HTMLボディー用のレンダリング文字列を返す| |getCollector(string $name="messages"): \\ \DataCollector\DataCollectorInterface|デバッグ出力用のコレクターの取得| こららのメソッドの内、''renderHead()'' と ''render()'' はHTMLテンプレートで使用され、ブラウザ上にデバッグ出力をレンダリングします。また、''getCollector()'' は以下で示す [[#Debugクラス]]の生成で使用されます。 \\ ==== Debugクラス ==== ''Debug'' クラスは、実際にデバッグ出力を行うクラスです。機能的にはDebugBarのコレクター( DataCollectorInterface )と同じですが、ロギングと同様にPSR-3に従って以下のように使います。以下の関数は基本的に ''var_dump()'' と同じように変数の内容をダンプします (これらの関数の違いは単に出力レベルが付いているだけです)。''Debug::debug($this)'' とすれば自分のメンバ変数が全てダンプされます。 使用法: ** Debug::{メソッド} ** ^メソッド^機能^ |emergency($message, array $context = [])|emergencyレベル| |alert($message, array $context = [])|alertレベル| |critical($message, array $context = [])|criticalレベル| |error($message, array $context = [])|errorレベル| |warning($message, array $context = [])|warningレベル| |notice($message, array $context = [])|noticeレベル| |info($message, array $context = [])|infoレベル| |debug($message, array $context = [])|debugレベル| |log($level, $message, array $context = [])|任意レベル| 使用例: use Apricot\Debug; Debug::debug($this); \\ ==== 設定ファイル ==== デバッグ出力には以下の設定ファイルが存在します。 {{fa>folder-open-o}} ** /your-project/config/setting ** env('APP_DEBUG',false), 'renderer' => [ 'auto_assets'=>true, 'base_url' => url('resources/debugbar'), 'base_path' => public_dir('resources/debugbar'), 'initialize' => true, 'stacked_data' => true, ], ]; ''debug'' はデバッグ出力の有効性を指定するブール値です。この値が真の場合、デバッグ出力が有効になります。初期設定は[[apricot:usage:ja:config#環境設定|環境変数]] ''APP_DEBUG'' と同じ値です。 ''renderer'' 要素には以下の子要素があります。 * ''auto_assets'' --- 使用するアセットファイルの自動作成を指定します。 * ''base_url'' --- DebugBarのアセットのベースURLを指定します。 * ''base_path'' --- DebugBarのアセットのサーバ内のベースパスを指定します。 * ''initialize'' --- 初期化コードをレンダリングするか否かを指定します。(デフォルト値はtrue) * ''stacked_data'' --- スタックデータをレンダリングするか否かを指定します。(デフォルト値はtrue) ''auto_assets'' が true の場合、アプリケーションの初期化時に使用するリソースファイルを自動的に公開用ディレクトリーに作成します。''auto_assets'' が falseの場合は、手動でリソースファイルを作成して下さい。''base_url'' と ''base_path'' は手動の場合に指定します。 ''initialize''と''stacked_data''は、デバッグ出力が有効( '''debug' => true'' )の場合に効果があり、通常は、true のままで使用して下さい。 \\ ==== アセットファイル ==== 設定値の ''auto_assets'' がtureの場合は、アプリケーションの初期化時に自動で以下のディレクトリにのアセットファイルが作成されます。 /your-app-path/var/debugbar ''auto_assets'' がfalseの場合は、手動で以下に場所にアセットファイルを配置するように初期設定されています。 /your-app-path/resources/debugbar デバッグ出力で使用するアセットファイルは、以下のディレクトリーに保存されているので、この下の全てのファイルとディレクリーを上記の場所にコピーして下さい。 /your-project/vender/maximebf/debugbar/src/DebugBar/Resources/ 結果的に手動の場合のアセットファイルの配置は以下のようになります: {{fa>folder-open-o}} ** /your-app-path/resources/debugbar ** vendor/ widgets/ debugbar.css debugbar.js openhandler.css openhandler.js widgets.css widgets.js \\ ===== 集約例外ハンドラー ===== Apricotでは例外ハンドラーとして[[https://github.com/filp/whoops|Whoops]]を使います。コントローラで捕捉されなかった例外は、最終的にこの例外ハンドラーで捕捉するので、これは集約例外ハンドラーと呼ばれます。 集約例外ハンドラーの動作にはデバッグモードと本番モードがあります。 * デバッグモード --- ログ出力して、例外内容とスタックトレースを表示する * 本番モード --- ログ出力して、利用者向けのエラーページを表示する これらの動作をカスタマイズするには、以下のWhoopsのセットアップファイルを変更して下さい。 セットアップファイル: /your-project/config/setup/whoops.setup.php \\ ==== 設定ファイル ==== 例外ハンドラーには以下の設定ファイルが存在します。 {{fa>folder-open-o}} ** /your-project/config/setting ** env('APP_DEBUG',false), 'controller' => \App\Exceptions\UncaughtExceptionHandler::class, 'action' => 'render', ]; * debug --- デバッグモードの場合 true (初期設定は、環境変数APP_DEBUGの値。無ければfalse) * controller --- 集約例外コントローラクラスを指定する (次項参照) * action --- 集約例外コントローラのアクションメソッド名を指定する (次項参照) \\ ==== 集約例外コントローラ ==== 本番モードで集約例外ハンドラーから呼び出されるコントローラを集約例外コントローラと呼びます。上述の whoops.setting.php での設定に従い、例外発生時に ''UncaughtExceptionHandler'' クラスの ''render()'' メソッドが実行されてエラーページを表示します。 初期実装されている集約例外コントローラでは、例外の種類に応じてHTTPステータスコードを以下のように設定します。 * CSRFエラーなどの TokenMismatchException( トークンエラー )は419( Page Expired )に設定 * HttpException( ボイラープレート ''abort()'' などよるHTTP例外 )はそのステータスコードを使用 * その他の例外は 500( Internal Server Error )に設定 集約例外コントローラは以下に配置されています。必要に応じてカスタマイズできます。 /your-project/app/Exceptions/UncaughtExceptionHandler.php \\ ===== コアの例外クラス ===== Exceptionを継承した2つの例外クラスがあります。 * ''Apricot\Exceptions\HttpException'' \\ HTTP例外(HTTPステータスコード400番台,500番台) * ''Apricot\Exceptions\TokenMismatchException'' \\ トークンミスマッチ例外(CSRFトークンなどの不一致) ==== abort() ==== ''abort()'' 関数は ''HttpException'' をスローするボイラープレートです。通常はこの例外が発生すると集約例外コントローラが補足してエラーページを表示します。以下のように使います。 abort(400); ''abort()'' は以下のように実装されています。 /** * Throws an HTTP exception. * * @param int $code * @param string $message * @throws \Apricot\Exceptions\HttpException */ function abort(int $code, string $message=null) { throw new Apricot\Exceptions\HttpException($code, $message); } \\ ===== アプリの例外クラス ===== ''App\Exceptions\ApplicationException'' はアプリで発生する例外クラスのベースクラスで、Exceptionクラス から派生しています。そして、ApplicationExceptionから派生した以下のクラスがあります。 * ''App\Exceptions\OptimissticLockException'' \\ 楽観的ロック例外 \\ ===== エラーバッグ ===== エラーバッグ( ''Apricot\Foundation\ErrorBag'' )は、入力エラーなどの業務的なエラー(例外でないエラー)の為のクラスです。 ErrorBag には名前を付けることができます( self::DEFAULT_NAME='error' )。バッグ内のエラーはキー付きの連想配列で保存されています。ErrorBagには以下のメソッドがあります。 ^メソッド^機能^ |__construct(array $errors=null, string $name=self::DEFAULT_NAME)|エラーバッグの生成| |count(string $name=null):int|エラー数の取得| |has(string $key, string $name=self::DEFAULT_NAME):bool|キーによるエラーの存在確認| |get(string $key, string $name=self::DEFAULT_NAME)|キーによるエラーの取得| |all(string $name=null):array|全てのエラーの取得| |put($errors)|エラー配列の設定| エラーバッグは[[https://www.php.net/manual/ja/class.iteratoraggregate.php|IteratorAggregateインターフェース]]を実装してるのでforeach()などのIteratorを使用した構文が使用できます。但し、Countable インターフェイス は実装していないので、count関数ではなくErrorBag@countメソッドを使用して下さい。 バリデーションエラー用の [[apricot:usage:ja:validation#validatorerrorbagクラス|ValidatorErrorBag]] クラスは、ErrorBag から派生したクラスで、'validator' という名前がついています。バリデーションエラーと他のエラーを区別するには、この名前を使用して下さい。 \\