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();
2
  • 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, 2013 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, 2015 at 7:11

2 Answers 2

30

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.

10
  • Is there a better way to do it in a single function? Even if it's not EntityFieldQuery Oct 5, 2012 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, 2012 at 17:21
  • I'll go with that. Thx Oct 5, 2012 at 17:33
  • @Clive ... oh this answer is really interesting. Like it. :P
    – tenken
    Oct 5, 2012 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, 2013 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.

1
  • Excellent solution for cases like mine, with custom tables. Awesome work! Nov 3, 2017 at 9:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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