Query on Drupal 8 with EntityQuery

Query on Drupal 8 with EntityQuery

Posted on Sat, 01/14/2017 - 16:02 by zhilevan

Often when building a site in Drupal you'll find yourself wanting to display a list of nodes, or find entities created by a particular author, or locate some content based on a particular set of criteria. Rather than querying the database directly, Drupal provides a helper class, EntityQuery, to make things a bit easier. The EntityQuery class (and entity.query service) will probably look very familiar to you if you're familiar with the Database API, or the EntityFieldQuery class in Drupal 7. In this tutorial we'll go through several examples of using EntityQuery to find subsets of content.

By the end of this article, you should understand how to use entity queries to create custom sets of data from entities.

EntityQuery Conditions

The most important method in the EntityQuery class is the condition() method. Conditions allow us to limit our query in specific ways so that we can get back exactly what we want. Let's walk through a few examples in code to get a sense of how this can work in practice.

// The EntityQuery class can be loaded manually (if you know the entity type):
$query = \Drupal::entityQuery('node');
// Or loaded via the service container:
$query = \Drupal::service('entity.query');
// The examples below assume we're using the service container to load the EntityQuery class.

// Use conditions to get a list of published articles.
$node_ids = $query->get('node') 
->condition('type', 'article') 
->condition('status', 1)  // Once we have our conditions specified we use the execute() method to run the query
->execute();
// Find all users with the Administrator role.
$admin_user_ids = $query->get('user') 
->condition('roles', 'Administrator', 'CONTAINS') 
->execute();

The condition method takes up to four arguments: field, value, operator, and language code. The field should be the field name (and optional column) of the field being queried. Column names can be useful when dealing with reference fields, since additional field names can then be chained together. An example of this chaining would be if you want to query for articles created by a particular user name (rather than by ID) you could use

$query = Drupal::service('entity.query')->get('node'); 
$articles_by_name = $query->condition('type', 'article') 
->condition('uid.entity.name', 'admin') 
->execute();

Once you have the field name and the desired value identified, the next parameter passed to the condition method is the operator. The operator can take one of several options: '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS', 'ENDS_WITH', 'IN', 'NOT IN', or 'BETWEEN'. For most operators, the value and the type of the column need to be the same literal. For example, it makes little sense to use the BETWEEN operator on an integer field, or the '<>' OPERATOR on a string. The 'IN' and 'NOT IN' operators expect array values. The final parameter is language code. Perhaps unsurprisingly, this allows you to limit the results of a query based on the translation status in a particular language.

// Find particular nodes published in the last year.
$query = Drupal::service('entity.query')->get('node');
$now = time();
$last_year = $now - 60*60*24*365; 
$last_years_articles = $query->condition('type', 'article') 
->condition('created', $last_year, '>=') 
->execute();

Two other methods that come in handy when building up the conditions of a query, orConditionGroup() and andConditionGroup(). Either allows you to define a group of conditions which will subsequently be either OR'ed or AND'ed together.

$query = \Drupal::entityQuery('node'); 
$group = $query->orConditionGroup() 
->condition('uid', 22) 
->condition('uid', 14) 
->condition('uid.entity.name', 'admin');
$entity_ids = $query->condition('type', 'article') 
->condition($group) -
>execute();

Other query helper methods

exists() or notExists()

If you need a simple check whether or not a particular field exists you can use the exists() or notExists() methods.

$query = \Drupal::entityQuery('node'); 
$untagged_articles = $query->condition('type', 'article') 
->notExists('field_tags') 
->execute();

sort()

The sort() method can be useful to order the results returned from EntityQuery in a particular way.

$query = \Drupal::entityQuery('user'); 
$time = time(); 
$yesterday = $time - 60*60*24; 
$new_users = $query->condition('created', $yesterday, '>=') 
->sort('created', 'DESC') 
->execute();

count()

If you're less interested in the actual entity ids, and more interested in how many entities match a particular query the count method returns the number of entities found matching your conditions.

$query = \Drupal::entityQuery('user');
$time = time();
$yesterday = $time - 60*60*24; 
$new_user_count = $query->condition('created', $yesterday, '>=')
 ->count()
 ->execute(); 

range() and pager()

Especially when working with a site that has a large amount of content it's important to think about limiting the number of results your query might return. Imagine the amount of memory required to load all of the published issue queue nodes from drupal.org with an entity query. That wouldn't be a very smart idea. This is where the pager() and range() methods come in handy. Pager allows us to specify a particular number of results, while the range method allows us to specify an index (or starting) number and the length (or page size) or results to return. Together these can be used to return a subset of any size from a result set.

$query = \Drupal::entityQuery('node');
$newest_articles = $query->condition('type', 'article') 
->condition('status', 1)  // Only return the newest 10 articles
->sort('created', 'DESC') 
->pager(10) 
->execute(); 
$not_quite_as_new_articles = $query->condition('type', 'article') 
->condition('status', 1)  // Only return the next newest 10 articles
->sort('created', 'DESC') 
->range(10, 10) 
->execute();

 

Now you can work with Drupal 8 Entityquery :D . it was simple, not?  :D

Aditional Resources :

https://www.drupal.org/project/entityqueryapi

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!Query!Que…