例外は、指定のエラーが発生した場合に、スクリプトの通常のフローを変更するために使用します。
PHP 5では、エラーに対処する新しいオブジェクト指向の方法が登場しました。
例外処理は、指定のエラー(例外)状態が発生した場合に、コード実行の通常の流れを変更するために使用します。この状態のことを例外といいます。
次は、例外がトリガされたときに通常発生します:
さまざまなエラー処理方法を次に示します:
注: 例外はエラー状態でのみ使用する必要があります。指定したポイントでコード内の別の場所にジャンプするために使用しないでください。
例外がスローされると、それに続くコードは実行されず、PHPは一致する "catch"ブロックを見つけようとします。
例外がキャッチされない場合、"Uncaught Exception" メッセージの致命的なエラーが発行されます。
キャッチブロックのない例外をスローします:
<?php
//create function with an exception
function checkNum($number) {
if($number>1) {
throw new Exception("Value must be 1 or below");
}
return true;
}
//trigger exception
checkNum(2);
?>
上のコードは次のようなエラーになります:
Fatal error: Uncaught exception 'Exception'
with message 'Value must be 1 or below' in C:\webfolder\test.php:6
Stack trace: #0 C:\webfolder\test.php(12):
checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6
上の例のエラーを回避するには、例外を処理するための適切なコードを作成する必要があります。
適切な例外コードには次のものを含める必要があります:
妥当なコードで例外をトリガーしてみましょう:
<?php
//create function with an exception
function checkNum($number) {
if($number>1) {
throw new Exception("Value must be 1 or below");
}
return true;
}
//trigger exception in a "try" block
try {
checkNum(2);
//If the exception is thrown, this text will not be shown
echo 'If you see this, the number is 1 or below';
}
//catch exception
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
?>
上のコードは次のようなエラーになります:
Message: Value must be 1 or below
上のコードは例外をスローしてキャッチします:
しかし、"すべてのスローにはキャッチがなければならない"とのルールを回避する方法の1つは、トップレベルの例外ハンドラに すり抜けるエラーを処理を設定することです。 (However, one way to get around the "every throw must have a catch" rule is to set a top level exception handler to handle errors that slip through.)
カスタム例外ハンドラを作成するには、PHPで例外が発生したときに呼び出すことのできる、特別なクラスを作成する必要があります。 クラスは例外クラスの拡張でなければなりません。
カスタム例外クラスは、PHPの例外クラスからプロパティを継承すると共に、カスタム関数を追加することが可能です。
例外クラスを作成します:
<?php
class customException extends Exception {
public function errorMessage() {
//error message
$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
.': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
return $errorMsg;
}
}
$email = "someone@example...com";
try {
//check if
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
//throw exception if email is not valid
throw new customException($email);
}
}
catch (customException $e) {
//display custom message
echo $e->errorMessage();
}
?>
新しいクラスは、errorMessage()関数を追加した古い例外クラスのコピーです。 これは古いクラスのコピーであり、古いクラスのプロパティとメソッドを継承しているため、getLine()やgetFile()、 getMessage()などの例外クラスメソッドを使用することができます。
c上のコードは例外をスローし、それをカスタム例外クラスでキャッチします:
スクリプトで複数の条件をチェックし複数の例外を使用することが可能です。.
いくつかのif..elseブロック、switch、または複数の例外をネストすることができます。 これらの例外は、異なる例外クラスを使用し、異なるエラーメッセージを返すことができます:
<?php
class customException extends Exception
{
public function errorMessage()
{
//error message
$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
.': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
return $errorMsg;
}
}
$email = "someone@example.com";
try {
//check if
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
//throw exception if email is not valid
throw new customException($email);
}
//check for "example" in mail address
if(strpos($email, "example") !== FALSE) {
throw new Exception("$email is an example e-mail");
}
}
catch (customException $e) {
echo $e->errorMessage();
}
catch(Exception $e) {
echo $e->getMessage();
}
?>
上のコードは2つの条件をテストし、いずれかの条件が満たされない場合は例外をスローします:
スローされた例外が class customException で、customException catch がなく、基本的な例外の catch しかなかった場合、その例外はそこで処理されます。
時には、例外がスローされたときに、標準的な方法とは異なる方法で処理したい場合もあります。"catch"ブロック内で例外を2回スローすることは可能です。
スクリプトは、システムエラーをユーザから隠すべきです。システムエラーは、コーダにとって重要であるかもしれませんが、 ユーザにとっては何の関心もありません。ユーザにとって使いやすいものにするために、ユーザーフレンドリーなメッセージで例外を再スローすることができます:
<?php
class customException extends Exception {
public function errorMessage() {
//error message
$errorMsg = $this->getMessage().' is not a valid E-Mail address.';
return $errorMsg;
}
}
$email = "someone@example.com";
try {
try {
//check for "example" in mail address
if(strpos($email, "example") !== FALSE) {
//throw exception if email is not valid
throw new Exception($email);
}
}
catch(Exception $e) {
//re-throw exception
throw new customException($email);
}
}
catch (customException $e) {
//display custom message
echo $e->errorMessage();
}
?>
上のコードは、メールアドレスに "example"という文字列が含まれているかどうかを調べ、含まれている場合は、例外を再スローします:
例外が現在の "try"ブロックでキャッチできない場合、"上位レベル"のcatchブロックを検索します。
set_exception_handler()関数は、キャッチされないすべての例外を処理するユーザ定義関数を設定します。
<?php
function myException($exception)
{
echo "<b>Exception:</b> " . $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>
output of the code above should be something like this:
Exception: Uncaught Exception occurred
上のコードには、"catch"ブロックはありませんでしたので、代わりに、トップレベル例外ハンドラがトリガされました。
この関数は、キャッチされない例外をキャッチするために使用します。
単純なルール:何かをスローするなら、それをキャッチしなければなりません。