Конструкция, расширяющая класс PDO - parent :: __ не работает, но создание нового PDO делает - PullRequest
5 голосов
/ 23 ноября 2011

Я пытаюсь написать оболочку для PDO, но у меня возникли некоторые проблемы с конструктором. В идеале я хотел бы вызвать конструктор родителя, но по какой-то причине это не работает. Я попытался (проверить), чтобы проверить, если создание нового PDO и это работает, что я нахожу наиболее запутанным.

Вот мой код:

class db extends PDO {

    private $dbconn;

    public function __construct() {
        $dsn = 'mysql:dbname=' . MYSQL_DB . ';host=' . MYSQL_HOST;
        $user = MYSQL_USER;
        $pw = MYSQL_PW;
        try {
            $this->dbconn = parent::__construct($dsn, $user, $pw);
            $this->dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $this->dbconn;
        }
        catch(PDOException $e) {
            echo 'Connection failed: ' . $e->getMessage();;
        }


    }
}

Работает, если заменить строку parent:: на $this->dbconn = new PDO($dsn, $user, $pw);

Я считаю, что «правильный / элегантный» способ сделать это - использовать синтаксис parent::, поэтому я хотел бы знать, почему это не работает / как я могу это исправить. Кто-нибудь может помочь?

Спасибо!

Ответы [ 3 ]

5 голосов
/ 23 ноября 2011

__construct() не имеет возвращаемого значения, и когда вы расширяете класс, ваш пользовательский имеет тип расширенного.Это означает (в вашем случае) объект db , равный , также объект PDO

В общем

$dsn = 'mysql:dbname=' . MYSQL_DB . ';host=' . MYSQL_HOST;
$user = MYSQL_USER;
$pw = MYSQL_PW;
parent::__construct($dsn, $user, $pw);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Это весь конструктор, который вам нужен

5 голосов
/ 23 ноября 2011

Это не то, как вы используете конструкторы, так как они ничего не возвращают.Вместо этого попробуйте следующее:

public function __construct() {
    $dsn = 'mysql:dbname=' . MYSQL_DB . ';host=' . MYSQL_HOST;
    $user = MYSQL_USER;
    $pw = MYSQL_PW;
    try {
        parent::__construct($dsn, $user, $pw);
        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch(PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();;
    }
}

ПРИМЕЧАНИЕ. Вы все еще можете столкнуться с проблемами, поскольку ваш конструктор не принимает те же аргументы, что и конструктор PDO.Одним из принципов ООП является эквивалентность, воплощенная в Принципе замены Лискова , что означает, что протокол (открытый API) подкласса должен быть строгим надмножеством своего суперкласса.Это важно по той причине, что если у подкласса есть API, который отличается от того, который представлен классом, от которого он наследует, то он не может быть использован для замены суперкласса во всех случаях.

Например, как бы вы использовали свой подкласс для подключения к базе данных PostgreSQL или использовали файл SQLite вместо mysql?Суперкласс PDO может работать со всеми тремя, наряду с другими бэкэндами базы данных, благодаря тому, что вы можете передавать DSN в качестве аргумента, но вы не можете сделать это с вашим подклассом.

Однако все это затрагивает аспекты информатики и несколько отходит от темы;)

2 голосов
/ 25 сентября 2012

Этот пример позволяет мне упростить строку подключения в моем программном обеспечении.

$db = new epdo('MyDataBase');

Он также позволяет использовать только другой сервер, имя пользователя и пароль, а также при необходимости.Надеюсь, это поможет:

class epdo extends PDO {
    public function __construct($dbname, $server='127.0.0.1', $username='usernamehere', $password='passwordhere') {
        parent::__construct("mysql:host=$server;dbname=$dbname", $username, $password);
        parent::setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

        // error reporting (only show errors on localhost)
        if( $_SERVER['SERVER_ADDR'] == '127.0.0.1') {
            parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
        } else {
            parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
        }
     }
}
...