Статьи

Понимание EntityFieldQuery в Drupal

Вступление

При создании сложных веб-приложений вам в конечном итоге придется взаимодействовать с базой данных. Для извлечения данных в 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!