Створіть EntityFieldQuery, який вибирає посилання на них


10

Я шукаю ідентифікатор об'єкта типу A і знаю ідентифікатор об'єкта B, який посилається на А.

Я знайшов кілька приємних джерел про 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;

1
EntityFieldQueryМоже посилатися тільки один набір сутностей, вона не може створити відносини до інших осіб на жаль. Він також може одночасно повертати лише один тип сутності, навіть якщо ви могли б створити ці відносини, результати були б ненадійними.
Клайв

@Clive Ви б заперечили, додавши це як відповідь, щоб я міг це підтвердити? дякую :)
mojzis

Відповіді:


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, щоб легко отримати подібну інформацію.


Дякую. на жаль, я вже визначив декілька відносин з посиланням на сутність, тому перехід на відносини було б проблематичним ... спробую наступного разу :).
mojzis

2

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

З наведеного вище опису у програмі встановлено два типи сутності, A і B. B посилання A з посиланням на сутність я припускаю. Отже, якщо у вас є ідентифікатор B, у вас повинно бути поле з ідентифікатором A, що зберігається в базі даних.

Примітки до коду:

  • Оригінальний NID - $original_node->nidце ідентифікатор B
  • Тип пачки - $typeце має бути тип А
  • Умова поля просто шукає поле, яке містить посилання
  • Для отримання додаткової інформації про використання 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, щоб забезпечити оновлення цих посилань. Або встановіть правило, щоб оновити посилання актуально, я використовував і те, і інше.


Якщо поле_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'). Не вдалося знайти нічого про те, як застосувати умову в полі багатозначного об'єкту. будь-яка пропозиція?
kiranking

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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.