Статьи

Версия EntityFieldQuery для Drupal 8

Несмотря на то, что ядро ​​Drupal 7 не смогло должным образом обработать свою совершенно новую систему сущностей (в настоящее время мы полагаемся на отличный модуль Entity для этого), оно действительно дало нам EntityFieldQuery . Для тех из вас, кто не знает, EntityFieldQuery — это очень мощный класс запросов, используемый для программного поиска объектов Drupal (узлов, пользователей и т. Д.).

Он предоставляет ряд методов, облегчающих запрос сущностей на основе таких условий, как значения полей или свойства класса. Если вы не знаете, как это работает, не стесняйтесь проверить эту страницу документации или этот замечательный учебник по этому вопросу.

В этой статье я расскажу о том, что у нас есть в Drupal 8 для запросов к сущностям. EntityFieldQuery больше не EntityFieldQuery , но есть сервис entity.query который будет создавать экземпляр объекта запроса для данного типа сущности (и реализующий \ Drupal \ Core \ Entity \ Query \ QueryInterface ). Мы можем получить доступ к этому сервису статически через пространство имен \ Drupal или используя внедрение зависимостей.

Сначала мы рассмотрим запросы к сущностям узлов, а затем посмотрим, как их загрузить. Те же методы будут работать и с другими объектами контента (пользователями, комментариями и т. Д.), Но также и с объектами конфигурации, и это действительно круто.

Служба запросов сущностей

Как уже упоминалось, есть два способа получить доступ к entity.query который мы используем для запроса сущностей. Статически мы можем сделать это:

 $query = \Drupal::entityQuery('node'); 

Вместо node мы можем указать любое другое имя компьютера типа сущности, и то, что мы получаем внутри переменной $query является объектом запроса для нашего типа сущности. Статический метод entityQuery() в пространстве имен \Drupal — это быстрый путь для использования службы entity.query .

Альтернативно (и очень рекомендуемый подход) состоит в использовании внедрения зависимости .

Если у вас есть доступ к контейнеру, вы можете загрузить сервис оттуда и затем получить правильный объект запроса:

 $entity_query_service = $container->get('entity.query'); $query = $entity_query_service->get('node'); 

Как вы можете видеть, мы используем метод get() в entity_query чтобы создать экземпляр объекта запроса для типа сущности с именем машины, переданным в качестве параметра.

Запрос сущностей

Давайте проиллюстрируем несколько примеров запросов для сущностей узлов, использующих этот объект.

Очень простой запрос, который возвращает опубликованные узлы:

 $query = \Drupal::entityQuery('node') ->condition('status', 1); $nids = $query->execute(); 

$nids будет массивом идентификаторов сущностей (в нашем случае идентификаторов узлов), ключом которого являются идентификаторы ревизий (если для типа сущностей разрешено изменение) или идентификаторы сущностей, если нет. Давайте рассмотрим пример, в котором мы добавляем больше условий свойства, а также условий поля:

 $query = \Drupal::entityQuery('node') ->condition('status', 1) ->condition('changed', REQUEST_TIME, '<') ->condition('title', 'cat', 'CONTAINS') ->condition('field_tags.entity.name', 'cats'); $nids = $query->execute(); 

В этом запросе мы извлекаем идентификаторы всех опубликованных узлов, которые были обновлены до текущего времени в последний раз, в названии которых содержится слово cat и в качестве ссылки в поле field_tags используется термин таксономии, называемый cats .

Как видите, больше нет различий между propertyCondition и fieldCondition (как в D7 с EntityFieldQuery ). Кроме того, мы можем включить условия, основанные на привязанных сущностях, привязанных к entity.(column) к имени поля ссылки на сущность.

Важно отметить, что у нас также есть параметр langcode в методе condition() помощью которого мы можем указать, какой перевод узла следует включить в запрос. Например, мы можем получить идентификаторы узлов, которые содержат определенное значение внутри поля на одном языке, но другое значение внутри того же поля для другого языка.

Для получения дополнительной информации о методе condition() вам следует обратиться к документации API .

Далее мы рассмотрим использование групп условий (и AND и OR ) для более мощных запросов:

 $query = \Drupal::entityQuery('node') ->condition('status', 1) ->condition('changed', REQUEST_TIME, '<'); $group = $query->orConditionGroup() ->condition('title', 'cat', 'CONTAINS') ->condition('field_tags.entity.name', 'cats'); $nids = $query->condition($group)->execute(); 

Выше мы изменили наш предыдущий запрос, чтобы получить узлы, которые либо имеют строку cat в заголовке, либо имеют ссылку на термин cats в поле field_tags . И мы сделали это, создав объект orConditionGroup, который затем передаем в запрос в качестве условия. И мы также можем сгруппировать несколько условий в andConditionGroup .

В QueryInterface есть много других методов, которые могут расширить запрос (например, для сортировки, диапазона и т. Д.). Я рекомендую вам проверить их в документации и поэкспериментировать с ними. А пока давайте кратко рассмотрим, что делать с набором результатов.

Загрузка сущностей

Как я упоминал выше, метод execute() объекта запроса, с которым мы работали, возвращает массив идентификаторов сущностей. Предположительно, теперь мы должны загрузить эти объекты и работать с ними. Как мы это делаем?

В Drupal 7 у нас была функция entity_load (), в которую мы передавали массив идентификаторов, и который возвращал бы массив объектов. В Drupal 8 эта вспомогательная функция поддерживается, и вы можете использовать ее почти таким же образом, за исключением только одного объекта за раз:

 $node = entity_load('node', $nids[1]); 

И возвращаемое значение является объектом узла. Чтобы загрузить несколько узлов, вы можете использовать функцию entity_load_multiple () :

 $nodes = entity_load_multiple('node', $nids); 

Который затем возвращает массив объектов-сущностей с ключами по их идентификаторам.

Дополнительный фрагмент информации заключается в том, что обе эти функции являются оболочками для менеджера хранилища рассматриваемых объектов. Они в основном извлекают менеджер хранилища статически, а затем вызывают для него методы load () и loadMultiple () соответственно:

Статически вы можете сделать аналогично:

 $node_storage = \Drupal::entityManager()->getStorage('node'); // Load multiple nodes $node_storage->loadMultiple($ids); // Load a single node $node_storage->load($id); 

Но, что еще лучше, вы можете использовать внедрение зависимостей и извлечь класс хранилища из контейнера:

 $node_storage = $container->get('entity.manager')->getStorage('node'); 

А затем продолжить загрузку. Использование внедрения зависимостей обычно является рекомендуемым способом, когда это возможно, то есть при работе в классе. Это облегчает тестирование вашего класса и лучше отделяет его от остальной части приложения.

Вывод

В этой статье мы увидели, как работать с запросами и загрузкой сущностей в Drupal 8. Был проведен капитальный ремонт класса D7 EntityFieldQuery который превратился в надежный API для запросов как контента, так и сущностей конфигурации. Мы рассмотрели запросы объектов содержимого, но система точно так же работает с объектами конфигурации. И это немного победа для новой системы сущностей Drupal 8.

Мы также видели, как загружать объекты на основе идентификаторов, приведенных в этих запросах, и что на самом деле стоит за функциями-обертками, которые выполняют эти операции. Далее мы рассмотрим определение нашего собственного типа сущности контента в Drupal 8. Чтобы узнать, как мы это делаем в Drupal 7, вы можете ознакомиться с этими статьями Sitepoint по этому вопросу.