错误处理

简介

正如大家(應該)知道的,在开发過程中,错误处理 是非常重要的部分。它不僅向使用者表明他/她/它所請求的頁面是不可用的, 也是一種透過提供一个 HTTP 错误狀態來通知機器 (瀏覽器等)发生了什么事情的方式。

程式码错误

FuelPHP 的內部错误处理是基於例外。这可以让你在你的程式码中捕捉它們, 因此你的应用程序可以優雅地处理发生的例外,且使用者可以繼續使用应用程序。

FuelPHP 也改變預設 PHP 行为,當從舊的程序函式涉及 PHP 错误(不是例外)時。 取代在所有非致命错误繼續的是,FuelPHP 将会在所有错误发生時拋出一个 PhpErrorException。 这将強迫你解決所有错误,即使過去你可能会忽略的一个 E_NOTICE。 它也能让你捕捉 PHP 错误。例如,當你有非程式設計師建立的檢視, 要在檢視档案捕捉語法错误時。

你可以透過添加 PHP 错误类型(像 E_NOTICE 或 E_STRICT)到你应用程序 config/config.php 档案中的 errors.continue_on 鍵來修改此行为。这裡定義的错误将能让你的指令码繼續。 这些错误的例外不会被拋出,所以你可以不再捕捉它們。

我們強烈建議在错误時別繼續,因为它可能会導致程式码中的错误非常難以发现, 一旦你的应用程序進入量產!

应用程序邏輯错误

错误 404

404 路由設定在 app/config/routes.php 并且必須指向处理 404 頁面的控制器/方法。 在路由章節閱讀更多關於它的部分。

拋出一个 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)
	{
		// 添加 '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 狀態,你的 Response 必須設定它。回傳 Response::forge(Presenter::forge('welcome/404'), 404); 以傳送正確的狀態表頭。

捕捉全部

由於 Fuel 不設定 404 回應狀態,你可以使用它做为一个捕捉全部的函式。 你可能已经有一个可以透過 URI 從資料庫取回頁面的頁面模型。 下面是一个例子來說明此可能性:

// 在你的 404 控制器中

public function action_my404()
{
	$original_uri = \Input::uri();
	$result = \DB::select()->from('pages')->where('uri', $original_uri)->execute();
	if(count($result) === 1)
	{
		// 用任何你喜歡的方式顯示該頁面
	}
	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 內部伺服器错误

相似於拋出一个 404,可以拋出一个 500 错误。

throw new HttpServerErrorException;

在 CLI 模式中的错误

當在 CLI 模式中发生一个错误,無論是透過 oil 控制台互动,或执行一个任務時, 错误会简单呈现,并根據错误的类型,目前的动作可能会中止。

你可以啟用倒出回溯跟蹤(backtrace)當致命错误发生時,透過設定在 config.php 配置档案中的 cli_backtrace 配置鍵为 true