Блог

Одним из весомых преимуществ Drupal 7 перед его предшественниками есть его гибкость в отношении настроек и систем. Веб разработчики не обошли стороной и запросы к БД. В седьмом релизе они стали объектно-ориентированными и не привязанными к конкретной базе дынных, поскольку теперь сам Drupal генерирует синтаксис запроса. Задача программиста - как и прежде -  всего лишь указать условия выборки. Эту статью я посвящаю анализу Database API, в ходе которого приведу конкретные примеры новшеств в “общение” с БД.

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

php $db_url = 'mysqli://username:/basename';

к более читабельному

php
$databases['default']['default'] = array( 
  'driver'   => 'mysql', 
  'database' => 'basename', 
  'username' => 'username', 
  'password' => 'password', 
  'host'     => 'localhost', 
);

Хочу заметить, что Drupal 7 все еще поддерживает db_query(), но и его коснулись кое-какие изменения - изменились заменители (placeholders). Одним из вариантов есть использования знака ? вместо %d, ’%s’. В этом случае значения таких заменителей указываются в массиве после запроса в таком же порядке, в каком они расположены в запросе:

php
db_query("SELECT `title` FROM {node} WHERE `uid` = ? AND `type` = ?", array(1, 'page'));

Другой вариант - использование так называемых “именных” заменителей. Подстановка значений происходит в ассоциативном массиве. Один и тот же заменитель не может быть описан дважды, даже если он будет иметь то же значение. Им принято присваивать имена соответствующих колонок таблиц, значения которых они определяют:

 php
db_query("SELECT `title` FROM {node} WHERE `uid`= :uid AND `type` = :type", array(':uid' => 1, ':type' => 'page'));
?>

Но вернемся, все же, к нашей теме и рассмотрим новшества в данной области. Если раньше мы использовали db_query(), внутри которого прописывали необходимый тип запроса (select, insert, update, delete), то теперь каждому из них соответствует своя функция (db_select(), db_insert(), db_update(), db_delete()), на основе которой и генерируется необходимый синтаксис. Список допустимых функций ниже:

  • db_and
  • db_close
  • db_condition
  • db_delete
  • db_driver
  • db_escape_field
  • db_escape_table
  • db_insert
  • db_like
  • db_merge
  • db_next_id
  • db_or
  • db_query 
  • db_query_range
  • db_query_temporary
  • db_select
  • db_set_active
  • db_transaction
  • db_truncate
  • db_update
  • db_xor
  •  

Определение формата данных, полученных в ходе выполнения обращения к базе, тоже претерпело изменения. На смену таким функциям как db_result(), db_fetch_array(), db_fetch_object() и т. д. пришли методы класса DatabaseStatementInterface:

    1. execute - выполнение запроса;
    2. fetchAllAssoc - возвращает результат запроса в виде ассоциативного массива ключей заданного поля;
    3. fetchAllKeyed - возвращает результат как единый ассоциативный массив;
    4. fetchAssoc - выбирает следующую строку и возвращает её в качестве ассоциативного массива;
    5. fetchCol - возвращает один столбец результирующего набора, как индексированный массив;
    6. fetchField - возвращает одно поле из следующей записи из результирующего набора;
    7. getQueryString - возвращает строку запроса;
    8. rowCount - возвращает число строк, которые возвращает запрос.

Необходимым условием выполнения запроса является присутствие execute(). Он должен быть использован перед определением формата.

Теперь рассмотрим как все это работает. Создадим запрос, который вернет нам содержимое таблицы `node`:

php
$result = db_select('node', 'n') 
  ->fields('n') 
  ->execute() 
  ->fetchAssoc();

В db_select необходимо указать таблицу (и при необходимости ее сокращение), с которой будет осуществляться выборка. Далее, добавляем метод fields(), в котором указываем таблицу и поля для выборки. Если поля не указанны, то запрос вернет все поля таблицы (аналог *). Execute() обеспечит выполнение нашего запроса, а fetchAssoc() вернет результат в виде ассоциативного массива. Указывая необходимые поля, нужно учесть одну особенность - они должны быть перечислены в массиве, даже если указывается лишь одно поле!

Если же в нашем запросе необходимо указать некое условие, то для этого нам необходимо использовать метод conditions(). Он принимает три значения - поле, значение поля, параметр сравнения. Если не указан последний, то по-умолчанию он определиться как “=”.

php
$result = db_select('node', 'n') 
  ->fields('n', array('type', 'tittle')) 
  ->condition('nid', $node->nid, '=') 
  ->condition('status', 0, '>') 
  ->condition('uid', array(1, 5, 7), 'IN') 
  ->execute() 
  ->fetchAssoc();

Есть, также, и другие методы запроса, которые позволяют делать сложение таблиц (join), группировку значений (groupBy), их сортировку (orderBy), ограничение количества результатов (range) и др. Все они, в своем сочетании, позволяют строить сложные запросы к БД.

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

php
$query = db_select('node', 'n'); 
$query->join('users', 'u', 'n.uid = u.uid'); 
$query->groupBy('u.uid'); 
$query->fields('n', array('title', 'created')) 
  ->fields('u', array('name')) 
  ->orderBy('created', 'DESC') 
  ->range(0, 10); 
$result = $query->execute(); 
while ($record = $result->fetchAssoc()) { 
   print_r ($record); 
}

Вот по такому принципу и работают все запросы. В подтверждение этих слов приведем примеры использования запросов для вставки и удаления записей:

php
$id = db_insert('node')->fields(array( 
  'title'        => 'Title', 
  'uid'         => 1, 
  'created' => REQUEST_TIME, 
))->execute();
 php
db_delete('node') 
  ->condition('uid', 5) 
  ->condition('created', time() - 3600, '<') 
  ->execute();

Database API, реализованный в Drupal 7, позволяет строить объемные запросы, имеет большую скорость их обработки, лучшую читабельность и возможность внесения изменений, а также самостоятельно строит синтаксис запроса, сводя таким образом к минимуму возможность пользовательской ошибки в структуре, и не привязывается к одной базе данных, что гарантирует возможность выполнения запроса для разных БД.

Вы можете ознакомиться со сравнениями построения запросов в Drupal 6 и 7, на основе презентации. Смотреть

Join the conversation
0 Comments