Недавно я заметил, что в Интернете можно найти огромное количество PHP-классов для работы с базой данных. Как обычно, они всегда щеголяют своей функциональностью и количеством возможностей. Я решил тоже написать свой класс для работы с базой данных, но пошёл по другому пути. Я хотел сделать такой класс, чтобы в нём был тот необходимый минимум функционала, который только и требуется. Всё остальное – это уже непонятные навороты, которые использовать, как минимум, небезопасно.
Привожу свой прокомментированный класс для работы с базой данных:
mysqli = new mysqli("localhost", "root", "", "my_db");
$this->mysqli->query("SET lc_time_names = ‘ru_RU’");
$this->mysqli->query("SET NAMES ‘utf8’");
>
/* Вспомогательный метод, который заменяет "символ значения в запросе" на конкретное значение, которое проходит через "функции безопасности" */
private function getQuery($query, $params) <
if ($params) <
for ($i = 0; $i sym_query);
$arg = "’".$this->mysqli->real_escape_string($params[$i])."’";
$query = substr_replace($query, $arg, $pos, strlen($this->sym_query));
>
>
return $query;
>
/* SELECT-метод, возвращающий таблицу результатов */
public function select($query, $params = false) <
$result_set = $this->mysqli->query($this->getQuery($query, $params));
if (!$result_set) return false;
return $this->resultSetToArray($result_set);
>
/* SELECT-метод, возвращающий одну строку с результатом */
public function selectRow($query, $params = false) <
$result_set = $this->mysqli->query($this->getQuery($query, $params));
if ($result_set->num_rows != 1) return false;
else return $result_set->fetch_assoc();
>
/* SELECT-метод, возвращающий значение из конкретной ячейки */
public function selectCell($query, $params = false) <
$result_set = $this->mysqli->query($this->getQuery($query, $params));
if ((!$result_set) || ($result_set->num_rows != 1)) return false;
else <
$arr = array_values($result_set->fetch_assoc());
return $arr[0];
>
>
/* НЕ-SELECT методы (INSERT, UPDATE, DELETE). Если запрос INSERT, то возвращается id последней вставленной записи */
public function query($query, $params = false) <
$success = $this->mysqli->query($this->getQuery($query, $params));
if ($success) <
if ($this->mysqli->insert_ > else return $this->mysqli->insert_id;
>
else return false;
>
/* Преобразование result_set в двумерный массив */
private function resultSetToArray($result_set) <
$array = array();
while (($row = $result_set->fetch_assoc()) != false) <
$array[] = $row;
>
return $array;
>
/* При уничтожении объекта закрывается соединение с базой данных */
public function __destruct() <
if ($this->mysqli) $this->mysqli->close();
>
>
?>
Как видите, нет ничего лишнего, только всё самое необходимое. Теперь разберём PHP-код, который использует данный класс:
<?>AND `online` = <?>";
$table = $db->select($query, array(10, 1)); // Запрос явно должен вывести таблицу, поэтому вызываем метод select()
$query = "SELECT `login` FROM `users` WHERE `email` = <?>";
$login = $db->selectCell($query, array("test@mail.ru"));// Запрос должен вывести конкретную ячейку, поэтому вызываем метод selectCell()
?>
Теперь Вы понимаете, что для удобной и безопасной работой с базой данных вовсе не требуется библиотека из 100 классов. Всё необходимое имеется, и данный класс без проблем обработает любой запрос. Единственное, что я рекомендую – это настройки вынести в отдельный класс. То есть адрес хоста, имя пользователя, пароль, название базы данных, кодировку, локаль и "символ значения" вынести в отдельный класс, откуда их считывать.
Вот такой незамысловатый класс для работы с базой данных я использую в своих проектах.
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Она выглядит вот так:
Комментарии ( 21 ):
Интересный метод getQuery(), напоминает параметризованные запросы prepare(), bind_param(). Как по вашему, стоит ли заморачиваться с ними или для безопасности вполне хватит вашего подхода для подстановки значений в запрос?
Лично я их не использую и особого смысла не вижу.
Михаил, а можете написать пример изменёной функции getQuery так, чтобы ставить не <?>а что-то типа :i, :s, 😕 тоесть i это число, s это строка, ? это любое значение, как сделать такое распределение, напишите пожалуйста, если вдруг тут не захотите писать, то напишите мне в ответ "Пишите на форум и я отвечу и помогу с примером", хорошо?
Михаил, возникла проблема. Все методы работают кроме select и selectRow. Не знаю в чем проблема, никаких ошибок не выводит но и то, что нужно тоже 🙁 Я в отчаянии.
Скорее всего, ошибка в Вашем запросе. Используйте этот метод для поиска ошибок: http://myrusakov.ru/php-finderror.html и для поиска ошибки в SQL: http://myrusakov.ru/sql-finderror.html
Ок, задам вопрос по другому. Как правильно вывести все данные из таблицы в БД используя метод select в вашем классе? $query = "SELECT * FROM `users`"; $db->select($query) – не прокатывает, возвращает Array если вывести print-ом.
Он Array и должен возвращать. Это же массив данных.
Михаил, спасибо БОЛЬШОЕ Вам за это курс, подскажите, пожалуста, нет ли в отправке формы в БД каких-либо особенностей при отправке значений радиокнопок? У меня есть форма отзыва о компании, в которой есть 2 текстовых поля и 2 поля с радиокнопками. Значения полей с текстом в БД попадает, а выбранное значение радиокнопок-нет. просто пустая ячейка. Хотя через echo на странице оно выводиться?
Никаких особенностей нет, надо просто искать ошибку: http://myrusakov.ru/php-finderror.html
Спасибо за класс, удобно. Прошу показать пример работы с insert и update
Мне больше вот этот нравится, не знаю, дает он 100% защиту от sql инъекция, но хотя бы какая то. http://habrahabr.ru/post/165069/
Дякую за посилання.. дуже зручно і безпечно.
Не получается подключиться к базе данных. Куда класть этот файл класса БД?
В папку положите корневую.
Так и сделал. Все пхп туда положил. Даже пароль от базы данных пишу нарочно неправильный – ошибки не выдает.
Сделал! Сделал! Оказывается в файле класса БД не надо было прописывать данные БД (логин пароль и пр.)!
А я его чуть-чуть под себя переделал. Убрал конструктор, вместо него добавил метод set_parameters(). Это позволило задавать параметры объекта при создании нового экземпляра. Т.е. реализовано это так public $server; public $host; public $port; public $user; public $pass; public $base; public function set_parameters() < $this->mysqli = new mysqli($this->host.’:’.$this->port,$this->user,$this->pass,$this->base); $this->mysqli->query("SET lc_time_names = ‘ru_RU’"); $this->mysqli->query("SET NAMES ‘utf8’"); > Теперь когда мне нужно создать новый экземпляр класса с другими параметрами, я делаю так $db = new dBase; $db -> server = SQL_SERVER; $db -> host = SQL_HOST; $db -> port = SQL_PORT; $db -> user = SQL_USER; $db -> pass = SQL_PASS; $db -> base = SQL_BASE; $db -> set_parameters(); Таким образом класс стал более гибким, ну т.е. мне не нужно каждый раз править файл класса чтобы подключиться к новому серверу, и появилась возможность переключаться между серверами "на лету"
Добрый день. Не могу понять, а по чему в методах массиву $params присваевается значиние false?
Здравствуйте! В запрос msqli->query(объект) отправляется как параметр объект класса. Вопрос: как этот запрос вытаскивает из объекта сформированный запрос для баз данных msql? Пример Вашего кода: $result_set = $this->mysqli->query(AbstractSelect $select);
Добавить этот весь код надо в один файл? У меня database_class.php
Подскажите я делаю запрос $query_made_pay_advertise = $db->select("SELECT * FROM `made_pay_advertise` WHERE `advertise_ ); while($row_made_pay_advertise = $db->selectRow($query_made_pay_advertise))< echo "
"; > но ничего не выводит
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2019 Русаков Михаил Юрьевич. Все права защищены.
Не так давно я устроился на новую работу и впервые столкнулся с популярным фреймворком. Мне необходимо было написать большой SQL-запрос. Я его написал, сделал bindValue, запустил сценарий и… запрос завершился с ошибкой. Я очень надеялся, что фреймворк позволит мне получить полноценный SQL-запрос, что бы я смог его отладить. Но не тут то было — фреймворк не позволял сделать ничего подобного. Ровно, как и PDO/mysqli не позволяют этого до сих пор.
Современные средства для работы с базой MySql в PHP, будь то абстракция PDO или расширения mysql и mysqli — просто не предназначены для «клиентского» кода. Об этом очень хорошо написали на хабре еще в 2012 году. Есть две основных причины, по которым использовать родные инструменты в «голом» виде просто невозможно. Это:
- Многословность — на каждый запрос приходится писать по несколько однотипных строк кода
- Невозможность получить SQL запрос для отладки — функция, которой просто катастрофически не хватает
Не долго думая, я все же решил представить миру свое решение, которое уже достаточно давно работает в моих проектах. Эта библиотека представляет собой удобный инструмент для работы с обычным SQL в рамках СУБД MySQL — и не более того. Это важно — я не стал идти по пути других разработчиков различных библиотек, которые по факту пишут сами не понимают что — то ли построители запросов (sql builders), то ли подобие ActiveRecord библиотек, то ли вообще симбиоз из нескольких слоёв. Библиотека Database — это «низкоуровневый» слой, лежащий над стандартным mysqli.
В библиотеке два основных метода для выполнения запросов — методы query() и queryArguments(), работающих в составе обертки над стандартным объектом mysqli. Эти методы возвращают результативный объект, который также представляет собой обертку над стандартным mysqli_result.
Все просто и ясно. Ничего лишнего.
Основное достоинство библиотеки — это эмуляция подготовленных запросов, удобная работа с заполнителями (placeholders). Параметры запроса передаются отдельно от SQL, а в самом SQL на месте, где должны присутствовать параметры запроса, пишутся специальные типизированные маркеры. Парсер библиотеки находит эти маркеры, определяет их тип и в зависимости от типа маркеров, занимается преобразованием параметров запроса и их подстановкой в исходную строку SQL-запроса.
Приведу пример работы.
Таким образом:
- Ваш код становится короче — выполнение запросов пишется в одну строку
- Надежная защита от SQL-инъекций. Никаких mysqli_real_escape_string() и intval()
- Экранирование символов для оператора LIKE
- Несколько полезных плейсходеров — как для подготовки скалярных типов, так и создания множеств из массивов
- Возможность получать все SQL-запросы текущего соединения, как до процедуры парсинга, так и после
- Прозрачный и понятный код, доступный для расширения и модификации
Более подробное описание и примеры можно посмотреть на сайте проекта: www.database.phpinfo.su
Ссылка на репозиторий: github.com/Vasiliy-Makogon/Database–class-PHP-Mysql-prepare-placeholders
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.
В последнее время задался вопросом написания php класса для работы с базой данных mysql. Мои требования – удобство формирования запроса к базе данных и возможность сортировки и записи данных через массив, что упрощает работу с БД.
В результате появился вот такой класс:
Вот такой класс, а теперь подробнее о функциях.
Для подключения к базе данных (БД) объявляем класс Db и с помощью функции connect подключаемся к БД. Значения для функции: connect(Хост, Имя пользователя, пароль, имя базы данных);
После подключения можно приступать к работе. Для сортировки с помощью массива объявляю массив, а для записи данных использую функцию where, в которую передаю массив:
Далее функцию where опишу подробнее. А сейчас объявим из каких полей делать выборку, для этого используем функцію select, по умолчанию ее значение — * и ее можно не объявлять.
По умолчанию where использует знак = для сравнения, но если нужно другое значение, например больше или меньше то можно вторым значением передать нужный нам знак сравнения. В функции можно использовать как строчный вариант сравнения, например ‘price,1000’, так и массив как в примере выше и всему массиву будет подставлен переданный знак.
Для сортировки значений внутри выборки используем функцию order_by, для нее также формируем массив:
Эта функция сформирует такой запрос: ORDER BY price DESC, data ASC. В ORDER BY можно подставлять свои аргументы используя функцию order_by_text():
Теперь функции вывода данных — их три: num_rows, multiline, lines:
Функция num_rows показывает количество записей, соответствующих запросу, false — означает, что объявленные данные для сортировки стирать не нужно. Без false все объявленные данные стираются и их нужно объявлять заново. ‘data’ – таблица в БД к которой делаем запрос.
Функция multiline выводит массивы данных соответствующих запросу.
Функция lines выводит один первый массив соответствующий запросу.
Функции формируют такой запрос:
SELECT msg,zag FROM data WHERE status=’1′ AND category=’2′ AND price>’1000′ ORDER BY price DESC, data ASC, id DESC
Функция limit — устанавливает LIMIT в запрос, где 2 — стартовый номер для вывода (т.е. вывод начнется со 2-го элемента соответствующего запросу), 4 — количество элементов в массиве.
Select, where и order_by объявляем заново, т.к. предыдущая функция lines была без false — это означает, что все данные для сортировки были стерты. Формирует такой запрос:
SELECT AND id IN (1,2,3,4) ORDER BY price DESC, data ASC LIMIT 2,4
Здесь была использована еще одна функция where_text – она нужна для того, чтобы самому написать запрос в WHERE
Формирует такой запрос: SELECT * FROM data WHERE MATCH(test,text) AGAINST(‘+тест +поиска’ IN BOOLEAN MODE). Ищем в таблице data, в полях test и text совпадения со словами тест и поиска.
$order_by и $where берутся из предыдущих объявленных переменных и получаем такой запрос:
SELECT IN BOOLEAN MODE) ORDER BY price DESC, data ASC
Для записи в базу данных: используем функцию set — передача параметров сохранения массивом и insert — запись в базу данных:
Для внесения изменений в строку используем функцию update:
Если запись прошла успешно, $message вернет UPDATE OK иначе ERROR UPDATE. Запрос будет таким:
UPDATE data SET test=’test’, text=’text’, category=’2′, test=’test change’, text=’text change’ WHERE
И еще одна функция query — в ней можно написать свой запрос select полностью:
Также можно сделать параллельное соединение с другой базой данных:
Такой вот класс у меня получился. Не буду сравнивать его с другими класcами для работы с БД, знаю — их множество. Публикую его, т.к. думаю, что, может, кому-то пригодится, а также хочется конструктивной критики, которая позволит улучить этот код.