PDOException 类

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

介绍

表示由 PDO 引发的错误。您不应该从自己的代码中抛出 PDOException。有关 PHP 中异常的更多信息,请参见 异常

类概要

class PDOException extends RuntimeException {
/* 属性 */
protected int|string $code;
public ?array $errorInfo = null;
/* 继承的属性 */
protected string $message = "";
private string $string = "";
protected int $code;
protected string $file = "";
protected int $line;
private array $trace = [];
private ?Throwable $previous = null;
/* 继承的方法 */
public Exception::__construct(string $message = "", int $code = 0, ?Throwable $previous = null)
final public Exception::getCode(): int
final public Exception::getFile(): string
final public Exception::getLine(): int
final public Exception::getTrace(): array
}

属性

errorInfo

对应于 PDO::errorInfo()PDOStatement::errorInfo()

code

SQLSTATE 错误代码。使用 Exception::getCode() 来访问它。

添加注释

用户贡献的注释 5 个注释

Typer85 at gmail dot com
14 年前
关于 PDOException 有一个有趣的事情,它涉及 PHP 动态特性带来的某些烦恼。

PDOException 继承自 RuntimeException,后者又继承自 Exception。因此,它可以访问 $code 受保护的类变量,该变量表示异常的代码,是一个整数(很明显!),可以通过 Exception::getCode 方法从外部访问。

有趣的是,PDOException 实际上将 $code 重定义为一个字符串,而不是一个整数,因为对于它的情况,$code 实际上包含异常的 SQL 状态,该状态由字符和数字组成。

手册中实际上记录了 $code 是一个字符串而不是一个整数,但它可能并不立即清楚,因为 PDOException::getCode 被记录为返回一个整数,而不是一个字符串!

一些开发者喜欢捕获 PDOException 并将其重新抛出为一个不同的异常,如果他们在外部库中包装了他们的数据库调用。例如,请考虑以下代码

<?php

try {
$PDO = new PDO( '...' ); // PDO 驱动程序 DSN。抛出 PDOException。
}
catch(
PDOException $Exception ) {
// PHP 致命错误。第二个参数必须是整数,但 PDOException::getCode 返回一个
// 字符串。
throw new MyDatabaseException( $Exception->getMessage( ) , $Exception->getCode( ) );
}

?>

小心的是,在将返回的值传递给异常构造函数作为参数之前,必须将 PDOException::getCode 返回的值类型转换为整数。以下将起作用

<?php

try {
$PDO = new PDO( '...' ); // PDO 驱动程序 DSN。抛出 PDOException。
}
catch(
PDOException $Exception ) {
// 注意类型转换为整数!
throw new MyDatabaseException( $Exception->getMessage( ) , (int)$Exception->getCode( ) );
}

?>

希望这能为一些开发者节省一些令人沮丧的时间,免受原本令人愉快的工作的困扰 :)。

祝好,
radu.potop at wooptoo.com
10 年前
由于 PDOException 将错误代码返回为字符串,因此如果您希望将 PDOException 重新抛出为自定义异常,则需要像下面这样的构造函数。
此构造函数不调用父类的 __construct,这将对错误代码强制执行 int 类型,而是直接在自定义异常对象上设置消息和代码作为属性。

<?php

class CustomException extends PDOException {

/**
* 覆盖构造函数并设置消息和代码属性。
* 解决 PHP 漏洞 #51742、#39615
*/
public function __construct($message=null, $code=null) {
$this->message = $message;
$this->code = $code;
}

}
samuelelliot+php dot net at gmail dot com
14 年前
PDOException 有两种方法可以检索有关错误的信息。在解释 PDOException 时,我遇到了一个问题,getCode() 提供的错误代码毫无意义。我已经找到了一个方法来使错误代码和消息更加可用。

错误的用户名或密码通常会提供以下内容

代码:0
消息:“SQLSTATE[28000] [1045] 拒绝用户 'user'@'example.com' 的访问权限(使用密码:YES)”

使用我扩展的异常类提供

代码:“28000”
消息:“拒绝用户 'user'@'example.com' 的访问权限(使用密码:YES)”

<?php
class pdoDbException extends PDOException {

public function
__construct(PDOException $e) {
if(
strstr($e->getMessage(), 'SQLSTATE[')) {
preg_match('/SQLSTATE\[(\w+)\] \[(\w+)\] (.*)/', $e->getMessage(), $matches);
$this->code = ($matches[1] == 'HT000' ? $matches[2] : $matches[1]);
$this->message = $matches[3];
}
}
}
?>

解释一下这个方法;首先检查消息的开头是否有 SQLSTATE 文本。如果存在该文本,则解析消息以提取 ANSI 代码、SQL 特定代码和消息。解析后的值存储在其各自的变量中。错误代码变量存储 ANSI 代码,除非 ANSI 为 'HT000'(未映射的错误代码),否则使用 SQL 特定代码。

使用这个类很简单;与 PDO 交互时,使用 try catch 块集,如下所示

<?php
try {
$pdo = new PDO($dns, $username, $password, $options);
} catch (
PDOException $e) {
throw new
pdoDbException($e);
}
?>

现在您可以使用正常的错误方法来检索真实的错误代码和消息。

<?php
echo $err->getCode(); // 输出:"28000"
echo $err->getMessage(); // 输出:"拒绝用户 'user'@'example.com' 的访问权限(使用密码:YES)"
?>

如果您决定使用此代码,请注意错误代码是一个字符串(与 PHP 标准错误是整数相反),因为一些错误代码是字母数字的。
jesse dot chisholm at gmail dot com
9 年前
回复 2010 年 5 月 15 日 07:45 来自:samuelelliot+php dot net at gmail dot com 的留言

由于最基本的 Exception 类接受三个参数,而之前的异常不是第一个,...
由于继承的类不会隐式调用父构造函数,...

我建议将他的构造函数更改为以下内容

public function __construct(string $message = "", int $code = 0, PDOException $e = null)
{
// 以防他们调用:new MyException($somePDOException);
// 而不是遵循接口。
//
if (is_subclass_of($message, PDOException))
{
$e = $message;
$code = $e->getCode();
$message = $e->getMessage();
}

// 让 PDOException 做它通常做的事情
//
parent::__construct($message, $code, $e);

// 现在要纠正代码编号。
//
$state = $this->getMessage();
if(!strstr($state, 'SQLSTATE['))
$state = $this->getCode();
if(strstr($state, 'SQLSTATE['))
{
preg_match('/SQLSTATE\[(\w+)\] \[(\w+)\] (.*)/', $state, $matches);
$this->code = ($matches[1] == 'HT000' ? $matches[2] : $matches[1]);
$this->message = $matches[3];
}
}
wes at nospampls dot org
9 年前
sqlstate 是一个十六进制整数(作为字符串)
如果您想包装 pdoexception,请使用

throw new MyDBException($pdoe->getMessage(), hexdec($pdoe->getCode()), $pdoe);
To Top