Drupal 7: работа с базой данных

В своем стремлении к абстракции от конкретной БД разработчики Drupal, похоже, неплохо так выворачивают извилины. Разработчикам модулей приходится тоже изворачиваться. Ниже приведены отличия в запросах к БД между 6-й и 7-й версиями Drupal.

Теперь различают статический запрос (static query) и динамический запрос (dynamic query). Примеры приведены ниже.

Выборка.

Обычно методы запроса возвращают объект SelectQuery, что позволяет использовать цепочку вызовов вроде db_select()->method1()->method2().

//****  выборка всех значений по условию, в результате получаем массив объектов
//****  затем используем foreach ($nodes as $node) { ... }
//****  в особо ответственных случаях необходимо использовать addTag('node_access')
//****  для проверки прав на исполнение этого  запроса
// Drupal 6
$nodes = db_query("SELECT nid, title FROM {node}  WHERE type = '%s' AND uid = %d", 'page', 1);
 
// Drupal 7, статический запрос
$nodes = db_query(" SELECT nid, title FROM {node} WHERE type = :type AND uid = :uid
              ", array(':type' => 'page', ':uid' => 1))->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n', array('nid', 'title'))
  ->condition('n.type', 'page')
  ->condition('n.uid', 1)
  ->addTag('node_access')
  ->execute()
  ->fetchAll();
 
//****  получение единственной записи
// Drupal 6
$title = db_result(db_query("SELECT title FROM {node} WHERE nid = %d", 123));
 
// Drupal 7, статический запрос
$title = db_query("SELECT title FROM {node} WHERE nid = :nid", array(':nid' => 123))->fetchField();
 
// Drupal 7, динамический запрос
$title = db_select('node', 'n')
  ->fields('n', array('title'))
  ->condition('n.nid', 123)
  ->execute()
  ->fetchField();
 
//****  получение объекта по его id
// Drupal 6
$node = db_fetch_object(db_query("SELECT * FROM {node} WHERE nid = %d", 123));
 
// Drupal 7, статический запрос
$node = db_query("SELECT * FROM {node} WHERE nid = :nid", array(':nid' => 123))->fetchObject();
 
// Drupal 7, динамический запрос
$node = db_select('node', 'n')
  ->fields('n')
  ->condition('n.nid', 123)
  ->execute()
  ->fetchObject();
 
//****  использование  INNER JOIN
//****  Тут необходимо помнить, что некоторые методы (например джоины) не возвращают объект SelectQuery, 
//****  и поэтому их нельзя использовать в цепочке вызовов. 
// Drupal 6
$nodes = db_query("SELECT n.title, u.name FROM {node} n  INNER JOIN {users} u ON n.uid = u.uid");
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT n.title, u.name FROM {node} n
               INNER JOIN {users} u ON n.uid = u.uid
               ")->fetchAll();
 
// Drupal 7, динамический запрос
$query = db_select('node', 'n');
$query->innerJoin('users', 'u', 'n.uid = u.uid');
$query->fields('n', array('title'));
$query->fields('u', array('name'));
$nodes = $query->execute()->fetchAll();
 
//****  поиск минимального значения
// Drupal 6
$min = db_result(db_query("SELECT MIN(fieldname) FROM {table}"));
 
// Drupal 7, статический запрос
$min = db_query("SELECT MIN(fieldname) FROM {table}")->fetchField();
 
// Drupal 7, динамический запрос
$query = db_select('table');
$query->addExpression('MIN(fieldname)');
$min = $query->execute()->fetchField();
 
//****  выборка заданного количества записей
// Drupal 6
$nodes = db_query("SELECT * FROM {node} LIMIT 0, 10");
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT * FROM {node} LIMIT 0, 10")->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->range(0, 10)
  ->execute()
  ->fetchAll();
 
//**** подсчет количества записей
// Drupal 6
$count = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE n.uid = 1"));
 
// Drupal 7, статический запрос
$count = db_query("SELECT COUNT(*) FROM {node} n WHERE n.uid = 1")->fetchField();
 
// Drupal 7, динамический запрос, вариант 1
$count = db_select('node', 'n')
  ->condition('n.uid', 1)
  ->countQuery()
  ->execute()
  ->fetchField();
 
// Drupal 7, динамический запрос, вариант 2
$query = db_select('node');
$query->addExpression('COUNT(*)');
$count = $query->execute()->fetchField();
 
//****  использование логического оператора OR
// Drupal 6
$nodes = db_query("SELECT * FROM {node} WHERE uid = %d OR status = %d", 1, 0);
 
// Drupal 7, статический зспрос
$nodes = db_query("SELECT * FROM {node} WHERE uid = :uid OR status = :status", array(':uid' => 1, ':status' => 0))->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->condition(
    db_or()
      ->condition('uid', 1)
      ->condition('status', 0)
  )->execute()
  ->fetchAll();
 
//****  использование оператора IN 
$nds = array(1, 2, 3);
// Drupal 6
$nodes = db_query("SELECT * FROM {node} WHERE nid IN (" . db_placeholders($nds) . ")", $nds);
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT * FROM {node} WHERE nid IN (:nds)", array(':nds' => $nds))->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->condition('n.nid', $nds, 'IN')
  ->execute()
  ->fetchAll();
 
//****  использование оператора LIKE
// Drupal 6
$nodes = db_query("SELECT * FROM {node} WHERE title LIKE '%%%s%%'", 'substring');
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT * FROM {node} WHERE title LIKE :title", array(':title' => '%' . db_like('substring') . '%'))->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->condition('n.title', '%' . db_like('substring') . '%', 'LIKE')
  ->execute()
  ->fetchAll();
 
//****  использование оператора BETWEEN
// Drupal 6
$nodes = db_query("SELECT * FROM {node} WHERE nid BETWEEN %d AND %d", 123, 456);
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT * FROM {node} WHERE nid BETWEEN :nid1 AND :nid2", array(':nid1' => 123, ':nid2' => 456))->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->condition('n.nid', array(123, 456), 'BETWEEN')
  ->execute()
  ->fetchAll();
 
//****  сложные условия в WHERE:
// Drupal 6
$nodes = db_query("SELECT * FROM {node} WHERE YEAR(FROM_UNIXTIME(created)) = %d", 2011);
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT * FROM {node} WHERE YEAR(FROM_UNIXTIME(created)) = :created", array(':created' => 2011))->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->where('YEAR(FROM_UNIXTIME(n.created)) = :created', array(':created' => 2011))
  ->execute()
  ->fetchAll();
 
//****  проверка значения на NULL
// Drupal 6, Drupal 7 статический запрос
$result = db_query("SELECT * FROM {table} WHERE field IS NULL");
 
// Drupal 7, динамический запрос, вариант 1
$result = db_select('table', 't')
  ->fields('t')
  ->condition('t.field', NULL, 'IS NULL')
  ->execute();
 
// Drupal 7, динамический запрос, вариант 2
$result = db_select('table', 't')
  ->fields('t')
  ->isNull('t.field')
  ->execute();
 
//****  сортировка
// Drupal 6
$nodes = db_query("SELECT * FROM {node} ORDER BY created DESC, title ASC");
 
// Drupal 7, статический запрос
$nodes = db_query("SELECT * FROM {node} ORDER BY created DESC, title ASC")->fetchAll();
 
// Drupal 7, динамический запрос
$nodes = db_select('node', 'n')
  ->fields('n')
  ->orderBy('n.created', 'DESC')
  ->orderBy('n.title', 'ASC')
  ->execute()
  ->fetchAll();

Обновление записей
// Drupal 6
db_query("UPDATE {node} SET status = %d WHERE nid = %d", 1, 123);
 
// Drupal 7, статический запрос
db_query("UPDATE {node} SET status = :status WHERE nid = :nid", array(':status' => 1, ':nid' => 123));
 
// Drupal 7, динамический запрос
db_update('node')
  ->fields(array('status' => 1))
  ->condition('nid', 123)
  ->execute();
 
//****  инкремент значения определенного поля
// Drupal 6
db_query("UPDATE {node_counter} SET totalcount = totalcount + 1 WHERE nid = %d", 123);
 
// Drupal 7, статический запрос
db_query("UPDATE {node_counter} SET totalcount = totalcount + 1 WHERE nid = :nid", array(':nid' => 123));
 
// Drupal 7, динамический запрос
db_update('node_counter')
  ->expression('totalcount', 'totalcount + 1')
  ->condition('nid', 123)
  ->execute();

Добавление записей

В INSERT по прежнему можно использовать drupal_write_record()

// Drupal 6
db_query("INSERT INTO {mytable} (intvar, stringvar, floatvar) VALUES (%d, '%s', %f)", 5, 'hello world', 3.14);
$id = db_last_insert_id();
 
// Drupal 7, динамический запрос
$id = db_insert('mytable')
  ->fields(array(
    'intvar' => 5,
    'stringvar' => 'hello world',
    'floatvar' => 3.14,
  ))->execute();

Удаление записей
// Drupal 6
db_query("DELETE FROM {node} WHERE uid = %d AND created < %d", 1, time() - 3600);
 
// Drupal 7, статический запрос
db_query("DELETE FROM {node} WHERE uid = :uid AND created < :created", array(':uid' => 1, ':created' => time() - 3600));
 
// Drupal 7, динамический запрос
db_delete('node')
  ->condition('uid', 1)
  ->condition('created', time() - 3600, '<')
  ->execute();
 
//****  очистка таблицы
// Drupal 6, Drupal 7 статический запрос
db_query("TRUNCATE {node}");
 
// Drupal 7, динамический запрос
db_truncate('node')->execute();