web-dev-qa-db-fra.com

Créer un EntityFieldQuery qui sélectionne les entités référencées

Je recherche l'ID de l'entité de type A et je connais l'ID de l'entité B qui fait référence à A.

J'ai trouvé quelques sources sympas sur EntityFieldQuery. J'ai été étonné que j'obtienne des résultats de .NET dans google :) (est-ce un signe de maturité de Drupal? :). Mais n'a pas réussi à trouver cela. Veuillez aider ...

Quelques sources:

Voici à quoi cela ressemble avec des charges d'entité - vous comprendrez que j'ai besoin de cette requête :) Le wrapper est là pour la pratique principalement. Notez qu'il charge l'entité cible - beaucoup de requêtes.

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

  $tsl = $slm->field_sl_tpref->value();
  echo $tsl->id;
10
mojzis

Vous pouvez utiliser target_id au lieu de value pour récupérer les entités en fonction de l'ID des entités référencées:

$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();
15
pablo

euh, est le Relation Module ce que vous cherchez? On dirait que définir les relations entre les entités X et Y est ce que vous voulez faire. il a ses propres RelationQuery (un wrapper autour d'EFQ) et RelationQueryEndpoints pour obtenir facilement ce type d'informations.

2
tenken

Je sais que c'est une question plus ancienne, mais pour les gens qui y arrivent de Google, j'ai pensé que je lancerais une autre approche ici.

D'après la description ci-dessus, la configuration a 2 types d'entités, A et B. B référence A avec la référence d'entité que je suppose. Donc, si vous avez l'ID de B, vous devriez avoir un champ avec l'ID de A stocké dans la base de données.

Notes de code:

  • NID d'origine - $original_node->nid Ce serait l'ID de B
  • Type de bundle - $type ce devrait être le type de A
  • La condition de champ recherche simplement le champ contenant la référence
  • Pour plus d'informations sur l'utilisation d'EFQ, voir 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);
}

Vous pouvez également configurer des références d'entité bidirectionnelles et effectuer la même requête ci-dessus à l'envers. Vous pouvez utiliser un module comme CER pour vous assurer que ces références sont à jour. Ou définissez une règle pour maintenir la référence à jour, j'ai utilisé les deux.

2
burnsjeremy

une solution assez dynamique (un peu sale aussi mais j'en avais besoin rapidement) donc vous n'avez pas besoin de coder en dur le nom du champ de référencement et il est automatiquement géré avec un nouveau champ de référencement que vous ajouterez à l'avenir:

dans votre module personnalisé:

/**
 * 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;
}

où vous devez obtenir les nœuds parents étant donné le nœud enfant:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
1
Gueno