11

I am looking for the ID of the entity of type A and I know the ID of entity B that references A.

I found a few nice sources about EntityFieldQuery. I was amazed that i was getting results from .NET in google :) (is it a sign of Drupal's maturity ? :). But didnt manage to find this. Please help ...

Some of the sources :

This is what it looks like with entity loads - you will understand i need that query :) The wrapper is there for practice mainly. Note that it loads the target entity - quite a lot of queries.

  $b = entity_load('B', array($id));
  $bm = entity_metadata_wrapper('B', $sl[$id]);

  $tsl = $slm->field_sl_tpref->value();
  echo $tsl->id;
3
  • 1
    An EntityFieldQuery can only reference one set of entities, it cannot create relationships to other entities unfortunately. It can also only return one type of entity at a time so even if you could create these relationships the results would be unreliable.
    – Clive
    Apr 18, 2012 at 0:25
  • @Clive would you mind adding that as an answer, so i can confirm it ? thanks :)
    – mojzis
    Mar 5, 2013 at 6:22
  • Similar: Query custom node by user Entity Reference.
    – kenorb
    Aug 13, 2014 at 14:46

4 Answers 4

18

You can use target_id instead of value to retrieve entities based on the ID of referenced entities:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', <type-of-the-entity>);
$query->fieldCondition('<name-of-the-field-referring-the-other-entity>', 'target_id', <id-of-the-referenced-entity>, '=');
$results = $query->execute();
1
  • thanks, but i don't think that's what i was looking for ... i was trying to get the other direction, this way you would know the A and look for the B :)
    – mojzis
    Mar 5, 2013 at 6:28
2

err, is the Relation Module what you are looking for? It sounds like defining relations between X and Y entities is what you want todo. it has its own RelationQuery (a wrapper around EFQ) and RelationQueryEndpoints to easily get this kind of information.

1
  • thanks. unfortunately i have allready defined a few relations with entityreference, so switching over to relation would be problematic ... will try next time :).
    – mojzis
    Apr 18, 2012 at 18:12
2

I know this is an older question but for people getting to this from Google I figured I would throw another approach in here.

From the description above the setup has 2 entity types, A and B. B references A with entity reference I'm assuming. So if you have the id of B you should have a field with the ID of A stored in the database.

Code Notes:

  • Original NID - $original_node->nid This would be the ID of B
  • Bundle type - $type this should be the type of A
  • The field condition just looks for field that holds the reference
  • For more info on how to use EFQ see this

Code

// Start a new EFQ
$query = new EntityFieldQuery();

// Define query, the user load is probably not needed but sometimes is.
$query->entityCondition('entity_type', 'node')
      ->entityCondition('bundle', $type)
      ->fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')
      ->addMetaData('account', user_load(1));

// Execute query, result with have node key
$result = $query->execute();

// If results it will be in node key
if (isset($result['node'])) {
  $nids = array_keys($result['node']);
  // This example has multiple nodes being referenced by one node
  $nodes = node_load_multiple($nids, array('type' => $type));
  // Devel module needed
  dpm($nodes);
}

You can also set up two way entity references and do the same query above backwards. You could use a module like CER to make sure those references are kept up to date. Or setup a rule to keep the reference up to date, I've used both.

2
  • If field_NAME_OF_FIELD is multivalue will fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=') works? should it be changed to fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN'). Couldn't find anything about how to apply condition on multivalue entityreference field. any suggestion?
    – kiranking
    Mar 24, 2015 at 18:42
  • 1
    I know this an old comment but if you leave the '=' off EntityFieldQuery defaults to IN so fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid) would actually work in that situation. You probably already know that by now but just incase anyone else stumbles across that later :) May 2, 2017 at 21:56
1

a quite dynamic solution (a bit dirty too but I needed it quickly) so you do not need to hard code the name fo the referencing field and it is automatically handled with new referencing field you will add in the future :

in your custom module :

/**
 * Implement hook_field_create_instance().
 */
function MY_CUSTOM_MODULE_field_create_instance() {
  _MY_CUSTOM_MODULE_set_variable_node_back_references();
}

/**
 * Implement hook_field_delete_field().
 */
function MY_CUSTOM_MODULE_field_delete_field() {
  _MY_CUSTOM_MODULE_set_variable_node_back_references();
}

/**
 * Set Variable node_back_references.
 */
function _MY_CUSTOM_MODULE_set_variable_node_back_references() {
  $field_list = db_select('field_config', 'fc')
    ->fields('fc', array('field_name', 'data'))
    ->condition('fc.data', '%"foreign keys";a:1:{s:4:"node"%', 'like')
    ->condition('fc.deleted', 0);
  $field_list->innerJoin('field_config_instance', 'fci', 'fci.field_name = fc.field_name');
  $field_list->rightJoin('node_type', 'n', 'n.type = fci.bundle');
  $fields = $field_list->execute()->fetchAll();

  $fields_array = array();
  foreach ($fields as $field) {
    $unserialized = unserialize($field->data);
    if (isset($unserialized['settings']['handler_settings']['target_bundles'])) {
      foreach ($unserialized['settings']['handler_settings']['target_bundles'] as $bundle) {
        $fields_array[$bundle][] = $field->field_name;
      }
    }
  }

  variable_set('node_back_references', $fields_array);
}

function _MY_CUSTOM_MODULE_get_referencing_nodes($node) {
  $nids = array();
  $fields = variable_get('node_back_references', array());
  if (isset($fields[$node->type])) {
    foreach ($fields[$node->type] as $field) {
      $query = new \EntityFieldQuery();
      $query->entityCondition('entity_type', 'node');
      $query->propertyCondition('status', 1);
      $query->fieldCondition($field, 'target_id', $node->nid);
      $result = $query->execute();
      $nids = isset($result['node']) ? array_merge(array_keys($result['node']), $nids) : $nids;
    }
    $nodes = (!empty($nids)) ? node_load_multiple($nids) : array();

    return $nodes;
  }

  return $nids;
}

where you need to get the parent nodes given the child node :

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);

Your Answer

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

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