Работа с БД в Drupal 7 - урок 12 - Условия запросов (WHERE, HAVING, LIKE)
Условие запроса позволяет выбрать только те записи, которые подходят под некоторые ограничения, например ноды созданные не раньше двух недель назад, термины в которых есть слово "друпал" и т.д. В SQL мы используем WHERE и HAVING чтобы задать ограничения на запросы SELECT, UPDATE, DELETE. В динамических запросах также реализован механизм для работы с условиями запросов. Этот механизм работает одинаково для всех трех типов запросов: выбора, обновления, удаления.
Концепция условных выражений
Условие содержится в специальном выражение задающем ограничение.
Объединение(сложение, конъюнкция)
Каждое условие может состоять из нескольких выражений условий, которые объединяются вместе. Условия объединяются с помощью операторов AND ( И ) и OR (ИЛИ)
Объект условия
Друпал представляет каждый фрагмент условия как экземпляр класса QueryConditional. Объект условия это экземпляр класса QueryConditional.
Давайте рассмотрим пример SQL-запроса:
Запрос:
SELECT FROM {mytable} WHERE (a = 1 AND b = 'foo' OR (c = 'bar'))
Выражение условия:
WHERE (a = 1 AND b = 'foo' OR (c = 'bar'))
Части выражения условия:
(a = 1 AND b = 'foo' OR (c = 'bar'))
(c = 'bar')
Операторы соединения условий:
AND, OR
Объекты запросов SELECT, UPDATE, DELETE реализуются через класс QueryConditionalInterface, который предоставляет интерфейсы для каждого из трех видов запросов. Далее этот объект оборачивается в объект QueryConditional. Класс QueryConditional можно вызывать напрямую.
Каждый фрагмент выражения условия соединяется через оператор AND. Один или несколько фрагментов условия могут быть соединены с помощью других операторов соединения, например OR.
API
Есть два главных метода использовать все объекты условий:
$query->condition($field, $value = NULL, $operator = '=')
Метод condition() позволяет определить поле, значение и оператор фрагмента условия запроса. Этот метод можно использовать для задания условий с бинарным сравнением (там где есть два вариант ПРАВДА или ЛОЖЬ) таких как =, <, >=, LIKE и так далее. Если оператор не определен, то по умолчанию используется = (то есть точное соответсвие). Таким образом для обычного сравнения можно писать condition('myfield', $value), что будет преобразовано в myfield = :value, где :value будет заменено на значение переменной $value.
$query->where($snippet, $args = array())
Метод where() дополнительный метод, потому что можно использовать condition() вместо where(). Но where() очень часто используется, поэтому его вынесли в отдельный метод. В перменной $snippet мы пишем обычный SQL запрос, а в переменной $args массив заменителей для запроса в $snippet.
Испольльзование condition() предпочтительнее использования where().
Условия с массивами
Бывает что для запросов нужно сформировать условие со множеством значений. Для этого в запрос мы передаем массив значений. Наиболее популярные операторы SQL в таких случаях IN и BETWEEN. Оператор IN пропускает только при точном совпадение с одним элементом в массиве.
<?php $query->condition('myfield', array(1, 2, 3), 'IN'); // Становится: myfield IN (:db_placeholder_1, :db_placeholder_2, :db_placeholder_3) ?>
Таким образом мы выберим все записи в поле myfield которых значения 1,2 или 3.
Если нужно задать не точные значения, а диапазон значений, то мы используем BETWEEN:
<?php $query->condition('myfield', array(5, 10), 'BETWEEN'); // Становится: myfield BETWEEN :db_placeholder_1 AND :db_placeholder_2 ?>
Так мы выбираем все записи в поле myfield которых значения от 5 до 10.
Вложенные условия
Первый параметр condition() может принимать другие объект условия. Вложенный запрос может быть включен в другой более сложный запрос. В результате мы получим сложное условие соединеное где нужно операторами AND и OR.
Хелпер db_condition() возвращает новый объект условие. Этот метод имеет один параметр, а именно какой тип соединения условия он использует. Вы также можете использовать хелперы db_or(), db_xor() (все значения исключающие ИЛИ), db_and(), как правило этих готовых хелперов хватает. Давайте рассмотрим пример:
<?php $query ->condition('field1', array(1, 2), 'IN') ->condition(db_or()->condition('field2', 5)->condition('field3', 6)) // В результате получится такой запрос: // (field1 IN (:db_placeholder_1, :db_placeholder_2) AND (field2 = :db_placeholder3 OR field3 = :db_placeholder_4)) ?>
Значения NULL
Для проверки значения NULL используйте следующие методы:
<?php $query->isNull('myfield'); // Результат (myfield IS NULL) $query->isNotNull('myfield'); // Результат (myfield IS NOT NULL) ?>
Эти методы isNull(), isNotNull() могут быть комбинированы с where(), condition().
Заметьте, что condition('myfield', NULL) устарело, используйте isNull(), isNotNull().
Подзапрос
Метод condition() поддерживает подзапросы для $value. Для использования подзапроса используется класс SelectQuery, который создается с помощью метода db_select(). Вместо выполнения метода select() объекту передаются параметры метода condition().
Подзапросы удобно использовать для коротких простых запросов с условием по одному полю. Если вы попытаетесь сделать что-то грандиозное с помощью db_select(), то лучше бросьте эту затею и используйте condition().
Давайте рассмотрим примеры подзапросов, чтобы стало яснее:
db_delete()
<?php db_delete('sessions') ->condition('timestamp', REQUEST_TIME - $lifetime, '<') ->execute(); // DELETE FROM {sessions} WHERE (timestamp < 1228713473) ?>
db_update() <?php db_update('sessions') ->fields(array( 'sid' => session_id() )) ->condition('sid', $old_session_id) ->execute(); // UPDATE {sessions} SET sid = 'abcde' WHERE (sid = 'fghij'); ?>
db_delete()
<?php // From taxonomy_term_save(): $or = db_or()->condition('tid1', 5)->condition('tid2', 6); db_delete('term_relation')->condition($or)->execute(); // DELETE FROM {term_relation} WHERE ((tid1 = 5 OR tid2 = 6)) ?>