从零开始攻略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)——错误和异常处理的更多相关文章
- 从零开始攻略PHP(5)——字符串操作与POSIX正则
一.字符串操作 1.字符串的格式化 1.1 干掉空格 trim()函数可以除去字符串开始位置和结束位置的空格,并将结果字符串返回. ltrim()函数可以除去字符串开始位置的空格. rtrim()函数 ...
- 从零开始攻略PHP(7)——面向对象(上)
1.理解面向对象的概念 面向对象软件的一个重要优点是支持和鼓励封装的能力.封装也叫数据隐藏. 在面向对象的软件中,对象是一个被保存数据和操作这些数据的操作方法的唯一.可标识的集合. 对象可以按类进行分 ...
- 从零开始攻略PHP(6)——代码重用与函数编写的一些注意事项
一个新的项目是这样创建的:它将已有的可重新利用的组件进行组合,并将新的开发难度降低到最小. 代码重用的好处:降低成本.提升可靠性和一致性. 1.使用require()和include()函数 使用一条 ...
- 从零开始攻略PHP(8)——面向对象(下)
8.编写代码类 每个分离的函数可以执行一个明确的任务.任务越简单,编写与测试这个函数就越简单,当然也不要将这个函数分得太小——若将程序分成太多的小个体,读起来就会很困难. 使用继承可以重载操作.我们可 ...
- 从零开始攻略PHP(4)——数组的使用
1.数组的概念 数组就是一个用来存储一系列变量值的命名区域. 每个数组元素有一个相关的索引(也成为关键字),它可以用来访问元素. PHP允许间隔性地使用数字或字符串作为数组的索引. 2.数字索引数组 ...
- PHP学习(9)——错误和异常处理
1.Exception类 这个类是PHP为异常处理提供的内置类.构造函数的两个参数分别是错误消息和错误代码. 除了构造函数之外,该类还提供了如下的内置方法: · getCode() 返回传递给构造函数 ...
- 【JAVA EE企业级开发四步走完全攻略】
本文是J2EE企业级开发四步走完全攻略索引,因内容比较广泛,涉及整个JAVA EE开发相关知识,这是一个长期的计划,单个发blog比较零散,所以整理此索引,决定以后每发一季JAVA EE blog后会 ...
- 主程的晋升攻略(4):TCP、消息分包和协议设计
在<主程的晋升攻略(3):IP.DNS和CDN>中,一次网络请求经过DNS解析知道了目的IP,如今就要发出网络包,这里我们说一说TCP的相关话题. TCP是一种流式协议 讲网络编程的教科书 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
随机推荐
- PHP程序员函数注释规格(麻烦大家遵守)
PHP程序员函数注释规格(麻烦大家遵守) 以前我也不愿意写注释,但是2个月后发现自己写的什么都不知道了.. 为了宇宙的发展,为了二次开发的便捷,为了代码的可读性,建议大家把注释写好.. <? ...
- CentOS安装TortoiseSVN svn 客户端
CentOS安装TortoiseSVN svn 客户端 一.CentOS安装TortoiseSVN yum install -y subversion 二.SVN客户端命令 1.查看帮助 命令:s ...
- BundleConfig 的使用 通配符
//是不是说一定要是前缀文件呢 OK 通过 通配符只能使用在前缀或后缀 //捆绑名称 bundles.Add(new StyleBundle("~/caijinhao/caijinhao&q ...
- 11.PHP内核探索:嵌入式PHP PHP内核探索:嵌入式PHP
从PHP源码目录结构的介绍以及PHP生命周期可知:嵌入式PHP类似CLI,也是SAPI接口的另一种实现. 一般情况下,它的一个请求的生命周期也会和其它的SAPI一样:模块初始化=>请求初始化=& ...
- 在Delphi中如何控制其它应用程序窗口
在编写Delphi的应用程序中,常常涉及对其它Windows应用程序的操作.例如,在数据库的管理系统中,财务人员需要使用计算器,即可调用Windows内含的计算器功能,若每次使用,均通过“开始/程序/ ...
- 数据库CRUD操作:C:create创建(添加)、R:read读取、U:update:修改、D:delete删除;高级查询
1.注释语法:--,#2.后缀是.sql的文件是数据库查询文件3.保存查询4.在数据库里面 列有个名字叫字段 行有个名字叫记录5.一条数据即为表的一行 CRUD操作:create 创建(添加)re ...
- javascript小实例,PC网页里的拖拽
几年前,我参与设计开发一个房产网的项目,我负责前端工作,由于项目经理要求比较高,参考了很多房产类网站比较优秀的功能,想把别人比较优秀的设计和想法集合到一起,那时的设计稿和功能实现,简直就是改了又改,今 ...
- 12 Most Useful Google Chrome Browser chrome:// Commands
1. chrome://flags 2. chrome://memory 3. chrome://about 4:chrome://net-internals 5:chrome://webrtc-in ...
- Intersection of Two Linked Lists | LeetCode
利用两个栈,然后分别存储每一个链表. 继而,相继pop相同的节点. 有些细节需要注意,请看最后的返回值是如何处理的. /** * Definition for singly-linked list. ...
- 从高版本JDK换成低版本JDK报错Unsupported major.minor version 52.0
ava.lang.UnsupportedClassVersionError: PR/Sort : Unsupported major.minor version 52.0这个错误是由于高版本的java ...