PDO catch PDOException在构造时失败

时间:2013-06-24 06:30:32

标签: php class pdo

我已经看到了这个代码的变体,包括许多S.O.帖子:

class db extends PDO {

    public function __construct( $dbconf ) {
        $options = array(
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_PERSISTENT => $dbconf['persist'] ? true : false
            );
        try {
            parent::__construct('mysql:host='. $dbconf['dbhost'] .';port=3306;dbname='. $dbconf['dbname'] .';' , $dbconf['dbuser'],
                $dbconf['dbpass'],
                $options);
        } catch (PDOException $e) {
            $this->myerror( $e->getMessage() );
            // echo 'Connection failed ... '. $e->getMessage();
        }
    }

    ...

    private function myerror( $error ) {
        echo 'Connection failed ... '. $error;
    }

}

该类使用$db = new db( $config );进行实例化,如果连接有效,它可以正常工作,但如果连接失败,PDOException似乎无法正常工作。 catch完全无法执行$this->myerror(...)功能!而不是有用的$e->getMessage()表示“连接失败...用户拒绝访问权限”,我得到PHP Fatal error: Call to a member function myerror() on a non-object in /.../lib/pdo.class.php on line 16

如果我在catch中注释掉第一行并取消注释echo,它会按预期工作,报告连接错误的原因。为什么消息在catch中可用,而在简单的myerror类函数中不可用?

这篇帖子...... PHP, PDO, and Exceptions ......似乎是适用的,但并没有多解释。在某些情况下,catch (PDOException $e)是否已过时或功能失调?我如何继续这项工作?

2 个答案:

答案 0 :(得分:1)

原因是PDO::__construct仅在成功连接时创建object。因此,当您调用父构造函数并且它失败时,您的对象将不再存在。在这种情况下,您应该使用self::myerror()静态访问错误功能。

答案 1 :(得分:1)

根本不应该有myerror()功能。数据库层几乎不需要它自己的错误处理程序。 构造函数必须是

public function __construct( $dbconf ) {
    $dsn  = "mysql:";
    $dsn .= "host=".   $dbconf['dbhost'].";";
    $dsn .= "dbname=". $dbconf['dbname'].";";
    $dsn .= "port=".   $dbconf['dbport'].";";
    $dsn .= "charset=".$dbconf['dbcharset'];
    $options = array(
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES '.$dbconf['charset'],
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_PERSISTENT         => (bool)$dbconf['persist'],
    );
    parent::__construct($dsn, $dbconf['dbuser'], $dbconf['dbpass'],$options);
}