Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Работа с БД в Drupal 7 - урок 6 - Изменение запроса на лету (hook_query_alter)

02/12/2019, by Ivan

Важной особенностью динамических запросов выбора является возможность других модулей изменять запросы на лету. Это позволяет другим модулям вставлять их собственные инструкции в запрос, тем самым влияя на поведение запроса или применить изменения во время выполнения запроса, например задать разграничение прав к нодам. Существуют 3 компонента изменения запроса на лету, tagging, meta data и hook_query_alter().

Tagging

Любой динамический запрос выбора может быть "tagged" с одной или более строкой. Эти теги служат для идентификации с типом запроса, который при возвращение позволяет определить эту строку и добавить какое-нибудь действие. Теги следует задавать в буквенный-цифровой форме в нижнем регистре, следуя тем же правилам, что и в переменных PHP. Для добавления тега к запросу используйте метод addTag().

<?php
$query->addTag('node_access');
?>

Определить если для заданного объекта тег, можно с помощью 3 доступных методов:

<?php
// TRUE если объект-запрос имеет тег.
$query->hasTag('example');

// TRUE если этот объект-запрос имеет каждый из следующих тегов.
$query->hasAllTags('example1', 'example2');

// TRUE если этот объект-запрос имеет любой из следующих тегов.
$query->hasAnyTag('example1', 'example2');
?>

Оба hasAllTags() и hasAnyTag() принимают два параметра, причем их порядок не имеет значения. Нет ничего сложного чтобы использовать теги, причем есть уже готовые теги для использования, вот их примеры:

node_access
Этот запрос должен иметь разграничение прав на ноды.
translatable
Этот запрос должен иметь переводимую строку.
term_access
Этот запрос должен иметь разграничение по термину.
views
Этот запрос должен иметь тег созданный модулем Views

Meta data

Запросы могут также иметь meta data прикрепленные к ним, meta data предоставляет дополнительные возможности для изменения запроса на лету. Meta data может быть любой PHP с ключом описанным через строку.

<?php
$node = node_load($nid);
// ... Create a $query object here.
$query->addMetaData('node', $node);
?>

Meta data не имеет внутреннего смысла и не создает эффект для объект-запроса. Meta data существует только для дополнительной информации для изменения на лету и главным образом применяется только когда запрос имеет теги. Для  доступа к переменным заданным через meta data используйте метод getMetaData().

<?php
$node = $query->getMetaData('node');
?>

Если нет мета-данных, связанных с этим ключом, то будет возвращено NULL.

hook_query_alter()

Ни теги ни мета-данные не оперируют с запросом. Оба они предоставляют лишь информацию для hook_query_alter(), который может принимать любое действие с динамическим объект-запросом выборки. Все динамические запросы выборки передаваемые через hook_query_alter(),  передаются перед методом execute(), сразу перед тем как запрос будет скомпилирован. Это дает модулям возможность манипулировать запросом как угодно. hook_query_alter() принимает один параметр: объект-запроса.

<?php
/**
* Реализация hook_query_alter().
*/
function example_query_alter(QueryAlterableInterface $query) {
  // ...
}
?>

Здесь также возможно обрабатывать только запросы с тего через хук hook_query_TAG_NAME_alter(). Следующий код вызывает для запроса тег "node_access".

<?php
function example_query_node_access_alter(QueryAlterableInterface $query) {
  // ...
}
?>

Два важных наблюдения могут быть сделаны в отношение hook_query_alter().

  1. Параметр $query не может быть передан по ссылке. Потому что это объект, а объект не будет дублирован в любом случае при использование PHP5. Передача по ссылке не нужна. hook_query_alter() также не возвращает значение.
  2. Тип параметра явно определен как QueryAlterableInterface. Явное определение типа параметра предоставляет обеспечивает более лучшую защиту против передачи неправильного типа переменной. Тип также определен как QueryAlterableInterface раньше чем просто SelectQuery для обеспечения в будущем большей совместимости

hook_query_alter() может совершать любое действие с объект-запросом, кроме выполнения запроса таким образом, что это приведет к зацикливанию. hook_query_alter() может использовать теги и мета-данные ассоциированный с запросом для определения, какое именно действие нужно выполнить. Разработчики модулей могут также вызывать дополнительные методы для объект-запросов такие как добавление полей, объединения, условия и т.д. для запроса или могут запросить разграничить доступ для запроса, чтобы управлять данными напрямую. Вы можете удалить первый вариант запроса, изменив его хуком.

<?php
$fields =& $query->getFields();
$expressions =& $query->getExpressions();
$tables =& $query->getTables();
$order =& $query->getOrderBy();
$where =& $query->conditions();
$having =& $query->havingConditions();
?>

Важно заметить, значения возвращаются по ссылке, так что  alter hook будет иметь доступ к тем же данным что и структура объекта. Все вышеуказанные методы возвращают массив, главным образом структура которого описана в документации об SelectQuery в файле includes/database/select.inc.