Zbuduj EntityFieldQuery, który wybiera encje odniesienia


10

Szukam identyfikatora jednostki typu A i znam identyfikator jednostki B, która odwołuje się do A.

Znalazłem kilka fajnych źródeł o EntityFieldQuery. Byłem zaskoczony, że otrzymałem wyniki z .NET w google :) (czy to oznaka dojrzałości Drupala? :). Ale nie udało mi się tego znaleźć. Proszę pomóż ...

Niektóre źródła:

Tak to wygląda z ładowaniami encji - zrozumiesz, że potrzebuję tego zapytania :) Opakowanie służy głównie do ćwiczeń. Zauważ, że ładuje jednostkę docelową - całkiem sporo zapytań.

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

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

1
EntityFieldQueryMoże odwoływać się tylko jeden zbiór jednostek, nie mogą tworzyć relacje z innymi podmiotami niestety. Może również zwracać tylko jeden typ encji na raz, więc nawet gdyby można było utworzyć te relacje, wyniki byłyby niewiarygodne.
Clive

@Clive, czy mógłbyś dodać to jako odpowiedź, więc mogę to potwierdzić? dzięki :)
mojzis,

Odpowiedzi:


15

Możesz użyć target_idzamiast valuedo pobierania encji na podstawie identyfikatora encji, do których istnieją odniesienia:

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

dzięki, ale nie sądzę, że tego właśnie szukałem ... starałem się
pójść

2

err, czy szukasz modułu relacyjnego ? Wygląda na to, że zdefiniowanie relacji między elementami X i Y jest tym, czego chcesz. ma własne RelationQuery (opakowanie wokół EFQ) i RelationQueryEndpoints, aby łatwo uzyskać tego rodzaju informacje.


dzięki. niestety już zdefiniowałem kilka relacji z odniesieniem do bytu, więc przejście do relacji byłoby problematyczne ... spróbuję następnym razem :).
mojzis,

2

Wiem, że to jest starsze pytanie, ale dla ludzi, którzy docierają do tego z Google, pomyślałem, że rzuciłbym tutaj inne podejście.

Z powyższego opisu konfiguracja ma 2 typy encji, A i B. B referencje A z referencją encji Zakładam. Więc jeśli masz identyfikator B, powinieneś mieć pole z identyfikatorem A przechowywane w bazie danych.

Uwagi do kodu:

  • Oryginalny NID - $original_node->nidbyłby to identyfikator B
  • Rodzaj pakietu - $typepowinien to być typ A
  • Warunek pola szuka tylko pola zawierającego odniesienie
  • Aby uzyskać więcej informacji na temat korzystania z EFQ, zobacz to

Kod

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

Możesz także skonfigurować dwukierunkowe odwołania do encji i wykonać to samo zapytanie powyżej. Możesz użyć modułu takiego jak CER, aby upewnić się, że te referencje są aktualne. Lub skonfiguruj regułę, aby aktualizować referencje, użyłem obu.


Jeśli field_NAME_OF_FIELD jest wielowartościowy, czy zadziała fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')? powinien zostać zmieniony na fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN'). Nie można znaleźć niczego o tym, jak zastosować warunek w polu odwołania do jednostki wielowartościowej. jakieś sugestie?
Kiringing

1
Wiem, że to stary komentarz, ale jeśli pozostawisz '=' wyłączone EntityFieldQuery domyślnie ustawiony jest na IN, więc fieldCondition ('field_NAME_OF_FIELD', 'target_id', $ original_node-> nid) faktycznie działałoby w tej sytuacji. Prawdopodobnie już o tym wiesz, ale po prostu wpadnij na kogoś, kto natknie się na to później :)
burnsjeremy

1

dość dynamiczne rozwiązanie (trochę brudne, ale potrzebowałem go szybko), więc nie musisz sztywno kodować nazwy pola referencyjnego i jest ono obsługiwane automatycznie z nowym polem referencyjnym, które dodasz w przyszłości:

w niestandardowym 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;
}

gdzie musisz uzyskać węzły nadrzędne, biorąc pod uwagę węzeł podrzędny:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.