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异常处理有所帮助. 请一定要注意 ...
随机推荐
- Git始终忽略特定文件的某一行内容
笔者在编写Z Shell文件的时候经常会使用到set -x来开启调试,但不希望提交到仓库 解决方案 Git提供了一种文件过滤器,此方法可以帮助在提交时移除set -x 我们先来编写脚本,如何移除这一行 ...
- [Javascript] How to deal with floating number
What's your expect of the output?: console.log(0.1 + 0.2 === 0.3); The answer is 'false'. Because: 0 ...
- [Spring Boot] Set Context path for application in application.properties
If you were using Microservice with Spring Boot to build different REST API endpoints, context path ...
- javascript内置对象一: Array数组
在JavaScript中的任何事物,字符串,数组,函数等等都是对象. 理解:浏览器自己封装好的对象,可以直接使用. push /pʊʃ/ 增加 在末尾增加 unshif ...
- (十八)链接数据库,QSqlTableModel
QMYSQL——mysql QSQLITE——sqlite QOICQ——orcale 所需头文件 .pro增加 sql #include <QSqlDatabase> #include ...
- jQuery系列(十一):jQuery的事件绑定和解绑
1.绑定事件 语法: bind(type,data,fn) 描述:为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数. 参数解释: type (String) : 事件类型 data ( ...
- vue-element-admin登录逻辑,以及动态添加路由,显示侧边栏
这段时间在研究element-admin,感觉这个库有许多值得学习的地方,我学习这个库的方法是,先看它的路由,顺着路由,摸清它的逻辑,有点像顺藤摸瓜. 这个库分的模块非常清晰,适合多人合作开发项目,但 ...
- kong-dashbord本地安装gulp打包报错的解决办法
本地安装kong-dashbord执行npm run build 报如下错误 gulp[]: ../src/node_contextify.cc::]->IsString()' failed. ...
- Vue小实例
最近刚学习Vue的官方文档,了解了指令.模板.组件.数据双向绑定等有关Vue的知识点.因此估摸着做点实例出来练练手. 下面介绍一个简单的例子,模拟购物车自动统计金额,效果图如下: 代码如下: < ...
- 2016 Multi-University Training Contest 1 部分题解
第一场多校,出了一题,,没有挂零还算欣慰. 1001,求最小生成树和,确定了最小生成树后任意两点间的距离的最小数学期望.当时就有点矛盾,为什么是求最小的数学期望以及为什么题目给了每条边都不相等的条件. ...