本文面向希望了解PHP5异常处理机制的程序员。阅读本文你需要具有一定面向对象编程和PHP基础。
PHP5内建的异常类需要有以下成员方法:
__construct()构造函数,需要一个出错信息和一个可选的整型错误标记作参数getMessage()取得出错信息 getCode()
出错的代码 getFile()异常发生的文件getLine()异常发生的行数 getTrace()跟踪异常每一步传递的路线,存入数组,返回该数组 getTraceAsString()和getTrace()功能一样,但可以将数组中的元素转成字符串并按一定格式输出
可以看出来,Exception 类的结构和Pear_Error 很相似。当你的脚本中遇到一个错误,你可以建立你的异常对象:
$ex = new Exception( "Could not open $this->file" );
throw new Exception( "my message", 44 );
<?php // PHP 5
require_once('cmd_php5/Command.php');
class CommandManager {
private $cmdDir = "cmd_php5";
function getCommandObject($cmd) {
$path = "{$this->cmdDir}/{$cmd}.php";
if (!file_exists($path)) {
throw new Exception("Cannot find $path");
}
require_once $path;
if (!class_exists($cmd)) {
throw new Exception("class $cmd does not exist");
}
$class = new ReflectionClass($cmd);
if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
throw new Exception("$cmd is not a Command");
}
return new $cmd();
}
}
?>
Fatal error: Uncaught exception 'Exception' with message 'Cannot find command/xrealcommand.php' in /home/xyz/BasicException.php:10
Stack trace:
#0 /home/xyz/BasicException.php(26):
CommandManager->getCommandObject('xrealcommand')
#1 {main}
thrown in /home/xyz/BasicException.php on line 10
<?php
// PHP 5
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
} catch (Exception $e) {
print $e->getMessage();
exit();
}
?>
可以看到,通过结合使用throw关键字和try-catch语句,我们可以避免错误标记“污染”类方法返回的值。因为“异常”本身就是一种与其它任何对象不同的PHP内建的类型,不会产生混淆。
如果抛出了一个异常,try语句中的脚本将会停止执行,然后马上转向执行catch语句中的脚本。
如果异常抛出了却没有被捕捉到,就会产生一个fatal error。
处理多个错误
在目前为止异常处理看起来和我们传统的作法—检验返回的错误标识或对象的值没有什么太大区别。让我们将CommandManager处理地更谨慎,并在构造函数中检查command目录是否存在。
index_php5_2.php
<?php
// PHP 5
require_once('cmd_php5/Command.php');
class CommandManager {
private $cmdDir = "cmd_php5";
function __construct() {
if (!is_dir($this->cmdDir)) {
throw new Exception("directory error: $this->cmdDir");
}
}
function getCommandObject($cmd) {
$path = "{$this->cmdDir}/{$cmd}.php";
if (!file_exists($path)) {
throw new Exception("Cannot find $path");
}
require_once $path;
if (!class_exists($cmd)) {
throw new Exception("class $cmd does not exist");
}
$class = new ReflectionClass($cmd);
if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
throw new Exception("$cmd is not a Command");
}
return new $cmd();
}
}
?>
<?php
// PHP 5
try {
$mgr = new CommandManager(); // potential error
$cmd = $mgr->getCommandObject('realcommand');
// another potential error
$cmd->execute();
} catch (Exception $e) {
// handle either error here
print $e->getMessage();
exit();
}
?>
<?php
// PHP 5
require_once('cmd_php5/Command.php');
class CommandManager {
private $cmdDir = "cmd_php5";
const CMDMAN_GENERAL_ERROR = 1;
const CMDMAN_ILLEGALCLASS_ERROR = 2;
function __construct() {
if (!is_dir($this->cmdDir)) {
throw new Exception("directory error: $this->cmdDir", self::CMDMAN_GENERAL_ERROR);
}
}
function getCommandObject($cmd) {
$path = "{$this->cmdDir}/{$cmd}.php";
if (!file_exists($path)) {
throw new Exception("Cannot find $path", self::CMDMAN_ILLEGALCLASS_ERROR);
}
require_once $path;
if (!class_exists($cmd)) {
throw new Exception("class $cmd does not exist", self::CMDMAN_ILLEGALCLASS_ERROR);
}
$class = new ReflectionClass($cmd);
if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
throw new Exception("$cmd is not a Command", self::CMDMAN_ILLEGALCLASS_ERROR);
}
return $class->newInstance();
}
}
?>
<?php // PHP 5
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
} catch (Exception $e) {
if ($e->getCode() == CommandManager::CMDMAN_GENERAL_ERROR) {
// no way of recovering
die($e->getMessage());
} else if ($e->getCode() == CommandManager::CMDMAN_ILLEGALCLASS_ERROR) {
error_log($e->getMessage());
print "attempting recovery/n";
// perhaps attempt to invoke a default command?
}
}
?>
<?php
// PHP 5
require_once('cmd_php5/Command.php');
class CommandManagerException extends Exception{}
class IllegalCommandException extends Exception{}
class CommandManager {
private $cmdDir = "cmd_php5";
function __construct() {
if (!is_dir($this->cmdDir)) {
throw new CommandManagerException("directory error: $this->cmdDir");
}
}
function getCommandObject($cmd) {
$path = "{$this->cmdDir}/{$cmd}.php";
if (!file_exists($path)) {
throw new IllegalCommandException("Cannot find $path");
}
require_once $path;
if (!class_exists($cmd)) {
throw new IllegalCommandException("class $cmd does not exist");
}
$class = new ReflectionClass($cmd);
if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
throw new IllegalCommandException("$cmd is not a Command");
}
return $class->newInstance();
}
}
?>
<?php // PHP 5
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
} catch (CommandManagerException $e) {
die($e->getMessage());
} catch (IllegalCommandException $e) {
error_log($e->getMessage());
print "attempting recovery/n";
// perhaps attempt to invoke a default command?
} catch (Exception $e) {
print "Unexpected exception/n";
die($e->getMessage());
}
?>
<?php
// PHP 5
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
} catch (Exception $e) {
print "Unexpected exception/n";
die($e->getMessage());
} catch (CommandManagerException $e) {
die($e->getMessage());
} catch (IllegalCommandException $e) {
error_log($e->getMessage());
print "attempting recovery/n";
// perhaps attempt to invoke a default command?
}
?>
<?php
// PHP 5
class RequestHelper {
private $request = array();
private $defaultcmd = 'defaultcmd';
private $cmdstr;
function __construct($request_array=null) {
if (!is_array($this->request = $request_array)) {
$this->request=$_REQUEST;
}
}
function getCommandString() {
return ($this->cmdstr ? $this->cmdstr : ($this->cmdstr=$this->request['cmd']));
}
function runCommand() {
$cmdstr = $this->getCommandString();
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject($cmdstr);
$cmd->execute();
} catch (IllegalCommandException $e) {
error_log($e->getMessage());
if ($cmdstr != $this->defaultcmd) {
$this->cmdstr = $this->defaultcmd;
$this->runCommand();
} else {
throw $e;
}
} catch (Exception $e) {
throw $e;
}
}
}
$helper = new RequestHelper(array(cmd=>'realcommand'));
$helper->runCommand();
?>
} catch (Exception $e) {
throw $e;
}
return $class->newInstance();
<?php
// PHP 5
class Front {
static function main() {
try {
$helper = new RequestHelper(array(cmd=>'realcommand'));
$helper->runCommand();
} catch (Exception $e) {
print "<h1>".get_class($e)."</h1>/n";
print "<h2>{$e->getMessage()}
({$e->getCode()})</h2>/n/n";
print "file: {$e->getFile()}<br />/n";
print "line: {$e->getLine()}<br />/n";
print $e->getTraceAsString();
die;
}
}
}
Front::main();
?>
ReflectionException Access to non-public constructor of class realcommand (0)
file: c:/MyWEB/Apache/htdocs/php5exception/index_php5_4.php
line: 31
#0 c:/MyWEB/Apache/htdocs/php5exception/index_php5_5.php(25): CommandManager->getCommandObject()
#1 c:/MyWEB/Apache/htdocs/php5exception/index_php5_6.php(10): RequestHelper->runCommand('realcommand')
#2 c:/MyWEB/Apache/htdocs/php5exception/index_php5_6.php(23): Front::main()
#3 {main}