Класс PDO php


Dram
297

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

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

Наваял такое

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

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

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

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

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

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

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

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


Marat_Kh

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

Класс PDO обвернём ещё в один класс! А потом напишем подклассы, чтобы везде были классы 🤣


ArbNet

LEOnidUKG #:
Класс PDO обвернём ещё в один класс! А потом напишем подклассы, чтобы везде были классы 🤣

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

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

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


LEOnidUKG

ArbNet #:

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

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

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

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


Dram

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

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


ArbNet

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

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

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

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

печалька.. 😂


Dram

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

Dram #:
Нельзя так?

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

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


Дикий пионер

Я бы глянул как это в 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…

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *