20

I'd like to run a query using the EntityFieldQuery object. I need value from both the node and node_access table therefore I'd need to use INNER JOIN. From the d.o documentation I can't figure out how this is possible.

Here's what I have --

$query = new EntityFieldQuery();
$result = $query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'node_access')
->propertyCondition('type', 'external_link')
->propertyCondition('status', 1)
->fieldCondition('gid', '3', '=')
->fieldCondition('realm', 'domain_id', '=')
->fieldCondition('grant_view', '1', '>=')
->range(0,1)
->execute();
  • 1
    Although it can't be done on-the-fly in Drupal 7, it can be done in Drupal 8 (unreleased at the time of this writing). See Entity Field query got join support for details (including an example). – colan Oct 17 '13 at 18:17
  • In Drupal 8 all conditions is Like that (->condition()). Ex of an EFQ in D8: $result = \Drupal::entityQuery('node') ->condition('type', array('entity_a', 'entity_b'), 'IN') ->condition('status', NODE_PUBLISHED) ->condition('field_myfield.value', '5', '=') ->execute(); In Drupal 8 EFQ the collumn is defined directly in name field by field_name.value or field_name.target_id in drupal 7 is ->fieldCondition('field_name', 'target_id', $entities_a, 'IN'); – woprrr Sep 2 '15 at 7:11
29

You can't add extra joins to an EntityFieldQuery directly (it's not supported), but you could add a tag to the query, implement hook_query_TAG_alter(), and add the join manually when the query is converted down to a standard db query.

This isn't tested but will probably get you most of the way there:

$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'node_access')
  // etc
  ->addTag('MYTAG');

// get the query results as normal

And then the query alter function:

function MYDMOULE_query_MYTAG_alter(QueryAlterableInterface $query) {
  $query->join('node_access', 'node_access', 'node_access.nid = node.nid');
}

The other way to do it would be to subclass EntityFieldQuery itself and add the join, but I think the above method is simpler in this case.

  • Is there a better way to do it in a single function? Even if it's not EntityFieldQuery – Allan Bendy Oct 5 '12 at 17:16
  • 2
    Not really, the only other way is to build the query up manually using db_select, then you can have as much control as you want over it – Clive Oct 5 '12 at 17:21
  • I'll go with that. Thx – Allan Bendy Oct 5 '12 at 17:33
  • @Clive ... oh this answer is really interesting. Like it. :P – tenken Oct 5 '12 at 17:51
  • 2
    @Michiel No EntityFieldQuery doesn't do any caching, it just wraps around a SelectQuery and adds some methods for entities. Those extra methods account for the slight (very slight) performance decrease you'd experience using it as opposed to a regular SelectQuery – Clive Jun 28 '13 at 11:41
3

If you're using custom properties with your own tables, the tag method won't work. You need to use subqueries instead:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'user');

$roles_subquery = db_select('users_roles', 'ur');
$roles_subquery->fields('ur', array('uid'));
$roles_subquery->condition('rid', $my_role_id);

$query->propertyCondition('uid', $roles_subquery, 'IN');

See Need a join in an EntityFieldQuery, how about a subquery? for details.

  • Excellent solution for cases like mine, with custom tables. Awesome work! – Ignacio Segura Postigo Nov 3 '17 at 9:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.