PHP学习(9)——错误和异常处理
1.Exception类
这个类是PHP为异常处理提供的内置类。构造函数的两个参数分别是错误消息和错误代码。
除了构造函数之外,该类还提供了如下的内置方法:
· getCode() 返回传递给构造函数的代码
· getMessage() 返回传递给构造函数的消息
· getFile() 返回产生异常的代码文件的完整路径
· getLine() 返回代码文件中产生异常的代码行号
· getTrace() 返回一个包含了产生异常的代码回退路径的数组
· getTraceAsString() 返回与getTrace()方向相同的信息,该信息将被格式化成一个字符串。
· _toString() 允许简单地显示一个Exception对象,并且给出以上所有方法可以提供的信息。
通过执行以下命令,可以获得相同的异常信息(以及代码回退路径):
echo $e;
回退路径显示了在发生异常时所执行的函数。
2.异常控制结构
异常处理的基本思想是代码在try代码块被调用执行。在PHP中,异常必须手动抛出。
异常控制结构:try...throw...catch
可以将多个catch代码块与一个try代码块进行关联。还可以在一个catch代码块产生新的异常。
如下代码抛出并捕获一个异常:
<?php
try {
throw new Exception("A terrible error has occurred", 42);
}
catch (Exception $e) {
echo "Exception ". $e->getCode(). ": ". $e->getMessage()."<br />".
" in ". $e->getFile(). " on line ". $e->getLine(). "<br />";
}
?>

这里我们使用了exception类的前四个方法,catch代码块报告了异常错误信息以及发生错误位置的说明。
3.用户自定义异常
可以扩展Exception类来创建自己的异常类。
可能需要继承的代码:
<?php
class Exception{
function __construct(string $message=NULL,int $code=0){
if(func_num_args()){
$this->message = $message;
}
$this->code = $code;
$this->file = __FILE__; // of throw clause
$this->line = __LINE__; // of throw clause
$this->trace = debug_backtrace();
$this->string = StringFormat($this);
} protected $message = "Unknown exception "; // exception message
protected $code = 0; // user defined exception code
protected $file; // source filename of exception
protected $line; // source line of exception private $trace; // backtrace of exception
private $string; // internal only!! final function getMessage(){
return $this->message;
}
final function getCode(){
return $this->code;
}
final function getFile(){
return $this->file;
}
final function getTrace(){
return $this->trace;
}
final function getTraceAsString(){
return self::TraceFormat($this);
}
function _toString(){
return $this->string;
}
static private function StringFormat(Exception $exception){
// ... a function not available in PHP scripts
// that returns all relevant information as a string
}
static private function TraceFormat(Exception $exception){
// ... a function not available in PHP scripts
// that returns the backtrace as a string
}
}
?>
该类的大多数公有方法都是final的:这就意味着不能重载这些方法。我们可以创建自己的Exception子类,但是不能改变这些基本方法的行为。请注意,_toString()函数可以重载,因此我们可以改变异常的显示方式。也可以添加自己的方法。
用户自定义的Exception类示例:
<?php class myException extends Exception
{
function __toString()
{
return "<table border=\"1\">
<tr>
<td><strong>Exception ".$this->getCode()."
</strong>: ".$this->getMessage()."<br />"."
in ".$this->getFile()." on line ".$this->getLine()."
</td>
</tr>
</table><br />";
}
} try
{
throw new myException("A terrible error has occurred", 42);
}
catch (myException $m)
{
echo $m;
} ?>
在以上代码中,我们声明了一个新的异常类myException,该类扩展了Exception基类。该类与Exception类之间的差异在于重载了_toString()方法,从而为打印异常提供了一个更好的方法。

4.文件I/O相关的异常
写文件时可能会出现三种情况的错误:文件无法打开、无法获得写锁或者文件无法写入。我们为每一种可能性都创建了一个异常类:
<?php class fileOpenException extends Exception
{
function __toString()
{
return "fileOpenException ". $this->getCode()
. ": ". $this->getMessage()."<br />"." in "
. $this->getFile(). " on line ". $this->getLine()
. "<br />";
}
} class fileWriteException extends Exception
{
function __toString()
{
return "fileWriteException ". $this->getCode()
. ": ". $this->getMessage()."<br />"." in "
. $this->getFile(). " on line ". $this->getLine()
. "<br />";
}
} class fileLockException extends Exception
{
function __toString()
{
return "fileLockException ". $this->getCode()
. ": ". $this->getMessage()."<br />"." in "
. $this->getFile(). " on line ". $this->getLine()
. "<br />";
}
} ?>
Exception类的这些子类并没有执行任何特别的操作。事实上,对于这个应用程序的作用来说,可以让它们成为空的子类或者使用PHP所提供的Exception类。然而,我们为每个子类提供了_toString()方法,从而可以解释所发生的异常类型:
<?php
require_once("file_exceptions.php");
// create short variable names
$tireqty = $_POST['tireqty'];
$oilqty = $_POST['oilqty'];
$sparkqty = $_POST['sparkqty'];
$address = $_POST['address'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
?>
<html>
<head>
<title>Bob's Auto Parts - Order Results</title>
</head>
<body>
<h1>Bob's Auto Parts</h1>
<h2>Order Results</h2>
<?php
$date = date('H:i, jS F');
echo "<p>Order processed at ".$date."</p>";
echo '<p>Your order is as follows: </p>';
$totalqty = 0;
$totalqty = $tireqty + $oilqty + $sparkqty;
echo "Items ordered: ".$totalqty."<br />";
if( $totalqty == 0) {
echo "You did not order anything on the previous page!<br />";
} else {
if ( $tireqty > 0 ) {
echo $tireqty." tires<br />";
}
if ( $oilqty > 0 ) {
echo $oilqty." bottles of oil<br />";
}
if ( $sparkqty > 0 ) {
echo $sparkqty." spark plugs<br />";
}
}
$totalamount = 0.00;
define('TIREPRICE', 100);
define('OILPRICE', 10);
define('SPARKPRICE', 4);
$totalamount = $tireqty * TIREPRICE
+ $oilqty * OILPRICE
+ $sparkqty * SPARKPRICE;
$totalamount=number_format($totalamount, 2, '.', ' ');
echo "<p>Total of order is ".$totalamount."</p>";
echo "<p>Address to ship to is ".$address."</p>";
$outputstring = $date."\t".$tireqty." tires \t".$oilqty." oil\t"
.$sparkqty." spark plugs\t\$".$totalamount
."\t". $address."\n";
// open file for appending
try
{
if (!($fp = @fopen("$DOCUMENT_ROOT/../orders/orders.txt", 'ab')))
throw new fileOpenException();
if (!flock($fp, LOCK_EX))
throw new fileLockException();
if (!fwrite($fp, $outputstring, strlen($outputstring)))
throw new fileWriteException();
flock($fp, LOCK_UN);
fclose($fp);
echo "<p>Order written.</p>";
}
catch (fileOpenException $foe)
{
echo "<p><strong>Orders file could not be opened.
Please contact our webmaster for help.</strong></p>";
}
catch (Exception $e)
{
echo "<p><strong>Your order could not be processed at this time.
Please try again later.</strong></p>";
}
?>
</body>
</html>
可以看到,以上脚本的文件I/O部分被封装在一个try代码块中。通常,良好的编码习惯要求try代码块的代码量较少,并且在代码块的结束处捕获相关异常。这使得异常处理代码更容易编写和维护,因为可以看到所处理的内容。
如果无法打开文件,将抛出一个fileOpenException异常;如果无法锁定该文件,将抛出一个fileLockException异常;而如果无法写这个文件,将抛出一个fileWriteException异常。
我们给出了两个catch代码块:一个用来处理fileOpen-Exception异常,而另一个用来处理Exception。由于其他异常都是从Exception继承过来的,它们将被第二个catch代码块捕获。catch代码块与每一个instanceof操作符相匹配。这就是为每一个类扩展自己异常类的理由。
如果异常没有匹配的catch语句块,PHP将报告一个致命错误。
请注意fopen()函数的调用仍然使用了@错误抑制操作符前缀。如果该函数调用失败,PHP将发出一个警告,根据php.ini中的错误报告设置不同,该警告可能会被报告或者记录。无论是否产生一个异常,这个警告仍然会发出。
好了,从零开始攻略PHP系列到这里就水完了,仅供参考,好多我也是一知半解,只是整理出来方便查阅。下个月会陆续发一些数据库的,也就是该书整理的第二篇。
整理自《PHP and MySQL Web 开发》
PHP学习(9)——错误和异常处理的更多相关文章
- ThinkPHP5.0源码学习之注册错误和异常处理机制
在base.php文件中,用一句代码\think\Error::register();实现错误和异常处理机制的注册. // 注册错误和异常处理机制 \think\Error::register(); ...
- Golang错误和异常处理的正确姿势
Golang错误和异常处理的正确姿势 错误和异常是两个不同的概念,非常容易混淆.很多程序员习惯将一切非正常情况都看做错误,而不区分错误和异常,即使程序中可能有异常抛出,也将异常及时捕获并转换成错误.从 ...
- 2018/05/02 PHP 之错误与异常处理
在学习中,越学习越觉得自己基础薄弱. 在平常工作中,对于某些错误处理感觉不知道怎么下手,于是决定重新再整理一下. 强烈推荐这篇文章,真的感觉学习到了很多. 部分引用::再谈PHP错误与异常处理 -- ...
- PHP 注册错误和异常处理机制
注册错误和异常处理机制有三个PHP函数需要学习 1. register_shutdown_function('Bootstrap\Library\Frame::fatalError'); 2. set ...
- 转 Python3 错误和异常/ Python学习之错误调试和测试
########sample 0 https://www.cnblogs.com/Simon-xm/p/4073028.html except: #捕获所有异常 except: <异常名> ...
- PHP10 错误和异常处理
学习要点 修改错误报告级别 写错误日志 异常处理实现 自定义异常 捕获多路异常 错误处理 定义 错误:开发过程中的失误.用户操作引起的错误. 错误产生原因 语法错误:开发环境提示,未修正则脚本无法 ...
- Python学习之路11☞异常处理
一 错误和异常 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 de ...
- PHP错误以及异常处理
以前一直觉得php的异常处理没有什么,现在才发现这个还真是门学问,于是狠下心来好好研究了一下,写一篇文章,也作备忘吧. 1. php错误 无论是什么语言编程,都会有如下三种错误,当然php也不例外. ...
- Yii中的错误及异常处理
Yii中的错误及异常处理 Yii已经默认已经在CApplication上实现了异常和错误的接管,这是通过php的set_exception_handler, set_error_handler实现的. ...
- 再谈PHP错误与异常处理
博客好久没有更新了,实在惭愧,最近在忙人生大事,哈哈!这段时间没有看什么新的东西,结合项目中遇到的PHP异常处理问题,我又重新梳理了之前模糊的概念,希望对大家理解PHP异常处理有所帮助. 请一定要注意 ...
随机推荐
- 多项式乘法(FFT)模板 && 快速数论变换(NTT)
具体步骤: 1.补0:在两个多项式最前面补0,得到两个 $2n$ 次多项式,设系数向量分别为 $v_1$ 和 $v_2$. 2.求值:用FFT计算 $f_1 = DFT(v_1)$ 和 $f_2=DF ...
- MacOs High Sierra 升级失败解决办法
进入recovery的方法: Command-R 重新安装您在 Mac 上安装过的最新 macOS,但不会升级到更高的版本. Option-Command-R升级到与您的 Mac 兼容的最新 macO ...
- Remove Mapping
http://social.msdn.microsoft.com/forums/vstudio/en-US/ffa3aa15-1d61-4464-ac4a-7a812d073a67/remove-ma ...
- STL中的BITSET运用
胡小兔的OI博客C++ bitset 常用函数及运算符 对于一个叫做foo的bitset: foo.size() 返回大小(位数) foo.count() 返回1的个数 foo.any() 返回是否有 ...
- 【CUDA 基础】5.6 线程束洗牌指令
title: [CUDA 基础]5.6 线程束洗牌指令 categories: - CUDA - Freshman tags: - 线程束洗牌指令 toc: true date: 2018-06-06 ...
- Win10 下载 masmplus
一.下载: masmplus链接: http://www.aogosoft.com/masmplus/
- python 输出三角形
pattern = input("请输入你要选择的模式:") while True: if pattern == "A": row = eval(input(& ...
- codeforces gym #101161H - Witcher Potion(状压DP)
题目链接: http://codeforces.com/gym/101161/attachments 题意: 总共有n瓶药可供选择 每瓶药可以增加$e_i$点体力,和$p_i$点毒性 每分钟消耗1点毒 ...
- $\LaTeX$数学公式大全
$\LaTeX$数学公式大全$1\ Geek\ and\ Hebrew\ letters$ $\LaTeX$数学公式大全$2\ Math\ Constructs$ $\LaTeX$数学公式大全$3\ ...
- uni-app 的更新及碰到的问题
uni-app 的更新 我这个是针对 app 的测试,没有考虑 小程序 及 h5,如需考虑请参考 uni-app 的条件编译 当我们将文件打包好之后,我们在手机上就可以下载 apk 文件,安装到我们的 ...