Побудова запитів з використанням Database API

28.04.2011
Building queries using Database API
Автор:

Однією з вагомих переваг Drupal 7 щодо його попередників є його гнучкість до налаштувань і систем. Веб розробники не обійшли стороною і запити до БД. В цьому релізі вони стали об'єктивно-орієнтованими і не прив'язаними до конкретної бази даних, так як тепер сам Друпал генерує синтаксис запиту. Завданням програміста залишається лише вказати умоби вибірки. Цю статтю я присвячую аналізу Database API, де наведу приклади як саме змінилось "спілкування" з БД.

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

php $db_url = 'mysqli://username:password@localhost/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:

  • execute - виконання запиту;

  • fetchAllAssoc - повертає результат запиту у вигляді асоціативного масиву ключів заданого поля;
  • fetchAllKeyed - повертає результат як єдиний асоціативний масив;
  • fetchAssoc - вибирає наступний рядок і повертає його в якості асоціативного масиву;
  • fetchCol - повертає стовпець результивного набору, як індексований масив;
  • fetchField - повертає одне поле з наступного запису з результивного набору;
  • getQueryString - повердає рядок запиту;
  • 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, на основі презентації. Дивитись

Голосів: 1 Рейтинг: 5

Також по темі

1

В кінці квітня цього року в своєму офіціальному блозі представники Google Analytics оголосили про запуск бета-тестування нового інтерфейсу. А в цій статті я хочу розповісти про використання...

2

Стаття для тих, в кого виникає необхідність відобразити прикріплений PDF документ на сторінці перегляду вмісту. Реалізується це доволі просто...

3

Пакетні операції дають можливість обробляти форми на протязі декількох запитів. Це попереджує обривання обробки через тайм-аут РНР. Також користувачу надається інформація про хід здійснення таких...

4

В цій статті я розкажу і розпишу як оперувати основними хуками із розділів Field API.

Field API - один з розділів Drupal 7 API, які дозволяють нам:

  • створювати поля, що...
5

Швидкість завантежння сторінки в браузері кінцевого користувача - один із ключових факторів популярності вашого сайту. Користувач може не дочекатися...

Subscribe to our blog updates