Last updated March 13, 2015. Created on November 16, 2011.
Edited by tz_earl, drupalshrek, batigolix, dalin. Log in to edit this page.

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.

http://api.drupal.org/api/drupal/includes--entity.inc/class/EntityFieldQ... and the test cases in modules\simpletest\tests\entity_query.test are the authoritative documentation for EntityFieldQuery. The class itself "EntityFieldQuery" is in includes/entity.inc. 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). Note the $result won't have the 'node' key when it's empty, thus the check using isset, this is explained here.

<?php
$query
= new EntityFieldQuery();

$query->entityCondition('entity_type', 'node')
  ->
entityCondition('bundle', 'article')
  ->
propertyCondition('status', NODE_PUBLISHED)
  ->
fieldCondition('field_news_types', 'value', 'spotlight', '=')
  ->
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)
  ->
addMetaData('account', user_load(1)); // Run the query as user 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 'target_id' and 'target_type' as column names.

->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.

->count()

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));

Operators

The $value and $operator parameters of entityCondition, propertyCondition, and fieldCondition behave the same. The $operator values depend on the $value format as summarized in http://api.drupal.org/api/drupal/includes--entity.inc/function/EntityFie...

Random ordering

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

<?php
function mymodule_superblock() {
 
$query = new EntityFieldQuery();
 
$result = $query
   
->entityCondition('entity_type', 'node')
    ->
fieldCondition('field_categories', 'tid', array('12','13'), 'IN')
    ->
propertyCondition('status', NODE_PUBLISHED)
    ->
addTag('random')
    ->
range(0,5)
    ->
execute();
}
?>

and then :

<?php
function mymodule_query_random_alter($query){
 
$query->orderRandom();
}
?>

See : hook_query_TAG_alter

Example taxonomy term query

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

<?php
 
function connect_country_fetch_countries() {
 
$query = new EntityFieldQuery();
 
$query->entityCondition('entity_type', 'taxonomy_term')
  ->
entityCondition('bundle', array('tags'))
  ->
propertyOrderBy('weight');
 
$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:

<?php
 dpm
(entity_get_info()); //gets a list of all defined entities
dpm(field_info_fields()); //gets a list of all defined fields
?>

Debugging

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

<?php
function CUSTOMMODULE_query_alter($query) {
  if (
$query->hasTag('efq_debug') && module_exists('devel')) {
   
dpm((string) $query);
   
dpm($query->arguments());
  }
}
?>

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

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

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

Articles

Other resources

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

TuWebO’s picture

There is a
addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
that will bypass access checkings, here is the documentation http://drupal.org/node/1597378

Maybe in some cases could be good use this tag instead of running the query as user 1, but we should know what we are doing, since we are bypassing all access checkings.

RavindraSingh’s picture

I have used below mentioned example of EntityFieldQuery. it returns ony 3 fields.

1. Node Id
2. Type
3. Title

What i have to change in this query to get all columns with CCK fields.

$query = new EntityFieldQuery();

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

$result = $query->execute();

jjonj’s picture

You should look at node_load
http://api.drupal.org/api/drupal/modules!node!node.module/function/node_...
with that you can use the NID to get the full node.

RavindraSingh’s picture

node_load() does not add conditions for cck fields. wheather EntityFieldQuery query support for applying conditions like

->propertyCondition('status', 1)
->fieldCondition('field_news_types', 'value', 'spotlight', '=')
Anurag Ashok’s picture

Use EntityFieldQuery first. You will get a list of node ids of all nodes that match the condition.

then use $node = node_load();
and in $node you will have all the field values.

RavindraSingh’s picture

node_load() loads all the data which i don't want i want some specific fields.

earwax’s picture

Yeah, with node_load(), it's all or nothing. Otherwise, you can write your own SQL query with tons of JOINS, which is what I have done. :(

johnbarclay’s picture

this example solves the problem of loading all the nodes and getting the data. http://treehouseagency.com/blog/tim-cosgrove/2012/02/16/entityfieldquery...

use entity_load() or node_load_multiple()

Application Developer University of Illinois Office of Communications for Enrollment Management, johnbarclay.com. Consultant, JohnBarclay.com

e0ipso’s picture

OwilliwO’s picture

I actually work on a Drupal project, with several nodes existing. And I create a module which add a date field to all this nodes (to delay publication in this case). I want to get all nodes that don't have this delayed publication field, just to set it with a default value in a bulk operation for example..

<?php
$efq
= new EntityFieldQuery();
$efq->entityCondition('entity_type', 'node')
    ->
propertyCondition('type', 'article')
   
// doesn't work because field isn't set yet at this moment
   
->fieldCondition('delayed_publication', 'value', NULL);
?>

Any idea ?

TanvirAhmad’s picture

Try with node load to see if field is in array or not for that node.

t@n

ivanjaros’s picture

This doesn't work form me:
->fieldCondition(field_name, field_column, 'NULL', '!=')

I had to use:
->fieldCondition(field_name, field_column, 'NULL', 'IS NOT NULL').

ymakux’s picture

I think it should be "<>" instead of '!='

natemow’s picture

Hoping this helps those new to EFQ...simple wrapper class that builds your query based on keyed array params, then returns data in various formats (e.g. renderable array, entity, entity_id). Very much inspired by the related articles on this page. Our new distro (Totem, http://drupal.org/project/totem) uses this exclusively for all queries...no Views required!

http://drupalcode.org/project/totem.git/blob_plain/HEAD:/modules/feature...

This class could probably stand some improvement, so any feedback, patches, etc. are very welcome (preferably in that project's issue queue).

danharper’s picture

How can I filter by the created date of an entity type?

There is the created field in my entitytype table.

Thanks

Scott Falconer’s picture

Something like this should work:

<?php
 
// Timestamp for ten minutes ago
 
$time_since = time() - 600;
 
 
$query = new EntityFieldQuery();
 
$query->entityCondition('entity_type', 'my_entity')
 
// Filter by items created since timestamp (eg. in the last 10 minutes).
   
->propertyCondition('created', $time_since, '>');
?>
RavindraSingh’s picture

@Scott Falconer gives right answer but for condition fields. and you want to filter all data with their created date.
We can also use propertyOrderBy

<?php
 $query
= new EntityFieldQuery();
 
$query->entityCondition('entity_type', 'my_entity')
  
$query->propertyOrderBy('created', 'DESC');
?>
danharper’s picture

I think my question was badly worded, I didn't want to filter rather I wanted results between two dates I used the following.

I actually used it liked this, where the instance is an array that holds a timstamp.

<?php
$instance
= array('start' => 1370214001, 'end' => 1370905199);

 
$query = new EntityFieldQuery();
 
$query->entityCondition('entity_type', 'my_entity')
   ->
propertyCondition('created', array($instance['start'], $instance['end']), 'BETWEEN');
?>

Dan

tcalin’s picture

I have the following code

$node_query = new EntityFieldQuery();
$nodes = $node_query->entityCondition('entity_type', 'node')
          ->entityCondition('bundle', 'stm_emploi')
          ->fieldCondition('field_stm_emploi_extid', 'value', $stmjob['id'], '=')
          ->execute();

These lines should return all nodes of type stm_emploi that have a certain value for field_stm_emploi_extid field. Ideally it should return only one node since field_stm_emploi_extid contains unique values. Well, after someone deleted nodes directly from the node table, the query still returns the nid for those nodes (there are some orphaned rows in field_data_field_stm_emploi_extid table). It does not make a join between the node table and the field's table. The solution was to get back using db_select.

dobe’s picture

I am not sure if it is the same issue or not. But I had the similar issue when I didn't use $result = $query->execute(); to execute the query.

selvamkf’s picture

I used a query like this,

<?php
  $query
->entityCondition('entity_type', 'node')
    ->
entityCondition('bundle', 'TYPE')
    ->
entityCondition('entity_id', $already_processed, "NOT IN")
    ->
propertyCondition('created', array(REQUEST_TIME- 60 * 60 * 60 * 60, REQUEST_TIME ), "between")
    ->
propertyOrderBy('created', 'DESC')
    ->
range(0, 25)
?>

when $already_processed is empty array, it returned no results, while $already_processed=array(0), it returned all results as expected. Is it a bug when entity_id with NOT IN condition?

danielphenry’s picture

selvamkf,

One of the purposes of using object to query is you can edit them conditionally a lot easier. Try setting up your code like this:

  $query->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'TYPE');
  if (!empty($already_processed)) {
    $query->entityCondition('entity_id', $already_processed, "NOT IN")
  }
  $query->propertyCondition('created', array(REQUEST_TIME- 60 * 60 * 60 * 60, REQUEST_TIME ), "between")
    ->propertyOrderBy('created', 'DESC')
    ->range(0, 25)
samsterlin’s picture

danielphenry,

Thanks alot It works for me.

This code is displaying a last 30 days records.

<?php
    $query
= new EntityFieldQuery();
   
$query->entityCondition('entity_type', 'node')
               ->
entityCondition('bundle', 'TYPE')
               ->
propertyCondition('status',1)
               ->
propertyCondition('created', array(REQUEST_TIME- 60 * 60 * 24 * 30, REQUEST_TIME ), "between")
               ->
propertyOrderBy('created', 'DESC');
  
$result = $query->execute();
?>

    
spoetnik’s picture

Unlike db_query(), EntityFieldQuery doesn't support Union()

Any thoughts on a workaround? Like merge the resulting arrays, but keep the overall order of the array?

bhupendra_kanojiya’s picture

When I am using not null(!=) it's working, but not working for fetch the null value

$query = new EntityFieldQuery();
$entities = $query->entityCondition('entity_type', 'node')
->entityCondition('bundle', $content_type)
->propertyCondition('status', 1)
->fieldCondition('field_suggested_tags', 'tid', $child_term)
->fieldCondition('field_close_date', 'value','NULL','=')
->execute();

Bhupendra Kanojiya

sebto’s picture

This class is great. I wrote a tutorial to use EntityFieldQuery in my blog for persians.

fuerst’s picture

Use nicedpq($query) instead of dpm((string) $query) to get a nice formatted debug output.
You need to install the Nice DPQ module for that.

SlyK’s picture

In my project I'm using EntityFieldQuery alot to get some entities with given conditions, but working with resulting array of execute() function - is boring and makes code dirty IMHO. So I created helper class used only to load entities. Most of the time result is self describing one-liners instead of variables mess. I know it not covers all posibilities of EntityQuery, but 90% of my usage of it is loading Entities with some conditions.

<?php
/**
 * Easily load entities with power of EntityFieldQuery
 *
 * Usage example:
 * $country = (new EntityLoadQuery('country'))->propertyCondition('city_tid', 88)->loadSingle();
 *
 * @author Kirill Kuzmitskyy (toopro.org)
 */
class EntityLoadQuery extends EntityFieldQuery {

   
/**
     * @param string $entity_type tell the type of the entity to load
     */
   
public function __construct($entity_type) {
       
$this->entityCondition('entity_type', $entity_type);
    }

       
/**
     * @param $entity_type tell the type of the entity to load
     * @return EntityLoad
     */
   
public static function query($entity_type) {
        return new
EntityLoad($entity_type);
    }

   
/**
     * @return array of loaded entities keyed by Names or IDs
     */
   
public function load() {
       
$eqResult = $this->execute();
        foreach (
$eqResult as $entity_type=>$keyedArray)
            return (
module_exists('entity'))
                ?
entity_load_multiple_by_name($entity_type, array_keys($keyedArray))
                :
entity_load($entity_type, array_keys($keyedArray));
        return array();
    }

   
/**
     * @return object one loaded entity of given type
     */
   
public function loadSingle() {
       
$ents = $this->load();
        return
reset($ents);
    }

   
/**
     * @return array of Names or IDs of the entities matching query
     */
   
public function loadIDs() {
       
$eqResult = $this->execute();
       
$eqResult = reset($eqResult);
        return (
$eqResult) ? $eqResult : array();
    }

}
?>

As the result, instead of doing like this:

<?php
$result
= (new EntityFieldQuery())
                    ->
entityCondition('entity_type','country')
                   ->
propertyCondition('city_tid', 55)
                   ->
execute();

if (isset(
$result['country'])) {
 
$news_items_ids = array_keys($result['country']);
 
$entities = entity_load('country', $news_items_nids);
 
$country = reset($entities);
}
?>

I have this code:

<?php
$country
= EntityLoad::query('country')->propertyCondition('city_tid', 88)->loadSingle();
?>

I think it's more readable and less non-business logic in code. Hope someone will like it too :) And correct me if I'm doing something wrong with such approach.

lipinponmala007’s picture

Interesting...This will work..but I think the real power of the original one is the ability to keep the query with out executing add the fields and exicute them at the time we need. This is how I observe it ... :)

ehsankhfr’s picture

Thanks!

I have Finnish style of open-source coding! How about you?

nithinkolekar’s picture

Is there a way to typecast while checking condition?
ex:
fieldCondition('field_total_price', 'value',$total, '!=')

if stored value of field field_total_price is 1000.00 and $total is 1000 could it be possible to typecast the value(in this case int or float) while comparing?