扩展异常

可以通过扩展内置的 Exception 类来定义用户定义的异常类。以下成员和属性展示了从内置的 Exception 类派生的子类中可访问的内容。

示例 #1 内置的 Exception 类

<?php
class Exception implements Throwable
{
protected
$message = 'Unknown exception'; // 异常消息
private $string; // __toString 缓存
protected $code = 0; // 用户定义的异常代码
protected $file; // 异常的源文件名
protected $line; // 异常的源行号
private $trace; // 回溯
private $previous; // 如果是嵌套异常,则为上一个异常

public function __construct($message = '', $code = 0, Throwable $previous = null);

final private function
__clone(); // 禁止克隆异常。

final public function getMessage(); // 异常消息
final public function getCode(); // 异常代码
final public function getFile(); // 源文件名
final public function getLine(); // 源行号
final public function getTrace(); // 回溯的数组
final public function getPrevious(); // 上一个异常
final public function getTraceAsString(); // 回溯的格式化字符串

// 可覆盖
public function __toString(); // 用于显示的格式化字符串
}
?>

如果一个类扩展了内置的 Exception 类并重新定义了 构造函数,则强烈建议它也调用 parent::__construct(),以确保所有可用数据都已正确分配。可以覆盖 __toString() 方法,以便在对象作为字符串显示时提供自定义输出。

注意:

异常不能被克隆。尝试 克隆 异常将导致致命错误 E_ERROR

示例 #2 扩展 Exception 类

<?php
/**
* 定义自定义异常类
*/
class MyException extends Exception
{
// 重新定义异常,使其消息不再可选
public function __construct($message, $code = 0, Throwable $previous = null) {
// 一些代码

// 确保所有内容都正确赋值
parent::__construct($message, $code, $previous);
}

// 对象的自定义字符串表示形式
public function __toString() {
return
__CLASS__ . ": [{$this->code}]: {$this->message}\n";
}

public function
customFunction() {
echo
"此类异常的自定义函数\n";
}
}


/**
* 创建一个类来测试异常
*/
class TestException
{
public
$var;

const
THROW_NONE = 0;
const
THROW_CUSTOM = 1;
const
THROW_DEFAULT = 2;

function
__construct($avalue = self::THROW_NONE) {

switch (
$avalue) {
case
self::THROW_CUSTOM:
// 抛出自定义异常
throw new MyException('1 是一个无效的参数', 5);
break;

case
self::THROW_DEFAULT:
// 抛出默认异常
throw new Exception('2 不允许作为参数', 6);
break;

default:
// 没有异常,将创建对象
$this->var = $avalue;
break;
}
}
}


// 示例 1
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (
MyException $e) { // 将被捕获
echo "捕获到我的异常\n", $e;
$e->customFunction();
} catch (
Exception $e) { // 跳过
echo "捕获到默认异常\n", $e;
}

// 继续执行
var_dump($o); // 空值
echo "\n\n";


// 示例 2
try {
$o = new TestException(TestException::THROW_DEFAULT);
} catch (
MyException $e) { // 不匹配此类型
echo "捕获到我的异常\n", $e;
$e->customFunction();
} catch (
Exception $e) { // 将被捕获
echo "捕获到默认异常\n", $e;
}

// 继续执行
var_dump($o); // 空值
echo "\n\n";


// 示例 3
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (
Exception $e) { // 将被捕获
echo "捕获到默认异常\n", $e;
}

// 继续执行
var_dump($o); // 空值
echo "\n\n";


// 示例 4
try {
$o = new TestException();
} catch (
Exception $e) { // 跳过,没有异常
echo "捕获到默认异常\n", $e;
}

// 继续执行
var_dump($o); // TestException
echo "\n\n";
?>
添加备注

用户贡献的备注 8 个备注

iamhiddensomewhere at gmail dot com
14 年前
如前所述,异常链接最近已添加(真是太棒了,它确实使层抽象(以及相关的异常跟踪)变得更容易)。

由于 <5.3 缺少此有用功能,我主动创建了一个自定义异常类,我的所有异常都继承自该类

<?php

class SystemException extends Exception
{
private
$previous;

public function
__construct($message, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code);

if (!
is_null($previous))
{
$this -> previous = $previous;
}
}

public function
getPrevious()
{
return
$this -> previous;
}
}

?>

希望您觉得它有用。
Hayley Watson
5 年前
检查其他 SPL 异常类,如果您的目标异常是其中一个类的子类,则扩展其中一个类。这在捕获时允许更精细的控制。
michaelrfairhurst at gmail dot com
11 年前
自定义异常类允许您编写测试来证明您的异常
是有意义的。通常在测试异常时,您要么断言消息等于
某些东西,在这种情况下,您无法更改消息格式而无需重构,
要么根本不做任何断言,在这种情况下,您可能会在以后获得误导性的消息
在生产环境中。尤其是在您的 $e->getMessage 是比较复杂的东西时
像 var_dump'ed 上下文数组。

解决方案是将错误信息从 Exception 类抽象到
可以在所有地方进行测试的属性,除了用于格式的测试。

<?php

class TestableException extends Exception {

private
$property;

function
__construct($property) {

$this->property = $property;
parent::__construct($this->format($property));

}

function
format($property) {
return
"I have formatted: " . $property . "!!";
}

function
getProperty() {
return
$this->property;
}

}

function
testSomethingThrowsTestableException() {
try {
throw new
TestableException('Property');
} Catch (
TestableException $e) {
$this->assertEquals('Property', $e->getProperty());
}
}

function
testExceptionFormattingOnlyOnce() {
$e = new TestableException;
$this->assertEquals('I have formatted: properly for the only required test!!',
$e->format('properly for the only required test')
);
}

?>
sapphirepaw.org
14 年前
PHP 5.3.0 版本中添加了对异常链接的支持。在旧版本的 PHP 中,getPrevious() 方法和构造函数中的 $previous 参数在任何内置异常中都不可用。
Dor
12 年前
需要注意的是,Exception 类的子类将被默认的 Exception 处理程序捕获。

<?php

/**
* NewException
* 扩展 Exception 类,使 $message 参数现在是强制性的。
*
*/
class NewException extends Exception {
//$message 现在不是可选的,只是为了扩展。
public function __construct($message, $code = 0, Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
}

/**
* TestException
* 测试并抛出异常。
*/
class TestException {
const
NONE = 0;
const
NORMAL = 1;
const
CUSTOM = 2;
public function
__construct($type = self::NONE) {
switch (
$type) {
case
1:
throw new
Exception('Normal Exception');
break;
case
2:
throw new
NewException('Custom Exception');
break;
default:
return
0; //不抛出异常。
}
}
}

try {
$t = new TestException(TestException::CUSTOM);
}
catch (
Exception $e) {
print_r($e); //捕获异常
}

?>

注意,如果异常被捕获一次,它将不会再次被捕获(即使是更具体的处理程序)。
shaman_master at list dot ru
9 年前
使用此示例进行非数字代码
<code>
<?php
class MyException extends Exception
{
/**
* 创建一个新的异常。
*
* @param string $message 错误消息
* @param mixed $code 异常代码
* @param Exception $previous 之前的异常
* @return void
*/
public function __construct($message = '', $code = 0, Exception $previous = null)
{
// 将消息和整数代码传递给父级
parent::__construct((string)$message, (int)$code, $previous);

// @link http://bugs.php.net/39615 保存未修改的代码
$this->code = $code;
}
}
</
code>
florenxe
8 年前
我只想补充一点,“extends” 与“Inheritance”(继承)或“Prototyping in Javascript”(JavaScript 原型)的概念相同。因此,当您扩展一个类时,您只是继承了该类的 方法和属性。所以您可以从现有类创建自定义类,例如扩展数组类。
paragdiwan at gmail dot com
15 年前
我已经编写了类似的简单的自定义异常类。对新手很有帮助。
<?php
/*
这是为覆盖异常而编写的。
自定义异常类
*/
error_reporting(E_ALL-E_NOTICE);
class
myCustomException extends Exception
{

public function
__construct($message, $code=0)
{
parent::__construct($message,$code);
}

public function
__toString()
{
return
"<b style='color:red'>".$this->message."</b>";
}


}

class
testException
{

public function
__construct($x)
{

$this->x=$x;

}

function
see()
{


if(
$this->x==9 )
{
throw new
myCustomException("i didnt like it");
}
}
}

$obj = new testException(9);
try{

$obj->see();
}
catch(
myCustomException $e)
{
echo
$e;
}
?>
To Top