Гибкая минимальность для работы с базой данных

  • написал: MpaK
  • 433
Все мы думаю в 2012ом году без исключений пользуемся библиотеками, особенно в таком тонком деле как работа с базой данных, где нужна надежность сохранности данных, предсказуемость, гибкость и защищенность от всяческих неправильных данных (sql injections например).

На PHP великое множество таких библиотек для работы с базой данных, от встроенных в используемых фрэймворки, всяческие ORM, DataMapper, ActiveRecord паттерны доступа, до простейших конструкторов запросов. Но в случае если вы разрабатываете какой-то специфичный проект, например с большими нагрузками и решаете не использовать сторонние фрэймворки, а создавать проект своими силами, нанизывая на самописный каркас броню от лучших производителей титановых пластин, то выбор под PHP библиотек для работы с БД велик, сложно с ориентироваться в таком выборе и нужно исходить из своих требований, а дальше выбирать из PDO, DBSimple, PHP-ActiveRecord, RedBeans и т.д. сторонних решений.

Вот например, что требовалось мне в одном проекте и что выбрал я и почему.
Какие удобства и возможности я искал от библиотеки для работы с БД.
— ООП, хорошо бы иметь namespace, но если нет, то удобный chaining запросов в конструкторе запросов, чтобы можно было писать цепочки вида $sql->where('id'=>1)->findAll()
— возможность выбора нескольких одновременных подключений и даже с разными драйверами, например одна БД это sqlite, а другая mysql
— placeholder чтобы можно было регулировать типы вставки или задавать автоматическую типизацию и не пропускал sql injections
— сбор запросов и установка скобок на логических конструкциях AND, OR и т.п. очень важный пункт если вы работаете с конструктором запросов и хотите создавать ожидаемые запросы
— обработка ошибок, желательно конечно в 2012 году уметь выбрасывать Exceptions
— профайлинг, иметь лог или firebug отчет по скорости запросов, кол-ве их и съеденной памяти

Искать пришлось в моём требовательном случае довольно интенсивно.
PDO не подошел по ряду причин, глобальная, что сверху всё же надо писать класс свой обёртку, чтобы вести те самые логи, замеры. Отсутствие конструктора запроса, уменьшала гибкость. Ну и главный камень был, что нельзя было посмотреть собранный после работы placeholder'а «провальный» запрос на ошибке php.net/manual/en/book.pdo.php
DBSimple древний мамонт от Котерова, быстр хорош, но хорошим ООП и конструктором запросов не пахнет, нет менеджера коннектов, все открытые подключения нужно держать самому и хранить самому, отсутствие исключений dklab.ru/lib/DbSimple
PHP-ActiveRecord наверное это самый крутой в плане кода класс из представленных здесь, очень могучая и приятная копия AR класс из Ruby on Rails. Немного странный конструктор запросов, не нашел профайлер. Но зато крутые модели, расширяемость, возможность указания связей между моделями и т.п. www.phpactiverecord.org
RedBeans в общем-то отличный всем пример, легковесная библиотека с замашками на ORM, есть всё от placeholder'ов, обработки исключений до конструктора запросов, менеджера мультиподключений и ассоциативных связей между моделями. Не нашел одного, как профайлить запросы и смотреть их лог, потом выбор пал на следующий за ним класс redbeanphp.com но обещаю себе, что когда-нибудь я поработаю с этой библиотечкой, но в следующем проекте ;-)

А теперь сама цель статьи, познакомить вас с маленькой звездой на небосклоне работы с БД из PHP, библиотекой DIBIdibiphp.com на котором мы так и остановились в своём проекте и который мне всё больше и больше нравится своей гибкостью и ловкостью с которой он помогает решать мои дела с базой данных (mysql, sqlite).

Dibi это очень маленькая, очень дружественная и понятная на интуитивном даже уровне библиотека.

Она очень легко коннектится к базе к любой из баз данных из списка: MSSQL, MySQL, Oracle, PostgreSQL, SQLite и есть два универсальных на все случаи жизни PDO и ODBC.

Простейший коннект к базе данных выглядит так:
dibi::connect(array(
    'driver'   => 'mysql',
    'host'     => 'localhost',
    'username' => 'root',
    'password' => '***',
));


А мульти коннект еще проще, именуя каждое созданное подключение вторым параметром:
dibi::connect(array('driver'   => 'mysql', 'host'     => 'localhost1', 'username' => 'root', 'password' => '***'), 'mysql_db_local');
dibi::connect(array('driver'   => 'mysql', 'host'     => 'localhost2', 'username' => 'root', 'password' => '***'), 'mysql_db_main');

после чего необходимое подключение можно получить из менеджера:
$main_db = dibi::getConnection( 'mysql_db_main' );

если и директивы для ведения логов или ленивого подключения (lazy connect) к БД, когда подключение не создаётся до первого запроса, директива lazy = TRUE в конфиге подключения к базе.

Прелесть профайлинга и дебага заключается в имеющемся Firebug расширении, когда все запросы с временем выполнения можно видеть через браузер, например Firefox с установленным разумеется расширением Firebug или Chrome по умолчанию уже понимает.
$db_config = array(
    ...
    'lazy'     => TRUE,
    'profiler' => array(
    'run' => TRUE,
    'file' => 'log1.sql'
    )
);


Но есть и ручные выбросы dibi::$sql; и dibi::dump(); последних пропарсенных запросов. Помимо этого есть еще
ibi::$elapsedTime; // время последнего запроса
dibi::$numOfQueries; // кол-во всего запросов
dibi::$totalTime; // общее время запросов


Так же помимо включения логгирования в конфиге есть и директивы для этого dibi::getProfiler()->setFile('log.sql'); или для мультиподключения dibi::getConnect('mysql_main_db')->getProfiler()->setFile( 'log.txt' );

А уж после подключения dibi даёт полную свободу как использовать подключение и собирать запросы через передачу множественных параметров
dibi::query( 'SELECT * FROM ?', $table_name, ' WHERE id = %i', $id, ' AND alias = "hello" LIMIT 10' )->fetchAll();

до запросов конструктора, когда нужно учитывать условия к примеру
$sql = dibi::getConnection( 'main_db' );
$sql = $sql->select('*')->from( $table_name )->as( 'tt' );
if( !empty($id) ) $sql = $sql->where( 'id = %i', $id );
try(
  $res = $sql->limit(10)->fetchAll();
}catch( DibiException $e ){
  die( $e->getMessage() );
}

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

Результаты работы можно получать как в виде объектра итератора (ObjectIterator), так и в виде объекта массива (ArrayAccess)
$res = $sql->limit(100)->fetchAll();
foreach( $res as $r ){
  echo $r->name, ' knows about ', $r['name'];
}
$name = $sql->fetchSingle( 'name' );
echo $name, ' knows about ', $name;

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

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

А в помощь пригодится простенький мануал на одной странице dibiphp.com/cs/quick-start который хоть даже и на чешском, но прост, лаконичен и очень понятен.
А так же стоит заглянуть в папку скачанное дистрибутива где есть папка с очень толковыми примерами.

Удачи и побольше вам стабильных подключений!
  • 0

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.