エラー処理

はじめに

全ての人々が知っている (べきだ) と思いますが、エラー処理 は、開発過程において非常に重要な部分をなしています。リクエストされたページがアクセス不能であることを示すだけではなく、 HTTP エラーステータスを返すことで(ブラウザやそれに類する)マシンに対して、 今何が起きているのかを知らせる方法でもあります。

コード エラー

FuelPHP の内部的なエラー処理は、例外 (Exception) に基づいています。あなたはコード中で例外を捕えることにより、 アプリケーションに適切に例外を処理させることができ、ユーザーは継続的にアプリケーションを使い続けることができます。

FuelPHP は、古い手続き型の関数からの(例外でなない)PHP エラーに遭遇した場合、デフォルトの PHP の振る舞いを変更します。 FuelPHP は、致命的でない PHP エラーに遭遇した場合、処理を継続せず、これらのすべてのエラーに対し PhpErrorException をスローします。 すると、以前は無視していたような E_NOTICE といったエラーもすべて解決することを求められます。 非プログラマが作成したビューファイル中の構文エラーといった、PHP のエラーを捕らえることも同時に可能になります。

アプリケーションの config/config.php ファイルにある errors.continue_on というキーに、 E_NOTICE や E_STRICT といった PHP エラータイプを追加することでエラー処理の振る舞いを変更することができます。 ここにエラーを定義することで、あなたのスクリプトの処理を継続させることができます。 これらのエラーに対する例外はスローされず、よってあなたはこれらのエラーをキャッチすることもできなくなります。

エラー時に処理を継続しないことを強く推奨します。コードにバグを発生させる原因となり、一度プロダクションとしてリリースされると 発見が大変困難になるかもしれません。

アプリケーションロジックエラー

404 エラー

404 のルートは app/config/routes.php で設定されます。そのルートは 404 のページ処理を行う controller/method を指示しています。 更なる情報はルーティングの節を参照ください

404 をスローする

ルーティング処理時のように、404 エラーをスローしたい時があるでしょう。 これは、HttpNotFoundException をスローすることで簡単に出来ます。404ページが動作すると、 Fuel は 終了 します。

throw new HttpNotFoundException;

この例外は、アプリケーションの index.php ファイル内で捕捉、処理されます。例外が捕捉されると、 設定されている 404 ルートを探し、見つかった場合、リクエストされた URI に対応する新しいリクエストを生成します。 つまりは、あたかも通常のリクエストと同じようにして、 その URI は 他のリクエストと同様のルーティング がなされるのです!

このような動作を望まないなら、index.php ファイルを下記のように変更してください。

// リクエストを生成し、実行し、出力を送信する。
try
{
	$response = Request::forge()->execute()->response();
}
catch (HttpNotFoundException $e)
{
	$route = array_key_exists('_404_', Router::$routes) ? Router::$routes['_404_']->translation : Config::get('routes._404_');
	if ($route)
	{
		// forge に 'false' を設定することで、リクエストはルーティングエンジンを無効にする
		$response = Request::forge($route, false)->execute()->response();
	}
	else
	{
		throw $e;
	}
}

404 処理

リクエストが生成され、そのルータがマッチしえるものを探し、その結果マッチするものがなかった場合、404 処理が開始されます。 デフォルトでは _404_ ルートは welcome/404 に向けられています。 以下、そのメソッドを一瞥することにしましょう:

// Controller_Welcome の中

/**
 * アプリケーションの 404 アクション。
 *
 * @access  public
 * @return  void
 */
public function action_404()
{
	$messages = array('Aw, crap!', 'Bloody Hell!', 'Uh Oh!', 'Nope, not here.', 'Huh?');
	$data['title'] = $messages[array_rand($messages)];

	// HTTP 404 出力ヘッダを設定する
	return Response::forge(Presenter::forge('welcome/404', $data), 404);
}

上記引用した部分を見れば、404 処理がどのようになっているのかわかると思います。普通のコントローラのアクションと同じです。 この処理が適切な点は、好みの内容をページ表示することが出来るところにあります。 データベースから取得したデータをそのビューに読み込むことが出来るのです。

Fuel は 404 ステータスを設定していませんので、ご自分で HTTP レスポンスを設定する必要があることに留意ください。正しいステータスヘッダを送信するには、 Response::forge(Presenter::forge('welcome/404'), 404); を返します。

Catch all

Fuel が 404 レスポンスステータスを設定していない点を利用して、同ステータスを catch all 機能として利用することが出来ます。 uri に基づいてページをデータベースから取得するようなページモデルを持つことも可能でしょう。 以下、そのようなことを可能とする例を示します:

// あなたの 404 コントローラの中

public function action_my404()
{
	$original_uri = \Input::uri();
	$result = \DB::select()->from('pages')->where('uri', $original_uri)->execute();
	if(count($result) === 1)
	{
		// お好みの [訳注: catch all によるデータベースからのデータ取得] ページを表示
	}
	else
	{
		// 一般的な 404 ページを表示
		$messages = array('Aw, crap!', 'Bloody Hell!', 'Uh Oh!', 'Nope, not here.', 'Huh?');
		$data['title'] = $messages[array_rand($messages)];
		return Response::forge(View::forge('welcome/404', $data), 404);
	}
}

500 をスローする

アプリケーションはサーバーで何かの問題が発生したことを示すために、 単に停止しエラーを表示することが必要な瞬間があるかもしれません。 通常、これは 500 Internal Server Error です。 この例外は、_500_ ルートを定義することにより、 フロントコントローラでキャッチすることができます。 それは適切なエラーメッセージを表示し追加のエラーログを行う、 または問題の解決を得るために管理者に通知を送信することができます。

404 エラーをスローするのと同様、500 エラーをスローすることができます。

throw new HttpServerErrorException;

403 をスローする

アクセス違反を集中処理をしたい場合は、 HttpNoAccessException をスローすることによって、 アクセス違反を通知するために選択することができます。 この例外は _403_ ルートを定義することにより、フロントコントローラでキャッチすることができます。 例えば、 ハンドラは現在の URI を記憶することができ、ログインをお願いし、成功の場合、 ユーザは違反が発生した場所に戻ることができ、保存された URI に戻ります。

404 をスローすると同様に、403 エラーをスローすることができます。

throw new HttpNoAccessException;

CLI モードでのエラー

CLI モードでエラーが起こると、oil console によるインタラクティブな場合でも、タスクを実行した場合でも、 単にエラーが表示され、エラーの種類により、現在の処理が中段されるかもしれません。

設定ファイル config.php の中の cli_backtrace 設定を true にすることで Fatal エラーの場合、 バックトレースをダンプするようにできます。