Frank Robert Anderson

I am a Developer who does web good and likes to do other stuff good too.

Blog Tutorials Rants Everything Back to My Site

Need a join in an EntityFieldQuery, how about a subquery?

I saw this over at stackexchange and I had to write about it.

Shaddap and give me the code:

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

In case you do not want to click the link I put in the opening paragraph. That is the code.

What was the problem?

This is the question.

I thought this was an easy task, yet there does not seem to be a Drupal-method for this. I came as far as knowing I have to use EntityFieldQuery for this - because the API said conditions for userloadmultiple() are deprecated.

So I tried this:

  $query = new EntityFieldQuery;
  $query
    ->entityCondition('entity_type', 'user')
    ->propertyCondition('rid',array(1,2,3);

  $result = $query->execute();

What this developer wants to do is a query to find all users of a certain role. The problem here is that propertyConditions will only allow querying based on the fields of the base table for the entity and role isn't in the user table. Further, role isn't even a field so fieldCondition wouldn't help either. Also, when doing an EntityFieldQuery we cannot do a typical JOIN as we normally would.

What is the solution.

To get around this we need to limit the EntityFieldQuery based on the uid and not the role. That means we need to get a the list of all the uids from the user_role table.

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

This will give us a query that will return a list of all the user ids for a particular role. Then we can use that to do a propertyCondition on the EntityFieldQuery to limit it to those uids.

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

The interesting thing about this is that this isn't an array of results being passed to the propertyCondition. Instead, this is passing the query object. Then, Drupal's query builder will build the query to include that.

Seriously, well done with the whole DB layer in Drupal 7.

Written on June 10, 2015 by Frank Robert (frob) Anderson

Social Networks

Blogroll

BTMash's blob of contradictions
LA Grafitti
Justin Biard's icodealot
Copyright Frank Robert Anderson 2020