Как добавить в дочерний класс функцию с PDO?

И снова здравствуйте, не могу разобраться.. Имеется несколько классов:
class Database {
    private $dbhost = '';
    private $dbuser = '';
    private $dbpass = '!';
    private $dbname = '';
    private $dbcharset = '';
    public $dbh;
    
    function connect() {
        try {
            $this->dbh = new PDO('mysql:host='.$this->dbhost.';dbname='.$this->dbname.';charset='.$this->dbcharset, $this->dbuser, $this->dbpass, array(PDO::ATTR_PERSISTENT => TRUE));
            $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        catch (PDOException $e) {
            echo '<br /><p align="center"><strong>Connect error:</strong> '.$e->getMessage().'</p>';
            exit();
        }
    }
    
    function select($what, $tbl_name, $opt = FALSE, $param = NULL) {
        try {
            if($opt != FALSE) { $opt = 'WHERE '.$opt; }
            $this->slt = $this->dbh->prepare('SELECT '.$what.' FROM '.$tbl_name.' '.$opt);
            $this->slt->execute($param);
            $this->slt->setFetchMode(PDO::FETCH_ASSOC);
            return $this->slt;
        }
        catch(Exception $e) {
            echo '<br /><p align="center"><strong>Select error:</strong> '.$e->getMessage().'</p>';
            exit();
        }
    }
}
class UserAuth extends Database {
    function check($user, $pass) {
        echo $user.' '.$pass;
        Database::select('*', 'ftl_workers'); # Лишь бы что-нибудь вывел =)
    }
}

ну и содержимое файла:
$db = new Database;
$db->connect();

$db->query('SELECT * FROM `ftl_workers` WHERE `name` LIKE "П%"');
print '<pre>'; print_r($db->qry->fetchAll()); print '</pre>'; # Работает!

$ua = new UserAuth;
$ua->check('admin', 'pqwe'); # Ругается :(

Что я уж только не пробовал, то он ругается, что не знает prepare(), то ругается что нет функции select()

P.S. с ООП только начал разбираться, сильно не пинайте, пожалуйста =)
  • Вопрос задан
  • 2686 просмотров
Решения вопроса 1
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Вот никогда не понимал такой стиль.
Зачем делать extend Database?
+ Вы вызываете функцию как статик, но при этом в функции используете $this.

UPD

class UserAuth{
private $db;
function __construct($db) {
   $this->db = $db;
}
    function check($user, $pass) {
        echo $user.' '.$pass;
       $this->db->select('*', 'ftl_workers'); # Лишь бы что-нибудь вывел =)
    }
}


$db = new Database;
$db->connect();

$ua = new UserAuth($db);
$ua->check('admin', 'pqwe'); # Ругается :(
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
FanatPHP
@FanatPHP
Чебуратор тега PHP
Просто классическая коллекция заблуждений, связанных с бд-врапперами.

1. Не надо писать функцию select().

Это какая-то массовая эпидемия: почему-то каждый пользователь похапе в какой-то момент решает, что ему просто невмоготу написать в SQL запросе пару ключевых слов, и решает сделать функцию, которая будет их за него писать. В результате на свет появляются совершенно одинаковые уродцы в виде функции select().

В итоге из практически натурального английского "выбрать все поля из таблицы пользователей, где логин равен тому-то и пароль тому-то" получаем на выходе непонятные иероглифы, про значение которых автор и сам забудет через пару месяцев.
$this->db->select('*', 'ftl_workers', "login = ? AND password = ?");

в этом коде автор экономит себе три слова.
Вопрос: стоит ли эта экономия читабельности и портируемости?
Вопрос: а что будет, когда автор узнает о других операторах SQL, таких, как GROUP BY, JOIN и пр.?
Неужели так сложно написать нормальный SQL запрос:
$this->db->get('SELECT * FROM ftl_workers WHERE login = ? AND password = ?");

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

2. Самые развесистые грабли. Класс бизнес-логики наследует классу БД. ООП же! Надо же что-то наследовать! При этом совсем не приходит автору в голову, что, скажем, пользователь - это не база данных! И нет ни одной причины наследовать первого от второй. БД может присутствовать в классе как сервис. Как свойство. Но не как. праордитель

3. по какой-то неизвестной причине все поголовно писатели врапперов делают параметры доступа к базе переменными класса. Ну, видимо, чисто для солидности. при этом им не приходит в голову, что переменные
а) должны приходить из конфига
б) используются ровно один раз, в одной-единственной функции и больше никак в жизни класса не участвуют.
Вопрос: какой смысл делать эти параметры переменными класса?

4. Как всегда, исключение кидается только для того, чтобы ТУТ ЖЕ его поймать и радостно вывалить на экран. И здесь мы опять видим совершенно поголовное убеждение пользователей похапе в том, что они являются единственными и эксклюзивными пользователями своего сайта. Средний похапешник совершенно искренне не понимает, что у сайта могут быть и другие пользователи, которые эти сообщения ни к чему. А сам он не всегда сидит за монитором, чтобы увидеть сообщение об ошибке.
И это при том, что сам РНР обработает исключение в сто раз лучше - главное просто ему не мешать. Подробнее можно прочитать здесь: phpfaq.ru/pdo#exceptions

В итоге, без переменных класса, функции Селект и "обработчика" ошибок от класса не остаётся ничего. И это правильно. PDO - это уже дб-враппер, и "расширять" его - только портить. Во всяком случае, начинающим похапешникам настоятельно рекомендуется этого не делать, а научиться сначала пользоваться родным PDO.

Если уж так уж прям хочется сэкономить одну строчку, то изменения нужны совсем крошечные:
- надо сделать так, чтобы prepare возвращала statement, и singleton по вкусу.
получается https://github.com/colshrapnel/thebestpdowrapper
С нормальным враппером код остаётся читаемым, но в то же время кратким:

class UserAuth {
    function check($user, $pass) {
        $sql = 'SELECT * FROM ftl_workers WHERE login = ? AND password = ?';
        return DB::prepare($sql)->execute([$user, $pass])->fetch();
    }
}
include 'bestpdo.php';
$ua = new UserAuth();
$ua->check('admin', 'pqwe');
Ответ написан
KurazhBambei
@KurazhBambei
Database::select('*', 'ftl_workers');
Метод select вы вызываете статично, хотя он таковым не является. Либо добавьте static и уберите $this из тела функции, либо обращайтесь как к методу объекта через ->, предварительно инициализировав объект.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы