Crea un EntityFieldQuery che seleziona entità referenziate


10

Sto cercando l'ID dell'entità di tipo A e conosco l'ID dell'entità B che fa riferimento ad A.

Ho trovato alcune belle fonti su EntityFieldQuery. Sono rimasto sorpreso dal fatto che stavo ottenendo risultati da .NET in Google :) (è un segno della maturità di Drupal? :). Ma non sono riuscito a trovarlo. Per favore aiuto ...

Alcune delle fonti:

Questo è quello che sembra con i carichi di entità - capirai che ho bisogno di quella query :) Il wrapper è lì principalmente per la pratica. Nota che carica l'entità target - molte query.

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

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

1
Può EntityFieldQueryfare riferimento solo a un insieme di entità, purtroppo non può creare relazioni con altre entità. Può anche restituire un solo tipo di entità alla volta, quindi anche se tu potessi creare queste relazioni i risultati sarebbero inaffidabili.
Clive

@Clive ti dispiacerebbe aggiungerlo come risposta, quindi posso confermarlo? grazie :)
mojzis

Risposte:


15

È possibile utilizzare target_idinvece di valuerecuperare entità in base all'ID delle entità referenziate:

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

grazie, ma non credo sia quello che stavo cercando ... stavo cercando di prendere l'altra direzione, in questo modo avresti conosciuto la A e avrei cercato la B :)
mojzis

2

err, il Modulo di relazione è quello che stai cercando? Sembra che definire le relazioni tra entità X e Y sia ciò che si desidera fare. ha i propri RelationQuery (un wrapper attorno a EFQ) e RelationQueryEndpoints per ottenere facilmente questo tipo di informazioni.


Grazie. purtroppo ho già definito alcune relazioni con entityreference, quindi passare alla relazione sarebbe problematico ... ci proverò la prossima volta :).
Mojzis,

2

So che questa è una domanda più vecchia, ma per le persone che arrivano a Google da questo ho pensato che avrei gettato un altro approccio qui.

Dalla descrizione sopra la configurazione ha 2 tipi di entità, A e B. B riferimenti A con riferimento entità presumo. Quindi se hai l'ID di B dovresti avere un campo con l'ID di A memorizzato nel database.

Note sul codice:

  • NID originale - $original_node->nidQuesto sarebbe l'ID di B
  • Tipo di pacchetto: $typequesto dovrebbe essere il tipo di A
  • La condizione del campo cerca solo il campo che contiene il riferimento
  • Per ulteriori informazioni su come utilizzare EFQ, consultare questo

Codice

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

Puoi anche impostare riferimenti di entità a due vie ed eseguire la stessa query sopra all'indietro. È possibile utilizzare un modulo come CER per assicurarsi che tali riferimenti siano aggiornati. O impostare una regola per mantenere aggiornato il riferimento, ho usato entrambi.


Se field_NAME_OF_FIELD è multivalore funzionerà fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')? dovrebbe essere cambiato in fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN'). Impossibile trovare informazioni su come applicare la condizione sul campo di riferimento entità multi-valore. qualche suggerimento?
Kirking il

1
Conosco questo vecchio commento, ma se si lascia '=' su EntityFieldQuery per impostazione predefinita su IN così fieldCondition ('field_NAME_OF_FIELD', 'target_id', $ original_node-> nid) funzionerebbe effettivamente in quella situazione. Probabilmente lo sapete già ormai, ma in caso
contrario

1

una soluzione abbastanza dinamica (un po 'sporca ma ne avevo bisogno rapidamente) quindi non è necessario codificare il nome nel campo di riferimento e verrà automaticamente gestito con un nuovo campo di riferimento che aggiungerai in futuro:

nel tuo modulo personalizzato:

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

dove è necessario ottenere i nodi padre dato il nodo figlio:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.