Создайте EntityFieldQuery, который выбирает ссылочные объекты

10

Я ищу идентификатор объекта типа A и знаю идентификатор объекта B, который ссылается на A.

Я нашел несколько хороших источников о EntityFieldQuery. Я был поражен, что я получил результаты от .NET в Google :) (это признак зрелости Drupal? :). Но не удалось найти это. Пожалуйста помоги ...

Некоторые из источников:

Вот как это выглядит с нагрузками на сущности - вы поймете, что мне нужен этот запрос :) Оболочка предназначена в основном для практики. Обратите внимание, что он загружает целевой объект - довольно много запросов.

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

  $tsl = $slm->field_sl_tpref->value();
  echo $tsl->id;
mojzis
источник
1
Он EntityFieldQueryможет ссылаться только на один набор объектов, но, к сожалению, не может создавать отношения с другими объектами. Он также может возвращать только один тип объекта за раз, поэтому даже если вы сможете создать эти отношения, результаты будут ненадежными.
Клайв
@Clive, не могли бы вы добавить это в качестве ответа, чтобы я мог это подтвердить? спасибо :)
Мойзис

Ответы:

15

Вы можете использовать target_idвместо того, valueчтобы извлекать сущности на основе идентификатора ссылочных сущностей:

$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();
Пабло
источник
спасибо, но я не думаю, что это то, что я искал ... я пытался найти другое направление, таким образом, вы бы знали A и искали B :)
mojzis
2

э-э, модуль отношений - это то, что вы ищете? Похоже, определение отношений между сущностями X и Y - это то, что вы хотите сделать. у него есть собственный RelationQuery (обертка вокруг EFQ) и RelationQueryEndpoints, чтобы легко получать такую ​​информацию.

tenken
источник
Спасибо. к сожалению, я уже определил несколько отношений со ссылкой на сущность, поэтому переключение на связь было бы проблематичным ... попробую в следующий раз :).
Мойзис
2

Я знаю, что это более старый вопрос, но для людей, которые обращаются к нему из Google, я решил добавить сюда другой подход.

Из приведенного выше описания установка имеет 2 типа сущностей, A и B. Ссылки B с ссылкой на сущность, которую я предполагаю. Так что, если у вас есть идентификатор B, у вас должно быть поле с идентификатором A, хранящимся в базе данных.

Кодовые примечания:

  • Оригинал NID - $original_node->nidэто будет идентификатор B
  • $typeТип пакета - это должен быть тип A
  • Условие поля просто ищет поле, которое содержит ссылку
  • Для получения дополнительной информации о том, как использовать EFQ см. Это

Код

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

Вы также можете установить двусторонние ссылки на сущности и выполнить тот же запрос в обратном порядке. Вы можете использовать такой модуль, как CER, чтобы обеспечить актуальность этих ссылок. Или настройте правило, чтобы поддерживать ссылку в актуальном состоянии, я использовал оба.

burnsjeremy
источник
Если field_NAME_OF_FIELD является многозначным, будет fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')работать? должен ли он быть изменен на fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN'). Не удалось найти что-либо о том, как применить условие к многозначному полю ссылки на сущность. любое предложение?
Киранкинг
1
Я знаю, что это старый комментарий, но если вы оставите '=' по умолчанию для EntityFieldQuery в IN, то fieldCondition ('field_NAME_OF_FIELD', 'target_id', $ original_node-> nid) будет действительно работать в этой ситуации. Вы, наверное, уже знаете это сейчас, но только если кто-нибудь еще наткнется на это позже :)
burnsjeremy
1

довольно динамичное решение (немного грязное, но оно мне понадобилось быстро), поэтому вам не нужно жестко кодировать имя поля ссылки, и оно автоматически обрабатывается новым полем ссылки, которое вы добавите в будущем:

в вашем пользовательском модуле:

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

где вам нужно получить родительские узлы с учетом дочернего узла:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
Güeno
источник