\EntityFieldQuery
class
Retrieves entities matching a given set of conditions.

Retrieves entities matching a given set of conditions.

This class allows finding entities based on entity properties (for example, node->changed), field values, and generic entity meta data (bundle, entity type, entity ID, and revision ID). It is not possible to query across multiple entity types. For example, there is no facility to find published nodes written by users created in the last hour, as this would require querying both node->status and user->created.

Normally we would not want to have public properties on the object, as that allows the object's state to become inconsistent too easily. However, this class's standard use case involves primarily code that does need to have direct access to the collected properties in order to handle alternate execution routines. We therefore use public properties for simplicity. Note that code that is simply creating and running a field query should still use the appropriate methods to add conditions on the query.

Storage engines are not required to support every type of query. By default, an EntityFieldQueryException will be raised if an unsupported condition is specified or if the query has field conditions or sorts that are stored in different field storage engines. However, this logic can be overridden in hook_entity_query_alter().

Also note that this query does not automatically respect entity access restrictions. Node access control is performed by the SQL storage engine but other storage engines might not do this.

Comments

axel.rutz’s picture

malc0mn’s picture

mlsamuelson’s picture

From https://drupal.org/node/1343708

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

Posting this here, for lack of a better place to bring it to the attention of those using EntityFieldQuery().

I had no idea, and this killed a morning of productivity for me.

aaronbauman’s picture

See also DANGEROUS_ACCESS_CHECK_OPT_OUT query tag added to EntityFieldQuery.

I'm not clear whether this is functionally equivalent to the addMetaData approach, but it seems to be the favored method.

pedrambehroozi’s picture

Is it feasible to add Group By functionality in EntityFieldQuery?
Like: propertyGroupBy or fieldGroupBy

amagdy’s picture

$taxonomyQuery = new EntityFieldQuery();
$taxonomyTerms = $taxonomyQuery->entityCondition('entity_type', 'taxonomy_term')
->propertyCondition('vid', 2) //change 2 to any vocabulary ID
->propertyOrderBy('weight')
->execute();
foreach($taxonomyTerms['taxonomy_term'] as $term) {
$relevantTerms[] = $term->tid;
}

amagdy’s picture

  $taxonomnyQuery = new EntityFieldQuery();
  $terms = $taxonomnyQuery->entityCondition('entity_type', 'taxonomy_term')
    ->propertyCondition('vid', 2)
    ->fieldCondition('field_status', 'value', 1)
    ->propertyOrderBy('tid', 'DESC')
    ->range(0, 5)
    ->execute();

  if (isset($terms['taxonomy_term'])) {
    $tids = array_keys($terms['taxonomy_term']);
    foreach ($tids as $tid) {
      $term = taxonomy_term_load($tid);
      // do some stuff here
    }
  }

here is some actual code, I loading the latest 5 terms with a condition on a custom field status, ordering by tid descending

then loading them to do some operation

lgomezma’s picture

Is there any possible way to use EntityFieldQuery to query entities per domain? Given that Domain Access is not in the core I can imagine that this isn't possible, but wouldn't it be an optional desirable feature? I ended up using a SelectQuery to achieve this instead.

reign85’s picture

Actually, EFQ can only interact with "standard" Drupal fields and because Domain Access adds a table in the database called "domainsource" rather than the standard way that other fields are implemented in the database (like **fieldname**).

Meanwhile a better system is released, you can use the SelectQuery class or just simply get all the node and use a foreach filter on domains or subdomains property

adammalone’s picture

This has been replaced with entity_query in Drupal 8.

wizonesolutions’s picture

It must have changed again. That link is dead.

adammalone’s picture

Looks like Drupal::entityQuery is where it ended up.

ooiyitung’s picture

Hi

We have a master and a slave database and would like EntityFieldQuery to always query off the slave database since it's just reading stuff.

In settings.php, the database config is as below:

$databases['default]['default'] = array(...);
$databases['default]['slave'] = array(...);

Without using EntityFieldQuery, we could do the following, which seems to be working correctly (reading from slave):

$query = db_select('node', 'n', array("target" => "slave"));

However, there does not seem to be a parameter in EntityFieldQuery that allows targeting the slave database, any idea?

Thanks in advance

eie0558’s picture

I also think it would be efficient for EntityFieldQuery to use slave in my situation. Did you find an answer to this? I would appreciate if you could share any of your finding. I would appreciate any help.

muku93’s picture

i am quite lost in which file am i supposed to used the entity field query

ludovic_reus’s picture

For some reasons i can't achieve to get the node title with this.

$field_list = array('my_field_name');

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node', '=');
$query->propertyCondition('type', $node_type);

$query_result = $query->execute();	
$entities = $query_result['node'];

$node_fields = field_info_instances('node', $node_type);

foreach ($field_list as $field_name) {
	//Recover current field_id from field structure
	$field_id = $fields[$field_name]['field_id'];
	//Populate query_result with field content
	field_attach_load('node', $entities, FIELD_LOAD_CURRENT, array('field_id' => $field_id));
}

This code will return more than my expected fields due to the drupal cache even the nid but not the title...

For now i only found a workaround using node_load_multiple

kingandy’s picture

Unless you have a module turned on that changes things (eg Title), native Drupal 7 node titles aren't fields so can't be loaded using the field API. You could query the database to fetch it from the Node table, but loading the node is probably safer - it'll accommodate any other modules that act on load to change the title.

kingandy’s picture

FWIW, here's how you'd load nodes from an EFQ result:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node', '=');
$query->propertyCondition('type', $node_type);

$query_result = $query->execute();
if (isset($query_result['node'])) {
  // EFQ query results are keyed by entity ID
  $node_ids = array_keys($query_result['node']);
  $nodes = node_load_multiple($node_ids);
}
arruk’s picture

I was directed here from the node_load_multiple page b/c conditions is deprecated, but I'm not seeing the single most important feature of node_load_multiple -- the ability to pass an array of nids to load. Does someone have an example of this? Or am I back to using a loop?

kingandy’s picture

The general principle is that instead of passing conditions into node_load_multiple, you first use EntityFieldQuery to get the NIDs and then pass those into NLM. Typically the $conditions var was used instead of $nids rather than as well as. I guess in this scenario you have a list of known NIDs that you want to filter down by some arbitrary condition? In that case you'd still do your EFQ, but include your original list of node IDs as another condition.

So say for example you had a list of NIDs and wanted to only load the ones that were published - you'd do something like this:

$query = new EntityFieldQuery;
$result = $query->entityCondition('entity_type', 'node')
  ->propertyCondition('nid', $nids) // Here instead of in $nids
  ->propertyCondition('status', 1) // Here instead of in $conditions
  ->execute();
if (empty($result['node'])) {
  return array(); // No applicable nodes found, no nodes to load.
}
$filtered_nids = array_keys($result['node']);
$nodes = node_load_multiple($filtered_nids);
kingandy’s picture

(I'd recommend asking questions like this in the Developer forum - you're more likely to get a response, and when you do, you can also get a notification...)