Я видел варианты этого кода повсюду, включая много сообщений SO:
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()
котором говорится: «Connection failed … Access denied for user blah», я получаю 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
класса myerror
?
Это сообщение … PHP, PDO и Исключения … кажется применимым, но не объясняет многое. Является ли catch (PDOException $e)
устаревшим или дисфункциональным при определенных обстоятельствах? Как я могу заставить это работать?
Причина в том, что PDO::__construct
только создает object
при успешном соединении. Поэтому, когда вы вызываете родительский конструктор, и он терпит неудачу, ваш объект больше не существует. Вы должны использовать self::myerror()
для доступа к функции ошибки статически в этом случае.
Не должно быть функции 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); }