Xpoint
   [напомнить пароль]

Написал класс для безопасной работы с СУБД Mysql

Метки: [без меток]
2013-02-01 11:19:27 [обр] Василий М.+(94/171)[досье]

Всем привет!

Написал класс для безопасной работы с СУБД Mysql, на базе mysqli адаптера и использованием именованных заполнителей.
Код тут - https://github.com/Vasiliy-Makogon/Database

Приведу некоторые примеры использования:

<?php
// Подключение к СУБД, указание БД и кодировки
$db = Krugozor_Database_Mysql::create('localhost', 'root', '')
     ->setDatabaseName('test')
     ->setCharset('cp1251');

// Создаем таблицу для тестов
$db->query('DROP TABLE IF EXISTS `test`');

$db->query('CREATE TABLE test(
id int unsigned not null primary key auto_increment,
name varchar(255),
age tinyint,
adress varchar(255)
)');

Запись данных

$db->query('INSERT INTO `test` VALUES (?n, "?s", "?s", "?s")', null, 'Иван', '25', 'Москва, ул. Ленина, ЗАО "Рога и копыта"');

$user = array('name' => 'Василий', 'age' => '30', 'adress' => 'Москва, ул. Деловая, 20');
$db->query('INSERT INTO `test` SET ?As', $user);

$user = array('id' => null, 'name' => 'Пётр', 'age' => '19', 'adress' => 'Москва, ул. Красносельская, 2А');
$db->query('INSERT INTO `test` SET ?A[?n, "?s", "?s", "?s"]', $user);

$user = array('id' => null, 'name' => '%Настя%', 'age' => '17', 'adress' => 'Москва, ул. Радиальная, 12');
$db->query('INSERT INTO `test` VALUES (?a[?n, "?s", "?s", "?s"])', $user);

Выборка данных

// LIKE-поиск записи, содержащей в поле `name` служебный символ % (процент)
$result = $db->query('SELECT * FROM `test` WHERE `name` LIKE "%?S%"', '%');

$result = $db->query('SELECT * FROM `test` WHERE `id` = ?s', '1');

$result = $db->query('SELECT * FROM `test` WHERE `id` = ?i', '2+мусор');

// Передать массив и получить результат на основе выборки.
$result = $db->query('SELECT * FROM `test` WHERE `name` IN (?a["?s", "?s", "?s"])', array('Катя', 'Иван', 'Роман'));

// Тоже самое, но типизировать и перечислять в заменителях точное количество аргументов не нужно.
// Значения аргументов будут заключены в "двойные" кавчки.
$result = $db->query('SELECT * FROM `test` WHERE `name` IN (?as) OR `name` IN (?as)',
                array('Пётр', 'Маша', 'Роман', 'Ибрагим'),
                array('Иван', 'Фёдор', 'Катя')
               );

// получить все и вывести
$res = $db->query('SELECT * FROM test');
while ($data = $res->fetch_assoc()) {
   print_r($data);
   echo "\n";
}
echo "\n\n";

Более подробную информацию см. на странице проекта + описание непосредственно в коде.

спустя 21 час [обр] Филипп Ткачев(20/112)[досье]
Как насчет работы с китайской кодировкой?
спустя 34 минуты [обр] Phlinten(0/14)[досье]
// Подключение к СУБД, указание БД и кодировки
$db = Krugozor_Database_Mysql::create('localhost', 'root', '')
     ->setDatabaseName('test')
     ->setCharset('cp1251');
жесть какая
спустя 8 минут [обр] Phlinten(0/14)[досье]

Пробежался глазами по коду...

А зачем надо было подключение к бд размазывать на три метода?
А зачем надо было одну из самых часто вызываемых функций( getQueryString() ) так сложно называть?

спустя 5 часов [обр] Jared(3/26)[досье]

Василий М.[досье], не вижу вообще никакого смысла рожать новые велосипеды и городить сторонние классы-обертки над дефолтными библиотеками. Их недостатки высосаны из пальца. Пара действительно неудобных моментов решается одной-двумя простейшими элементарными функциями-обертками, если кому вдруг надо.

INSERT INTO `test` VALUES (?n, "?s", "?s", "?s");
SELECT * FROM `test` WHERE `name` IN (?as) OR `name` IN (?as);

Это вообще супер. Ну не хочу я изучать еще один самопальный подъязык-расширение SQL, мне хватает стандартных возможностей.

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

спустя 8 часов [обр] Phlinten(0/14)[досье]
сообщение промодерировано

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

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

 
Хм, сто тысячи одинаковых записей? Да и что в запросе SELECT FROM препэрить?

спустя 19 часов [обр] Василий М.+(94/171)[досье]
А зачем надо было подключение к бд размазывать на три метода?

Подключение осуществляется через static метод. Все остальное - для удобства отладки и прозрачности кода.

Их недостатки высосаны из пальца

Привидение[досье] очень хорошо описал их недостатки - я повторяться не буду.

Это вообще супер. Ну не хочу я изучать еще один самопальный подъязык-расширение SQL, мне хватает стандартных возможностей.

Что Вы взамен предлагаете?
Руками писать SQL через

implode(', ', $args)

? Подобные конструкции во многих обертках существуют, они рано или поздно станут поставляться с драйверами баз.

жесть какая

Где тут жесть? В чем жесть? В то, что определение СУБД и кодировки вынесено в отдельный метод с возможностью менять кодировку и БД во время работы?

спустя 1 час 6 минут [обр] Jared(3/26)[досье]

Василий М.[досье], читал я тот пост. Все еще высосаны из пальца недостатки.

Что Вы взамен предлагаете?

Предлагаю стандартное поведение использовать без всяких "?typedef":

$result = $db->query('SELECT * FROM `test` WHERE `id` = ? OR `name` = ?', 1, 'John');

Пускай класс сам определяет, число у меня там, или строка, или еще что, зачем меня напрягать лишним синтаксисом?

Подобные конструкции во многих обертках существуют, они рано или поздно станут поставляться с драйверами баз.

Всем этим драйверам уже не первый год. До сих пор по каким-то причинам не сделали.

Вы, может, неправильно меня поняли. Я не против плейсхолдеров, я даже очень всеми руками и ногами за. Но для плейсхолдера символа '?' достаточно. Даже именованные плейсхолдеры со всякими %bind% методами - уже излишество ИМХО. Определять в плейсхолдере еще и его тип - это уже совсем.

Где тут жесть? В чем жесть? В то, что определение СУБД и кодировки вынесено в отдельный метод с возможностью менять кодировку и БД во время работы?

Думаю, Phlinten[досье] имеет в виду кодировку 1251.
Вот покажите заодно, в каких таких случаях вдруг понадобится менять кодировку налету?

Phlinten[досье] да я и не говорю что это плохо. Но могло бы быть куда лучше.
Что до подготовленных запросов - вставлять ессно 100к разных (!) записей - для этого prepare с плейсхолдерами и существует. Для SELECT запросов тоже есть применение - когда необходимость и условия следующего запроса зависят от результатов предыдущего и заодно от неких внешних для приложения и базы условий (фазы луны, например).

спустя 19 часов [обр] Василий М.+(94/171)[досье]

Предлагаю стандартное поведение использовать без всяких "?typedef":

$result = $db->query('SELECT * FROM `test` WHERE `id` = ? OR `name` = ?', 1, 'John');

Пускай класс сам определяет, число у меня там, или строка, или еще что, зачем меня напрягать лишним синтаксисом?

Основная цель — санитарная обработка. Например, получить по ID:

$db->query('SELECT * FROM `t` WHERE id=?', $_GET['id']);

-- если в $_GET['id'] будет не число, запрос попросту сломается. Ограничивающие кавычки данный класс не ставит по идеологическим мотивам, это описано в коде.

$db->query('SELECT * FROM `t` WHERE name LIKE "?"', $_GET['name']);

-- если $_GET['name'] содержит строку my_name, то символ `_` нужно экранировать.

Всем этим драйверам уже не первый год. До сих пор по каким-то причинам не сделали.

Тем не менее, с ними чертовски не удобно работать.

Powered by POEM™ Engine Copyright © 2002-2005