Класс PDO php

12 3
D
На сайте с 28.06.2008
Offline
1104
327

Я, когда мне нужно, пишу простые скрипты в процедурном стиле.

Решил все же заставить себя использовать ООП. Придумал написать класс для работы с БД, так как чаще всего мои скрипты работают с базой.

Наваял такое

class DB {
    private $database;
    private $user;
    private $password;
    private $conn;

    public function __construct()
    {
        $this->database = 'com';
        $this->user = 'user';
        $this->password = 'password ';
        $this->connect();
    }

    private function connect()
    {
        try{
            $this->conn = new PDO("mysql:host=localhost;dbname=" . $this->database . ";charset=UTF8", $this->user, $this->password);
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }catch(PDOException $e){
            echo 'Ошибка соединения с базой';
        }
    }

    public function request($str) {
        //защита запроса
        //$str = $this->conn->prepare($str)->queryString;
        //$str = $this->conn->quote($str);
        //var_dump($str);

        if (preg_match('~^SELECT~m', $str, $str_arr)){
            $resultObj = $this->conn->query($str);
            return $resultObj->fetchAll(PDO::FETCH_ASSOC);
        }
        if (preg_match('~(^UPDATE|^INSERT)~m', $str, $str_arr)){
            return $this->conn->exec($str);
        }
    }
}

Проверил SELECT запросы, все работает. Ну думаю, дальше нужно как-то разделить запросы, добавил разделение через регулярку. Чувствую что уже пахнет говнокодом...

Вопрос №1- может есть встроенные функции понимающие сразу что за тип запроса пришел в класс?

Протестировал запросы - все работает. Далее мысля пошла - нужно защититься от SQL инъекций и добавить экранирование кавычек (наиболее частое что я использую).

И вот тут я завис. 

Моя хотелка была написать универсальный класс, принимающий три вида запросов SELECT/UPDATE/INSERT (не важно какие они и что делают), чтобы они обрабатывались (экранировались) и выполнялись.

Но получается на входе у меня строка целикового запроса и ее фиг правильно экранируешь?

Вот так я пробовал проверять 

$str = "П'етр первый";
$insert = $db->request("INSERT INTO `test` (`id`, `name`, `url`, `sid`) VALUES (NULL, '{$str}', 'http://google.com', '0');");
var_dump($insert);

Получается не получится написать такой универсальный класс как хотел?

ArbNet
На сайте с 27.10.2019
Offline
131
#1

В классе сделай отдельные функции для SELECT/UPDATE/INSERT и др. какие нужны будут

В этих функциях используй подготовленный запрос prepare и экранировать ничего не надо будет

Для использования $BD->Insert($table,'id,name,url, sid',$value);

где $table - имя таблицы;

id,name,url, sid - поля для вставки;

$value - массив значений.

В функции формируешь запрос, выполняешь и отдаёшь результат, дальше по обстановке. И остальные функции в такой же манере.

MK
На сайте с 18.08.2005
Offline
126
#2
Dram :
Но получается на входе у меня строка целикового запроса и ее фиг правильно экранируешь?


$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour LIKE :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindValue(':colour', "%{$colour}%");
PDOStatement::execute
нет
LEOnidUKG
На сайте с 25.11.2006
Offline
1748
#3
Класс PDO обвернём ещё в один класс! А потом напишем подклассы, чтобы везде были классы 🤣
✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/ ✅ Настройка и оптимизация серверов https://getmanyspeed.ru/
ArbNet
На сайте с 27.10.2019
Offline
131
#4
LEOnidUKG #:
Класс PDO обвернём ещё в один класс! А потом напишем подклассы, чтобы везде были классы 🤣

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

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

Как-то общался с одним в скайпе, тот вообще не использует классы, так у него такие портянки(огромные файлы) кода жуть..

LEOnidUKG
На сайте с 25.11.2006
Offline
1748
#5
ArbNet #:

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

Но прелесть классов в том, что они подключаются по мере надобности автозагрузчиком, один раз написал и когда нужно присвоил переменной класс и используешь его методы.

Как-то общался с одним в скайпе, тот вообще не использует классы, так у него такие портянки(огромные файлы) кода жуть..

расскажите это разработчикам WP бедные, как живут без них :)

D
На сайте с 28.06.2008
Offline
1104
#6

Спасибо за ответы - но все что предложили выше вроде бы не универсально.  Insert ведь разные бывают в разные таблицы, разное кол-во полей, условия там разные....

По сути мне нужно просто экранирование кавычек но  ДЛЯ ЛЮБОГО запроса пришедшего в класс. Так можно сделать?

ArbNet
На сайте с 27.10.2019
Offline
131
#7
Dram #:
По сути мне нужно просто экранирование кавычек но  ДЛЯ ЛЮБОГО запроса пришедшего в класс. Так можно сделать?

Вам же Marat_Kh показал образец подготовленного запроса. PDO уже позаботилось чтобы не было SQL инъекций, надо делать подготовленный запрос.

То есть сначала формируется запрос с переменными вида :name далее PDO проверяет запрос и если всё хорошо подставляете вместо переменных данные.

LEOnidUKG #:
расскажите это разработчикам WP бедные, как живут без них :)

печалька.. 😂

D
На сайте с 28.06.2008
Offline
1104
#8
ArbNet #:

Вам же Marat_Kh показал образец подготовленного запроса. PDO уже позаботилось чтобы не было SQL инъекций, надо делать подготовленный запрос.

То есть сначала формируется запрос с переменными вида :name далее PDO проверяет запрос и если всё хорошо подставляете вместо переменных данные.

печалька.. 😂

Про подготовленные запросы я прочитал, но в итоге получится в 2 раза больше строк чем я обычно пишу.

Хотелось бы наоборот упростить себе задачу, а не усложнить, при этом козыряя - вот дескать на ООП пишу )))

Я бы хотел писать такие запросы типы

$str = "П'етр первый";
$insert = $db->request("INSERT INTO `test` (`id`, `name`, `url`, `sid`) VALUES (NULL, '{$str}', 'http://google.com', '0');");

и не думать каждый раз, а что там в переменной, надо ли экранировать - чтобы класс сам все экранировал, без танцев с подготовленными запросами.

Нельзя так?

ArbNet
На сайте с 27.10.2019
Offline
131
#9
Dram #:
Нельзя так?

Нет, так нельзя. Хотите по старинке используйте execute или не PDO а MySQLi и экранируйте кавычки.. Но это не даст полной гарантии от взлома.

Всё же лучше изучите современные подходы и тогда то что сейчас кажется трудным, непонятным, будет лучшим решением для вас.

ДП
На сайте с 23.11.2009
Offline
203
#10

Я бы глянул как это в Doctrine DBAL сделано (именно DBAL, a не ORM)

https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#delete - интерфейс простейший, как по мне

<?php
$conn->insert('user', array('username' => 'jwage'));
// INSERT INTO user (username) VALUES (?) (jwage)
Data Retrieval And Manipulation - Doctrine Database Abstraction Layer (DBAL)
Data Retrieval And Manipulation - Doctrine Database Abstraction Layer (DBAL)
  • www.doctrine-project.org
Table of Contents Data Retrieval And Manipulation Doctrine DBAL follows the PDO API very closely. If you have worked with PDO before you will get to know Doctrine DBAL very quickly. On top of the API provided by PDO there are tons of convenience functions in Doctrine DBAL. Data Retrieval Using a database implies retrieval of data. It is the...
12 3

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий