@vadi_kot

PHP PDO Ошибка соединения с БД: SQLSTATE[HY000]: General error: could not call class constructor?

Есть два класса, один с подключением к бд и дочерний с выводом юзеров, при выводе данных падает ошибка: SQLSTATE[HY000]: General error: could not call class constructor
класс db
class db
{
    private static $dbh;

    public static function getDbh()
    {
        try {
            self::$dbh = new PDO('mysql:host=localhost;dbname=pdo_dev;charset=utf8', 'root', 'root');
            self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
    catch (PDOException $e) {
            echo "Ошибка соединения с БД: ".$e->getMessage();
        }
    }

    public static function querySelect($query,$class)
    {
        self::getDbh();
        $sth = self::$dbh->prepare($query);
        $sth->execute();
        $result = $sth->fetchAll(PDO::FETCH_CLASS, $class);
        return $result;
    }
}


класс user
class user extends db
{
    protected $id;
    protected $name;

   function __construct($id,$name)
    {
        $this->id=$id;
        $this->name=$name;
    }

    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }


    public static function getUsers()
    {
        $query="SELECT * FROM user";
        $result = self::querySelect($query,__CLASS__);
        return $result;
    }
}

Ошибка падает в строке $result = self::querySelect($query,__CLASS__);
Если из класса user убрать конструктор, то все работает корректно, создаются объекты и выводит все данные, но стоит добавить конструктор, как начинает вылетать такая ошибка, может кто-нибудь подсказать в чем проблема и как исправить эту ошибку?
Код в исполняемом файле:
$result = user::getUsers();
    foreach ($result as $item) {
        echo $item->getName()."<br />";
    }
  • Вопрос задан
  • 739 просмотров
Пригласить эксперта
Ответы на вопрос 3
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Вы в дочернем классе user определили явный конструктор, поэтому конструктор родительского класса db автоматически не вызывается. Добавьте в конструктор класса user явный вызов parent::__construct();
Ответ написан
FanatPHP
@FanatPHP
Чебуратор тега РНР
Следует отметить, что у этого класса очень много других проблем.

1. Статическая функция для коннекта это картннный буратино, который никакой полезной функции не выполняет, а выполняет только вредную, каждый раз заново соединяясь с базой дынных. Надо хотя бы проверять, еслть ли уже соединение, и возвращать его.
2. prepare с пустым execute - это картннный буратино, который никакой полезной функции не выполняет, а выполняет только вредную, пропуская все инъекции на свете. В prepare надо передавать запрос с плейсхолдерами, а execute массив с переменными для замены.
3. echo "Ошибка соединения с БД: " - это это картннный буратино, который никакой полезной функции не выполняет, а выполняет только вредную. Пользователь из сообщения об ошибке ничего не поймет, а программист о ней ничего не узнает. Для вывода ошибок try должен быть один, глобальный, и выводить их в зависимости от окружения - на домашнем компике можно вываливать прямо на экран, а на боевом сервере только логировать.
4. Пользователь - это не база данных. Поэтому наследовать классу БД он не должен. и уж тем более нет ни малейшего смысла наследовать класс со статическими методами. Объект для работы с БД надо передавать в конструктор и присваивать переменной класса. Либо если это тупой синглтон, то ничего вообще не передавать, а просто вызывать его методы где надо, хотя это неправильно.

Подробне читать здесь (можно через гуглопереводчик)
https://phpdelusions.net/pdo/common_mistakes
https://phpdelusions.net/articles/error_reporting
Ответ написан
Комментировать
При использовании PDO::FETCH_CLASS в результате выборки создаётся новый объект указанного класса. Свойствам объекта будут присвоены значения столбцов, имена которых совпадут с именами свойств. При этом значения назначаются свойствам объекта ДО вызова конструктора. Если свойства с именами, соответствующими названиям столбцов, не существуют, они будут созданы автоматически (с областью видимости public).

Если ваши данные нуждаются в обязательной обработке сразу после их получения из базы данных, ее можно реализовать в конструкторе класса.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы