目录
1. 什么是异常
2. d 入门
3. 自定义异常
4. 多个异常
5. 重新抛出异常
6. 程序流的异常
7. 顶层异常处理程序
8. 错误代码
9. 摘要
什么是例外。
.随着PHP 5的到来,有了新的面向对象模型和一个新的对象的处理错误导向的方法。 .例外给我们很大的一个更好的错误让我们自定义的脚本错误时的行为(异常)遇到的处理。 此前PHP的处理功能,通过让来自错误标志和trigger_error()函数错误。 这些都是良好,良好的前的php5天,但在新的面向对象的环境中,我们需要更大的控制权。
我们有好的干净的代码处理教程。 在本教程中,我们将处理问题,以及如何处理这些问题。
Getting started. 入门。
.最简单的形式,例外情况仍然非常强大,因为它们使我们能够发现错误的地点和时间,我们想要的。.在一个更复杂的形式异常给我们一个替代的特殊的错误返回代码使用的信号函数调用失败。 我们可以使用各种功能的代码整个阻止他们。可以让潜水的,看看什么大惊小怪。 可让创建一个名为exception.php ...
/**
*
* @Check if number is greater than 3
*
* @param int
*
* @return bool on success
*
*/
function checkNum ( $number ){
if( $number > 3 )
{
throw new Exception ( "Number is greater than 3" );
}
return true ;
}
/*** call the function ***/
checkNum ( 28 );
?>
上面的代码将产生这样的错误:
Fatal error: Uncaught exception 'Exception' with message 'Number is greater than 3' in /www/exception.php:15 Stack trace: #0 /www/exception.php(21): checkNum(28) #1 {main} thrown in /www/exception.php on line 15致命错误:未捕获的异常异常与信息'数'大于3'/万维网/ exception.php:15堆栈跟踪:#0 /万维网/ exception.php(21):checkNum(28)#1(主要)抛出/万维网/在线15 exception.php
.该错误是因为发生了异常已在checkNum函数中抛出的,但尚未落网。.所有的异常必须被捕获或将出现此错误。.一个例外是被发现使用一个 catch块。但首先我们需要尝试的代码引发异常。 So the order of things is:因此,事物的顺序是:
* try 尝试
* throw 投
* catch 捕捉
.记住,如果你扔东西,你必须抓住它。 code.能让把它放到了一些有效的代码测试。
/**
*
* @Check if number is greater than 3
*
* @param int
*
* @return bool on success
*
*/
function checkNum ( $number ){
if( $number > 3 )
{
throw new Exception ( "Number is greater than 3" );
}
return true ;
}
/*** try block ***/
try
{
checkNum ( 28 );
/*** this code does not get excecuted if an exception is thrown ***/
echo 'If you see this, the number is not greater than 3' ;
}
/*** catch the exception here ***/
catch( Exception $e )
{
// code to handle the Exception
echo 'Catch exception here
' ;
echo 'Message: ' . $e -> getMessage (). '
' ;
echo 'More text or functions here.' ;
}
?>
当访问,上面的代码将产生输出到浏览器与此类似:
Catch exception here这里捕获异常
3消息:数大于3
.更多的文本或职能这里。
可以让单步执行代码,并获得一个正在发生的事情的抓地力。.函数checkNum简单地检查是一个数字大于3。 如果不是,异常与抛出的错误消息。 其次,我们有一个尝试()块作出调用checkNum()函数。 如果在checkNum条件()函数并不满足,exeption抛出,将在第一个catch块中捕获。.您可能有多个catch块。 PHP将试图解析出现任何异常,直至在这个代码块抛出或代码块结束。 Any code after an exception is thrown is not executed.以后的任何异常的代码不会被执行。
In the catch(){ } 代码的第一呼应一行文字说我们已经赶上了异常,则错误信息包含在调用$电子“getMessage()方法的异常类。 .错误信息是直接传递给构造异常类。 当捕捉抛出的异常,我们分配给一个变量的实例(对象)或代码中使用,而现在我们有一个异常对象,其中包含我们的异常信息。 So, enough of the basics.因此,足够的基础。 我们按照这份文件,我们将探讨更深...
Custom Exceptions 自定义异常
.异常类最喜欢的课程,可以扩展到创建自己的自定义异常类。 当一个新的类是基于PHP使用母公司统一施工,并允许的传承classAs。 .因此,当异常类扩展,所有方法都可以使用。 能让采取一类使用一个无效的电子邮件地址检查的基础上filter_var()函数返回的值运行它。
class customException extends Exception {
/**
*
* @return exception message
*
* @access public
*
* @return string
*
*/
public function exceptionMessage (){
/*** the error message ***/
$errorMsg = 'The email Address ' . $this -> getMessage (). ', on line ' .
$this -> getLine (). ' in ' . $this -> getFile (). ', is invalid.' ;
/*** return the error message ***/
return $errorMsg ;
}
} /*** end of class ***/
?>
The class above is essentially an exception class on its own.上面的类本质上是对自己的异常类。 It has the single addition of the exceptionMessage() method that calls the Exception class methods getLine() and getFile() and getMessage().它具有单一的exceptionMessage除了()方法调用的异常处理类方法getLine()和的GetFile()和getMessage()。 As they are defined in the base class, the extended class *inherits* from it.由于他们是在基类中定义的,扩展的类* *从它继承。 Lets take it for a test drive.能让采取试驾它。
/*** an invalid email address ***/
$email = "example@phpro@org" ;
try {
/*** check the validity of the email address ***/
if( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === FALSE )
{
/*** if there is a problem, throw an exception ***/
throw new customException ( $email );
}
}
catch ( customException $e )
{
/*** display the custom error message ***/
echo "
" . $e -> errorMessage (). "
" ;/*** the custome excetpion class ***/
class customException extends Exception {
/**
*
* @return exception message
*
* @access public
*
* @return string
*
*/
public function errorMessage (){
/*** the error message ***/
$errorMsg = 'The email Address ' . $this -> getMessage (). ', on line ' .
$this -> getLine (). ' in ' . $this -> getFile (). ', is invalid.' ;
/*** return the error message ***/
return $errorMsg ;
}
} /*** end of class ***/
?>
显然,提供的电子邮件地址是无效的,当filter_var()函数返回布尔假抛出一个异常的customException类。 .抛出异常的将任何正常例外。 即使只参数传递给customException类是变量$电子邮件,所有可用的方法父类可异常,如getMessage(),getLine()和的GetFile()。.由于PHP的面向对象模型包括统一的构造,当变量$电子邮件传递给customException类,它可以立刻提供给父类。.但这个例子表明,只有如何尝试,投掷,并抓到一个例外。.还有的时候,我们需要比这更多。 多个异常可以抛出并捕获。
Multiple Exceptions 多个异常
多个异常可以采取多种形式。 .他们可以在多的if / else块,在一个交换机或嵌套。 Yes, you can nest exceptions in multiple try{ } catch(){ } blocks.是的,你可以尝试在多个巢捕获异常()()()块。 A script may need to check for multiple conditions and different messages returned.阿脚本可能需要检查多个条件和不同的消息返回。 Program flow may also need to change if an exception is thrown.程序流程可能也需要改变,如果抛出一个异常。 Lets see how we can nest an exception and check for different error conditions.让我们看看我们如何可以嵌套异常和不同的错误条件检查。 The customException class need not change for this.在customException类并不需要改变这一点。 This is what is meant in PHP as re-usable code.这就是在PHP中的意思是可重复使用的代码。 Here we see an example of using nested try{ } catch(){ } blocks.这里我们看到一个使用嵌套的尝试,例如()赶上()()块。
error_reporting ( E_ALL );
$email = "example@phpro.org" ;
try {
if( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === FALSE )
{
throw new customException ( $email );
}
try {
if( strpos ( $email , 'phpro' ) !== FALSE )
{
throw new Exception ( " $email is funky" );
}
}
catch( Exception $e )
{
echo '
' . $e -> getMessage (). '
' ;" . $e -> errorMessage (). "
" ;class customException extends Exception {
/**
*
* @return exception message
*
* @access public
*
* @return string
*
*/
public function errorMessage (){
/*** the error message ***/
$errorMsg = 'The email Address ' . $this -> getMessage (). ', on line ' .
$this -> getLine (). ' in ' . $this -> getFile (). ', is invalid.' ;
/*** return the error message ***/
return $errorMsg ;
}
} /*** end of class ***/
?>
In the above example, the colors of the errors have been made red or blue to easily discern which error has been thrown.在上面的例子中,这些错误的颜色作出了红色或蓝色,不难看出其中的错误已被抛出。 The problem with this sort of code, or nested if/else blocks, is if the program calls for large amounts of validation, we end up with very deeply nested code which can become very clumsy to read and debug.与此代码排序,嵌套或问题的if / else块,如果程序是需要大量的验证,我们最终非常深嵌套代码,可能会变得非常笨拙的阅读和调试。 A better option is simply to code smarter.Lets look at an option using only single if() blocks to check a condition.一个更好的选择就是代码smarter.Lets在一个单一的,如果只使用()块检查条件的选项。
error_reporting ( E_ALL );
$email = "kevin@fish.phpro.org" ;
try {
/*** check if email is valid ***/
if( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === FALSE )
{
throw new customException ( $email );
}
/*** check for fish ***/
if( strpos ( $email , 'fish' ) !== FALSE )
{
throw new Exception ( " $email is funky" );
}
/*** check for example.org ***/
if( $email !== 'kevin@example.org' );
{
throw new customException ( $email );
}
}
catch( customException $e )
{
echo '
' . $e -> errorMessage (). '
' ;' . $e -> getMessage (). '
' ;class customException extends Exception {
/**
*
* @return exception message
*
* @access public
*
* @return string
*
*/
public function errorMessage (){
/*** the error message ***/
$errorMsg = 'The email Address ' . $this -> getMessage (). ', on line ' .
$this -> getLine (). ' in ' . $this -> getFile (). ', is invalid.' ;
/*** return the error message ***/
return $errorMsg ;
}
} /*** end of class ***/
?>
.上面的编码风格使得好多意识和更容易跟踪和阅读。 .两个catch()()块中采用了此代码的执行情况作为例外,允许倍数。 再次是错误的颜色编码,这一次,我们看到,PHP已经成功跃升至正确的捕获()()块对应抛出错误。 在这种情况下,美元的电子邮件变量的*鱼*,因此在它的标准异常,并在适当的catch捕获()()块字。 块被省略,只有基地异常catch块是用,将处理异常那里。
Re-throwing Exceptions 重新抛出异常
一个例外可以重新抛出当你希望执政程序流.如果条件不满足,并抛出一个异常,你可以有不同的处理的基础上第二个条件,或者您不妨尝试从错误中恢复。 人们普遍认为,从实践中隐藏用户的系统错误。让我们考虑与专业发展主任简单的数据库连接。 因为PDO是完全如此惊人的,它有一个内置的例外。 .如果发生错误,当试图连接到一个异常的,必须抓住数据库。虽然在从数据库错误可能是有意义的人编码的应用程序,它有很少或没有相关的用户。.因此,异常可以重新用了漂亮友好的信息,即用户更容易理解抛出。例如:一个失败的专业发展主任数据库错误是这样的:
无法打开数据库文件
当重新掷下级这样的错误,例外必须用内被抛出一个。 如果异常没有抓住包装,将继续“泡沫了”堆栈,直到找到一个catch()()块来处理它。如果没有赶上()()块找到,未捕获的异常错误的结果。下面的例子演示了如何正确地重新抛出一个异常。
try {
try {
/*** try to connect to a non-existant database ***/
$db = new PDO ( "sqlite:/path/to/database.sdb" );
}
catch( PDOException $e )
{
/*** rethrow the error to the custom handler ***/
throw new customException ( "Database unavailable" );
}
}
/*** catch the customException here ***/
catch( customException $e )
{
/*** echo the new error message ***/
echo $e -> errorMessage ();
}
class customException extends Exception {
/**
*
* @return exception message
*
* @access public
*
* @return string
*
*/
public function errorMessage (){
/*** the error message ***/
$errorMsg = '
' . $this -> getMessage (). '
' ;} /*** end of class ***/
?>
.从上面的代码中,我们看到一个PDO异常当我们试图连接到一个不存在的数据库。 .这一例外是捕获并重新与customException类处理错误,并优雅地退出抛出。 Any un-.任何未捕获的异常应被视为一个应用程序错误。
Program Flow with Exceptions 程序流的异常
例外不应被用作藤,即使他们似乎理想目的的理想选择 try{} catch{} blocks.一个好的例外implemtation意味着代码将未经尝试()()块捕获任何。.异常类应该只用于错误条件。 下面是一个不正确的异常使用的例子。
$animalsArray = array( 'dingo' , 'wombat' , 'steve irwin' , 'kiwi' , 'kangaroo' , 'platypus' );
try {
/*** loop over the array ***/
foreach( $animalsArray as $value )
{
/*** if we find a kiwi ***/
if( $value = 'kiwi' )
{
/*** throw an exception here ***/
throw new Exception ( "This is not an Australian Native" );
}
}
}
catch( Exception $e )
{
/*** catch the exception here ***/
echo $e -> getMessage ();
}
?>
.上面的脚本抛出一个值时,在foreach循环发现异常。 这是一个例外类作为一个简单的突破这里滥用后会做同样的工作干净。 没有错误发生,所以应该没有异常抛出。
Top Level Exception Handler 顶层异常处理程序
.阿PHP最惊人的特点是set_exception_handler()函数。 .这个小魔术师,照顾的联合国陷入数额是多少例外最后机会赶上任何先前未捕获的异常,即:如果没有任何异常在catch()()块捕获。.此函数作为其唯一的参数回调exception_handler前必须给它的任何要求定义。 该default_handler将一个参数是异常对象已抛出。 .这列出了脚本的运作。
/*** a default Exception handler ***/
function my_default_handler ( $exception ){
echo "Uncaught exception: " , $exception -> getMessage ();
}
/*** set the default to handler to my_default_handler ***/
set_exception_handler ( 'my_default_handler' );
/*** throw an exception ***/
throw new Exception ( 'Catch me if you can!' );
echo 'This is not executed' ;
?>
If you wanted to restore the default Exception handler, simple use the restore_exception_handler(); function.如果你想恢复默认异常处理程序,简单使用restore_exception_handler()函数。 This could also be used if your current default handler was another custom Exception class.这也可以使用如果您当前的默认处理程序是另一个自定义异常类。 The Exception classes are held in a stack can be restored with the restore_exception_handler() function as shown here.异常类被关押在一个栈可以与restore_exception_handler恢复()函数,如下所示。
/*** an email to validate ***/
$email = 'guru@phpro.org' ;
/*** red error messages ***/
function blue_default_handler ( $exception ){
echo '
' . $exception -> getMessage (). '
' ;/*** blue error messages ***/
function red_default_handler ( $exception ){
echo '
' . $exception -> getMessage (). '
' ;/*** set the default to handler to red_default_handler ***/
set_exception_handler ( 'red_default_handler' );
/*** some code here ***/
if(!isset( $email ))
{
/*** if there is no match ***/
throw new exception ( 'No Email is set' );
}
/*** set the default handler to blue_default_handler ***/
set_exception_handler ( 'blue_default_handler' );
/*** check the email value ***/
if( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === FALSE )
{
throw new Exception ( 'Invalid Email' );
}
/*** restore the default handler ***/
restore_exception_handler ();
if( strpos ( $email , 'guru' ) !== false )
{
throw new Exception ( 'Sorry, No gurus at phPro' );
}
echo 'This is not executed' ;
?>
So, from the script above we see the declaration of two Exception handlers, one makes the error messags red, and the other makes them blue.因此,从上面我们看到的是两个异常处理声明脚本,其中一个人的错误messags红色,蓝色等使它们。 This is perhaps an abuse of the Exception functionality but serves well to demonstrate changes in classes as they occur.这也许是一个异常功能的滥用,但可以很好地显示在课堂发生变化。 The initial default handler is set to red.最初的默认处理程序设置为红色。 The a check is run to see if an $email variable is set.在运行检查,看看是否$电子邮件变量。 Try removing the $email variable or commenting it out to see it work.尝试删除电子邮件美元的变量或评论出来才能看到它的工作。 If the $email varible is set, the code continues and the default handler is set to the blue_default_handler.如果$电子邮件varible设置,代码继续进行,默认处理程序设置为blue_default_handler。 Then using the filter_var() function, the $email is tested for validity and if it fails, a blue message is shown.然后使用filter_var()函数,电子邮件美元的有效性进行测试,如果失败,一个蓝色的消息显示。 Try changing the value of the email to 1234 to see the results.试着改变电子邮件的价值1234看到的结果。 Finally we see the use of restore_exception_handler(); which pops the stack and returns the default Exception handler to the red_default_handler.最后,我们看到了restore_exception_handler使用();的弹出堆栈,并返回默认的异常处理程序red_default_handler。 When any of these exceptions occur, code execution stops and control is passed to the handler.当这些异常的发生,代码执行停止和控制传递给处理程序。 You notice at the bottom of the script above that the line您会注意到在上述脚本的底部的行
echo 'This is not executed';回声'这是不执行';
is never executed.永远不会执行。 But..但.. what if we wish to continue with the script and execute code below the thrown exceptions?如果我们希望继续与脚本和执行下面的代码抛出的例外? This is the default behavior of Exceptions.这是例外的默认行为。 Once outside the catch(){ } block you are free to include whatever code you wish.一旦捕捉外()()块你可以自由地包括任何代码的愿望。
Output buffering is Off by default in php.ini so it will need to be turned on via ob_start().输出缓冲是在php.ini文件的默认关闭,因此它需要被关闭的通过ob_start()。 We can begin output to the brower in the script and if an exception is thrown, still use header() to redirect based on the exception type.我们可以开始输出到在脚本布劳尔,如果抛出异常,仍使用头()重定向的异常类型为基础。
try {
/*** try to connect to a non-existent database ***/
$dsn = new PDO ( "sqlite:/path/to/database.php" );
/*** this code is never executed ***/
echo 'Move along, nothing to see here' ;
}
catch ( PDOException $e )
{
/*** echo the error message ***/
echo '
/*** more code and HTML here ***/
echo '
Catch me if you can!
' ;
?>
Error Codes 错误代码
As seen in the beginning of this document, the Exception class contains a getCode() method that will fetch an error code, this can useful as you can define your own error codes as well as your own error messages.正如本文开头所看到的,异常类包含一个认证码()方法,将获取错误代码,这可以帮助你可以定义自己的错误代码,以及自己的错误信息。 This quick demonstration shows how.这显示了如何快速演示。
/*** an invalid email address ***/
$email = 'example@phpro@org' ;
try {
/*** validate the email address ***/
$db = validateEmail ( $email );
}
catch ( Exception $e )
{
/*** display the error code ***/
echo 'Error: ' . $e -> getCode ();
}
/**
*
* @validate an email
*
* @param string
*
* @throw standard exception on failure
*
*/
function validateEmail ( $email ){
if( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === FALSE )
{
throw new Exception ( "Invalid Email" , 10 );
}
}
?>
The above code returns the line:上面的代码返回行:
Error: 10错误:10
Well, big deal you say..好吧,大不了你说.. Ok, if we can define our own error codes, we can script based on thier value!好吧,如果我们可以定义自己的错误代码,脚本,我们可以根据他们的价值! The following script shows some of the possibilities.下面的脚本显示了一些可能性。
/*** an invalid email address ***/
$email = 'example@phpro@org' ;
try {
/*** validate the email address ***/
$db = validateEmail ( $email );
}
catch ( Exception $e )
{
/*** display the error code ***/
switch ( $e -> getCode ()) {
case 0 :
echo 'Handle error here' ;
break;
case 10 :
echo 'Handle error condition here' ;
break;
case 20 :
echo "handle other condition here" ;
break;
default:
echo 'some default handler here' ;
}
}
/**
*
* @validate an email
*
* @param string
*
* @throw standard exception on failure
*
*/
function validateEmail ( $email ){
if( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === FALSE )
{
throw new Exception ( "Invalid Email" , 10 );
}
}
?>