How to use EntityFieldQuery for Drupal 7

Last updated on
23 December 2016

The EntityFieldQuery API lets you fetch information about entities (nodes, users, taxonomy terms et cetera) from Drupal without actually building SQL queries.

EntityFieldQuery is a class that allows retrieval of a set of entities based on specified conditions. It allows finding of entities based on entity properties, field values, and other generic entity metadata. The syntax is really compact and easy to follow, as well. And, best of all, it's core Drupal; no additional modules are necessary to use it. and the test cases in modules\simpletest\tests\entity_query.test are the authoritative documentation for EntityFieldQuery. The class itself "EntityFieldQuery" is in includes/ This article is just jumpstart type documentation.

Creating A Query

Here is a basic query looking for all articles with a photo that are tagged as a particular faculty member and published this year. In the last 5 lines of the code below, the $result variable is populated with an associative array with the first key being the entity type and the second key being the entity id (e.g., $result['node'][12322] = partial node data).

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'article')
  ->propertyCondition('status', NODE_PUBLISHED)
  ->fieldCondition('field_news_types', 'value', 'spotlight', '=')
  // See the comment about != NULL above.
  ->fieldCondition('field_photo', 'fid', 'NULL', '!=')
  ->fieldCondition('field_faculty_tag', 'tid', $value)
  ->fieldCondition('field_news_publishdate', 'value', $year . '%', 'like')
  ->fieldOrderBy('field_photo', 'fid', 'DESC')
  ->range(0, 10)
  // Run the query as user 1.
  ->addMetaData('account', user_load(1));

$result = $query->execute();
if (isset($result['node'])) {
  $news_items_nids = array_keys($result['node']);
  $news_items = entity_load('node', $news_items_nids);

->entityCondition($name, $value, $operator = NULL)

entityConditions are conditions most types of entity classes should support and are in DrupalDefaultEntityController class.

  • entity_type
    • value examples: 'node', 'taxonomy_term', 'comment', 'user', 'file'
    • operator examples: operator disregarded
    • $query->entityCondition('entity_type', 'node')
  • bundle. (not supported in comment entity types)
    • value examples: 'article', 'page'.
    • operator examples: '=' for strings and 'IN' for arrays.
    • $query->entityCondition('bundle', 'article')
  • revision_id.
    • value examples: 3,4,52,342
    • operator examples: =, <, >, != for integer values and 'IN' and 'NOT IN' for arrays of values.
    • $query->entityCondition('revision_id', $revision_id, '=')
  • entity_id. e.g. node id
    • value examples: 3,4,52,342
    • operator examples: =, <, >, != for integer values and 'IN' and 'NOT IN' for arrays of values.
    • $query->entityCondition('entity_id', array(17, 21,422), 'IN')

->propertyCondition($name, $value, $operator = NULL)

These conditions are specific to each entity implementation such as node, user, comment, etc. and generally map to the columns in the database where the entity itself is stored. e.g. node, users, comment, file_managed, taxonomy_term_data, etc tables. A grep/search for "Implements hook_entity_info()" will show code indicating the name of the entity's base table.

  • status (nodes). e.g. propertyCondition('status', NODE_PUBLISHED)
  • type (nodes). e.g. ->propertyCondition('type', array('article', 'page', 'blog'))
  • uid (nodes) .e.g. ->propertyCondition('uid', $uid)
  • uri (media) .e.g. ->propertyCondition('uri', '%.jpg', 'LIKE')
  • type (media) e.g. ->propertyCondition('type', 'image');

->fieldCondition($field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL)

These conditions are specific to a field implementation.

Looking at the body field in the article node type, a field condition would look like this:
->fieldCondition('body', 'value', 'A', 'STARTS_WITH')

  • field name. Though the field table in the database is named 'field_data_body', the actual field name is 'body'. This is in the field_config_instance table.
  • column. This is the column in the database that should be matched, with field name prefix removed. For body field, the database columns are: body_value, body_summary, body_format, and language. 'value', 'summary', 'format', and 'language' are the actual arguments you would use.
    Likewise an image field would use 'fid', 'alt', and 'title' as column names; an entity reference field would use a 'target_id' column name.

->fieldOrderBy($field, $column, $direction = 'ASC')

  • field. Notice again that the first parameter, field_photo, has the prefix "field_data_" removed. That is, if you look in the database, you would see a table called field_data_field_photo, but for this parameter you remove the prefix "field_data_" and just keep the "field_photo" suffix of the table name.
  • column. Notice again that in the database, in the field_data_field_photo table, you would find a column called field_photo_value, but here you must remove the prefix "field_photo_" and just keep the field title as "value".

->propertyOrderBy($column, $direction = 'ASC')

does not work on all properties.

->range($start = NULL, $length = NULL)

Restricts a query to a given range in the result set.


Sets the query to be a count query only, i.e.

$count = $query->count()->execute(); 

->addMetaData($key, $object)

Adds additional metadata to the query. One important usage of this method is to run the query as another user, since EntityFieldQuery's fieldCondition will take current user's permission into account, this is not always the desired result, to run the query as for example user 1, use the following code:

$query->addMetaData('account', user_load(1)); 


The $value and $operator parameters of entityCondition, propertyCondition, and fieldCondition behave the same. The $operator values depend on the $value format as summarized in

Random ordering

The easiest way for to order randomly is to add a tag and do an alter on it:

function mymodule_superblock() {
  $query = new EntityFieldQuery();
  $result = $query
    ->entityCondition('entity_type', 'node')
    ->fieldCondition('field_categories', 'tid', array('12','13'), 'IN')
    ->propertyCondition('status', NODE_PUBLISHED)

and then :

function mymodule_query_random_alter($query){

See : hook_query_TAG_alter

Example taxonomy term query

This example returns the taxonomy term ids of the terms in the Tags vocabulary.

function connect_country_fetch_countries() {
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'taxonomy_term')
    ->entityCondition('bundle', array('tags'))
  $result = $query->execute();
  $tids = array_keys($result['taxonomy_term']);

  return $tids;

What to feed to EntityQuery?

These functions can help you get a list of defined entities and fields that you can then feed to your queries:

dpm(entity_get_info()); //gets a list of all defined entities
dpm(field_info_fields()); //gets a list of all defined fields


Debugging the query

As explained on stackexchange you can debug entity field queries by implementing hook_query_alter() and using the dpm function from devel:

function CUSTOMMODULE_query_alter($query) {
  if ($query->hasTag('efq_debug') && module_exists('devel')) {
    dpm((string) $query);

When you have added this function to your custom module you can extend the query with addTag('efq_debug'), e.g. as follows:

$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node')->addTag('efq_debug')->execute(); 

Unexpected results

EntityFieldQuery conducts certain access checks. In some circumstances these may lead to unexpected results, for example on a cron run. It is possible to run an EntityFieldQuery without access checks by including the following tag.


Selected Resources

Code Examples

  • Tests for EntityFieldQuery are in core in modules\simpletest\tests\entity_query.test
  • grep/search drupal code base for "new EntityFieldQuery()" in core and contrib will find additional examples


Other resources