Выкладываю на ваш суд свой класс-надстройку над стандартным PDO. Писался и совершенствовался он с каждым проектом, и содержит все мои изменения суммарно.
Ссылка на GitHub (обновлено 26.06.2016)
Данное расширение добавляет следующий функционал:
- Цепочки вызовов
- Аналоги функций из pear::db
- Показать сформированный запрос
- Функции для подсчета статистики запросов
- Дополнительные функции
- Дополнительные опции
- Другие изменения
Цепочки вызовов
Старый синтаксис:
$request = $pdo->prepare('SELECT data FROM table WHERE param = :placeholder ');
$request->bindValue('placeholder', 'value');
$request->execute();
$data = $request->fetchAll();
Новый синтаксис:
$data = $pdo
->prepare('SELECT data FROM table WHERE param = :placeholder ')
->bindValue('placeholder', 'value')
->execute()
->fetchAll();
Вобщем короче, удобнее, нагляднее.
Цепочки поддерживают следующие функции:
PDO->prepare
PDO->query
PDOStatement->bindParam
PDOStatement->bindValue
PDOStatement->bindValueList
PDOStatement->execute
Аналоги функций из pear::db
Представлены следующие функции
public function getAll($statement, $params = array());
public function getRow($statement, $params = array());
public function getColumn($statement, $params = array(), $column_number = null);
public function getOne($statement, $params = array(), $column_name = 0);
Конечно представлены не все функции из pear:DB, но это именно те которых мне не хватало в моих проектах.
Использовать очень просто:
$data = $pdo->getAll('SELECT data FROM table WHERE param = :placeholder ', array('placeholder' => 'value'));
Запросы получаются намного короче и лаконичнее чем использование даже предложенных мною цепочек.
Показать сформированный запрос
При использовании плейсхолдеров отсутствует возможность получить полный запрос (т.е. c заменой плейсхолдеров). Вобщем то это не проблема этого расширения. Это особенность реализации PDO, ведь сама замена плейсхолдеров проводится уже в БД.
$sql = $pdo
->prepare('SELECT data FROM table WHERE param = :placeholder ')
->bindValue('placeholder', 'value')
->getSQL();
Вернет сгенерированный запрос. Пока работает только с именованными плейсхолдерами.
Функции для подсчета статистики запросов
Это уже функционал который не добавляет только ленивый.
Используется для подсчета колличества выполненных запросов и времени затраченного на выполнение запросов.
public function statisticTime();
public function statisticCount();
По названию понятно что какая возвращает.
Дополнительные функции
Тут оформлены дополнительные функции, которые я использую в своих проектах.
Возвращает результат SELECT FOUND_ROWS(), оформлено в одну функцию для более удобного использования (работает только для MySQL):
PDO->calcFoundRows()
Алиас для lastInsertId:
PDO->calcLastInsertId()
Присвоить значения нескольким плейсхолдерам за один вызов функции:
PDOStatement->bindValueList(array $array)
Дополнительные опции
PDOExtended::ATTR_USE_UTF
Включено по умолчанию. Только MySQL. При инициализации подключения установить все настройки кодировок в UTF-8. При подключении выполняются следующие запросы:
$this->exec("SET NAMES utf8 COLLATE utf8_general_ci");
$this->exec("SET CHARACTER SET utf8");
PDOExtended::ATTR_STRICT_MODE
Включено по умолчанию. Только MySQL. При инициализации подключения включить строгий режим. При подключении выполняется следующий запрос:
$this->exec("SET sql_mode='STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE'");
PDOExtended::ATTR_TIME_ZONE
Только MySQL. При инициализации подключения установить временную зону сервера. При подключении выполняется следующий запрос:
$this->exec("SET time_zone=?");
Например:
$pdo->setAttribute(PDOExtended::ATTR_TIME_ZONE, '+0:00');
$pdo->setAttribute(PDOExtended::ATTR_TIME_ZONE, null); //Отключить изменение временной зоны сервера
Другие изменения
Включены PDOExtended::ATTR_STRICT_MODE
и PDOExtended::ATTR_USE_UTF
. Будем двигать правильные настройки mysql и правильную кодировку в массы =)
По умолчанию включена генерация исключений при возникновении ошибок PDOExtended::ERRMODE_EXCEPTION
.
Также изменены две стандартные функции, а точнее добавлены дополнительные параметры к ним:
PDO->exec($statement, $params = array());
PDO->query($statement, $params = array());
Функции делают тоже самое, согласно их документации, но добавлен еще один параметр $params массив который может содержать набор плейсхолдеров.
Пример:
$data = $pdo->
query(
'SELECT data FROM table WHERE param = :placeholder ',
array(
'placeholder' => 'value'
)
)->
fetchAll();
Использование
Приинклудьте файл с классом расширения в ваш проект. И при создании объекта PDO используйте имя класса PDOExtended:
$pdo = new PDOExtended([...])
Заключение
Как то так. Понятно что уже существующие проекты никто не будет переводить на этот класс. Но новые — почему бы и нет?
Так например при разработке меня всегда раздражала излишняя многословность PDO из коробки. Здесь она исправлена.
Ссылку на класс см. в начале статьи.
Гуд, но кажется уже давно пора переходить на activerecord\datamapper паттерны. Никакого sql, в подавляющем большинстве случаев, писать вообще не прийдётся. Да и удобнее.
Ну вобщем то ar/dm представляют лишь объекты, и это немного другое.
Я в своих проектах использую SQL для некоторых запросов и простенькие DataMapper-ы для представления основных объектов. Считаю это разумным компромисом между абстрактностью и простотой приложения. В итоге код достаточно легко поддерживается, и довольно понятен (хотя может это только на мой взгляд).
Отречься полностью от SQL и фигачить модели для всего только для ООП ради ООП не считаю правильным.
Ну вобщем как то так =)
Тут уже на вкус и цвет) Мне наоборот — чем выше абстракция, тем удобнее.
И это правильно. Нужно делать так как удобно самому, а не слушать других и уж тем более не делать так только потому что это модно.
За примером далеко ходить не надо. Иной раз достаточно почитать комменты к статьям на хабре. С комментариями в духе — мол у вас тут реализованно намного менее абстрактно чем во всех остальных фреймворках. Так и хочется спросить в ответ — вы е**нулись? Зачем делать тридцать слоев абстракции, если ты уверен что сделанного достаточно? Нет же, все стараются захреначить архитектуру суперрасширяемого приложения. А самое смешное, что вся эта огромная вложенность абстракций в момент когда потребуется отрефакторить код оказывается бесполезна, так как при разрабтке трудно учесть все, и то что вам надо будет дописать, в 90% случаев не уложится в них.
Просто одно дело делать так потому что это самому удобно, а второе дело — использовать херову кучу абстракций — ради упрощения будущего рефакторинга. Второе я не одобряю. Да, я не спорю, нужно правильно проектировать архитектуру, но переизбытка быть не должно. Все должно быть в меру)
Это не в твой адрес. Это мне просто высказаться захотелось, накипело так сказать)
Не могу понять а как вставить запись?
Как то так, если вы об этом:
Да с цепочками вызовов намного удобнее, код лаконичнее получается. Спасибо за идею
Так а почему идею? Берите реализацию)
Ну не, свой велосипед сердцу милее
Понимаю, плох тот програмист который не любит писать свои велоспеды)
Ай в общем ну его нафиг, взял вашу реализацию :)
странно как-то работает ваш класс…
не работает (и не генерит ошибок):
работает :
OpenServer, PHP 5.5, MySQL 5.5
Скорее всего дело в том что мой класс автоматически включает strict mode. Это режим в котором mysql бросает ошибки на любые неправильные данные (вместо округления, обрезания и проч.). По дефолту этот режим в MySQL выключен, что не совсем правильно, и слишком расслабляет программистов, откуда в итоге возникают ошибки.
Видимо у вас не задано значение по умолчанию для какого-то из столбцов, либо же данные «AAA» для столбца «name_ru» некорректны. Класс не бросает ошибки потому что по дефолту это отключено и в самом оригинальном PDO.
В общем ваш комментарий наконец сподвигнул меня обновить репозиторий на гитхабе. Возьмите новый код класса оттуда. Там я вынес настройку включения strict mode, а также включил генерацию исключений по умолчанию (наверное это правильнее чем их замалчивать).
Так например, ваш код теперь должен будет выбросить ошибку с пояснением проблемы при его выполнении. Для отключения строгого режима можете сделать так:
Ваш код кстати можно немного сократить: