Вступление
При создании сложных веб-приложений вам в конечном итоге придется взаимодействовать с базой данных. Для извлечения данных в Drupal можно использовать предоставленный уровень абстракции базы данных, который требует правильного использования некоторых знаний SQL. Из Drupal 7 предоставляется API-интерфейс EntityFieldQuery, который позволяет вам получать информацию о сущностях из Drupal без фактического построения запросов SQL. В этой статье давайте посмотрим, как мы можем использовать API EntityFieldQuery для извлечения данных из Drupal и использования их в наших модулях.
Класс EntityFieldQuery
Класс EntityFieldQuery используется для поиска сущностей в Drupal, которые соответствуют некоторым условиям. EntityFieldQuery присутствует в файле includes / entity.inc в вашей установке Drupal.
Этот класс имеет различные методы для указания типа объекта и определенных условий, на основании которых мы можем фильтровать, какие данные мы хотим получить. Мы рассмотрим эти методы подробно в этой статье.
Основное использование, которому вы будете следовать при использовании EntityFieldQuery, будет, в первую очередь, создание объекта этого класса. После создания объекта вы добавите к нему некоторые условия и затем вызовете метод execute для получения результатов.
Общий шаблон выглядит следующим образом
$entityquery = new EntityFieldQuery ();
/// Set some conditions $result = $query -> execute ();
Сейчас мы собираемся создать модуль Drupal, который будет устанавливать 3 новых типа узлов Drupal: «Продукт», «Фильмы» и «Книги», а также блок, в котором мы будем отображать наши результаты. Вы можете увидеть, как создать тип узла в этой статье
Код для модуля
entityquery.info
name = entityquery description = Shows how to use entity query to fetch data from drupal package = Entity Query Example core = 7.x
entityquery.install
<? php /** * Implement hook_install(). */
function entityquery_install () { node_types_rebuild (); $types = node_type_get_types (); node_add_body_field ( $types [ 'product' ]); node_add_body_field ( $types [ 'movies' ]); node_add_body_field ( $types [ 'books' ]);
}
entityquery.module
<? php /** * Implement hook_node_info() */
function entityquery_node_info () {
return array (
'product' => array (
'name' => t ( 'Product' ),
'base' => 'product' ,
'description' => t ( 'You can define new Products here' ),
'has_title' => TRUE ,
'title_label' => t ( 'Product title' )
),
'movies' => array (
'name' => t ( 'Movies' ),
'base' => 'movies' ,
'description' => t ( 'You can define new Movies here' ),
'has_title' => TRUE ,
'title_label' => t ( 'Movie title' )
),
'books' => array (
'name' => t ( 'Books' ),
'base' => 'Books' ,
'description' => t ( 'You can define new Books here' ),
'has_title' => TRUE ,
'title_label' => t ( 'Books title' )
)
);
}
/** * Implement hook_form() */
function product_form ( $node , $form_state ) {
return node_content_form ( $node , $form_state );
}
/** * Implement hook_form() */
function movies_form ( $node , $form_state ) {
return node_content_form ( $node , $form_state );
}
/** * Implement hook_form() */
function books_form ( $node , $form_state ) {
return node_content_form ( $node , $form_state );
}
/** * Implement hook_block_info(). */
function entityquery_block_info () { $blocks = array (); $blocks [ 'entityqueryblock' ] = array (
'info' => t ( 'A block to display results from entityquery' ),
);
return $blocks ;
}
/** * Implement hook_block_view(). */
function entityquery_block_view ( $block_name = '' ) {
if ( $block_name == 'entityqueryblock' ) { $content = '' ; $block = array (
'subject' => t ( 'A block to display results from entityquery' ),
'content' => $content ,
);
return $block ;
}
}
Поместите этот модуль в папку модулей, и если все прошло хорошо, вы сможете увидеть модуль entityquery в списке модулей, как показано ниже.
После установки модуля вы сможете увидеть новые типы узлов также в разделе «Добавить контент» вашей админ-панели Drupal следующим образом.
Выполнение простого запроса с использованием EntityFieldQuery
Как только мы настроим базовый модуль для использования EntityFieldQuery, давайте начнем писать некоторые запросы для извлечения данных из Drupal. Первый запрос, который мы напишем, должен получить все узлы, используя EntityFieldQuery. Затем мы будем использовать это для отображения названий узлов в нашем блоке.
Как указывалось ранее, первое, что нужно сделать, это создать экземпляр EFQ. Чтобы получить тип объекта, вы должны добавить к entity_type
условие entity_type
. В этом случае мы хотим получить узлы, поэтому код для него будет выглядеть следующим образом:
$query = new EntityFieldQuery (); $query -> entityCondition ( 'entity_type' , 'node' );
Условие объекта устанавливается с помощью функции entityCondition
в которой мы устанавливаем тип объекта как узел. Как только мы установили условие сущности, мы готовы выполнить запрос. Идентификаторы узлов возвращаются в массиве в ключе узла результата. Полный код для отображения узлов будет следующим:
$query = new EntityFieldQuery (); $query -> entityCondition ( 'entity_type' , 'node' ); $result = $query -> execute (); $nodes = array ();
if ( isset ( $result [ 'node' ])) { $nids = array_keys ( $result [ 'node' ]); $nodes = node_load_multiple ( $nids );
} $list = array ();
foreach ( $nodes as $node ) { $options = array ( 'absolute' => TRUE ); $url = url ( 'node/' . $node -> nid , $options ); $list [] = '<a href=' . $url . '>' . $node -> title . '</a>' ;
} $theme_args = array ( 'items' => $list , 'type' => 'ol' ); $content = theme ( 'item_list' , $theme_args ); $block = array (
'subject' => t ( 'A block to display results from entityquery' ),
'content' => $content ,
);
return $block ;
Теперь, если вы пойдете и увидите свой блок, вы сможете увидеть все узлы в нем следующим образом
Теперь вы должны попытаться добавить разные узлы, такие как фильмы и книги, и проверить их отображение в блоке. В приведенном выше коде, получив код узла из EntityFieldQuery, мы загружаем узлы с помощью node_load_multiple
и отображаем их.
Добавление условий объекта в EntityFieldQuery
Вы можете добавить условия объекта для отображения только определенных типов узлов. Если мы хотим отображать только «продукты» из типа узлов, мы будем использовать запрос:
$query = new EntityFieldQuery (); $query -> entityCondition ( 'entity_type' , 'node' )
-> entityCondition ( 'bundle' , 'product' ); $result = $query -> execute ();
Теперь, если мы проверим наш блок, он будет отображать только продукты:
Мы даже можем указать массив типов узлов для выборки нескольких типов узлов, используя entityCondition
. Чтобы получить все продукты и фильмы из вашей базы данных:
$query = new EntityFieldQuery (); $query -> entityCondition ( 'entity_type' , 'node' )
-> entityCondition ( 'bundle' , array ( 'product' , 'movies' )); $result = $query -> execute ();
Добавление условий собственности в EntityFieldQuery
Мы даже можем добавить условия свойства к запросу. Это будет зависеть от типа сущности, к которой вы обращаетесь. В большинстве случаев условие свойства будет в полях типа сущности, к которому вы обращаетесь. Вы можете, например, запросить узлы, которые опубликованы или написаны конкретным пользователем и т. Д.
Запрос, чтобы показать только опубликованные узлы, используя propertyCondition
выглядит следующим образом
$query = new EntityFieldQuery (); $query -> entityCondition ( 'entity_type' , 'node' )
-> propertyCondition ( 'status' , 1 ); $result = $query -> execute ();
Добавление условий поля в EntityFieldQuery и порядок
Полевые условия являются специфическими для полей, которые присутствуют на объекте. Итак, предположим, что мы хотим найти все продукты со словом скидка в своем теле — мы можем сделать это, используя условие поля. Мы даже можем упорядочить результаты, используя функцию propertyOrderBy
.
Если мы хотим, чтобы товары и фильмы, имеющие «скидку» в своем теле, располагались в порядке убывания их создания, запрос будет следующим:
$query = new EntityFieldQuery (); $query -> entityCondition ( 'entity_type' , 'node' )
-> entityCondition ( 'bundle' , array ( 'product' , 'movies' ))
-> propertyCondition ( 'status' , 1 )
-> fieldCondition ( 'body' , 'value' , 'discount' , 'CONTAINS' )
-> propertyOrderBy ( 'created' , 'DESC' ); $result = $query -> execute ();
Результат этого запроса будет следующим
Расширение класса EntityFieldQuery
Иногда вам может потребоваться создать один и тот же запрос во многих местах. Хороший способ абстрагироваться — расширить класс EntityFieldQuery и создать свой собственный дочерний класс.
Предположим, что вы хотите создать запрос, чтобы получить всех активных пользователей в порядке возрастания даты их создания:
class ActiveUsersEntityFieldQuery extends EntityFieldQuery {
public function __construct () { $this -> entityCondition ( 'entity_type' , 'user' )
-> propertyCondition ( 'status' , 1 )
-> propertyOrderBy ( 'created' , 'ASC' );
}
}
Теперь вы можете использовать этот запрос в любом месте, например:
$activeUsers = new ActiveUsersEntityFieldQuery (); $result2 = $activeUsers -> execute ();
Вывод
Многие модули в Drupal понадобятся вам для извлечения содержимого сущностей из базы данных. Можно напрямую использовать слой базы данных Drupal, но для этого вам необходимо иметь хотя бы практические знания SQL, и он может быть более подвержен ошибкам. Класс EntityFieldQuery
является частью ядра Drupal, и вы можете легко использовать его независимо от других модулей. Удачи в создании вашего следующего модуля Drupal!