Отримати значення поля, не завантажуючи весь вузол?


11

У мене велика кількість NID, і мені потрібно одне значення поля від кожного вузла. Чи є якийсь спосіб уникнути накладних витрат всього вузла, щоб отримати одне значення поля?

Відповіді:


19

Я не думаю, що в API є щось вбудоване, але ви можете просто запитати базу даних безпосередньо:

$entity_type = 'node';
$bundle = 'page';
$nids = array(1, 2, 3);

$field_values = db_select('field_revision_FIELD_NAME', 'f')
  ->fields('f', array('entity_id', 'FIELD_NAME_value'))
  ->condition('entity_type', $entity_type)
  ->condition('bundle', $bundle)
  ->condition('entity_id', $nids, 'IN')
  ->condition('deleted', 0)
  ->execute()
  ->fetchAllKeyed();

Після запуску у вас повинен бути масив значень поля, введених ключем від відповідного вузла вузла.

Варто пам’ятати назву стовпця не обов’язково буде FIELD_NAME_value; наприклад, опорне поле вузла має ім'я стовпця FIELD_NAME_nid. Який ви будете використовувати, залежатиме від типу поля.

ОНОВЛЕННЯ

Здається, є спосіб зробити це за допомогою API, але це не дуже добре і все ж включає в себе запит вручну:

// Get the field meta data for the field_id.
$field_name = 'field_something';
$field_info = field_info_field($field_name);
$field_id = $field_info['id'];

// Load up the properties from the node table.
$nids = array(1, 2, 3);
$sql = 'SELECT * FROM {node} WHERE nid IN (:nids)';
$nodes = db_query($sql, array(':nids' => $nids))->fetchAllAssoc('nid');

// Attach the single field to all nodes.
field_attach_load('node', $nodes, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

Цей метод використовує перевагу $optionsпараметра в field_attach_load(), вказуючи ідентифікатор поля для завантаження даних. Варто зазначити, за документами:

Зауважте, що повернені об'єкти можуть містити дані для інших полів, наприклад, якщо вони читаються з кеша.

Таким чином, може з'явитися код, що завантажує додаткові дані про поле, але все, крім вказаного вами поля, буде надходити з кешу.


Дивовижно. Працював ідеально і МНОГО швидше, ніж завантаження всього вузла.
Джорен

Я використовував цей підхід із сутністю користувача для завантаження значення одного поля, але цей метод завантажує всі поля (та їх значення), пов'язані з об'єктом користувача. Я щось пропускаю?
WM

Попередження: Перший приклад вимагає зберігання полів у базі даних SQL (за замовчуванням) і не сумісний з альтернативними сховищами полів. Другий повинен працювати (тому що він використовує field_attach_load і він буде працювати з абстракцією сховищ).
Бобік

@Clive, чи є причина, що ти використовував field_revision_FIELD_NAME замість field_data_FIELD_NAME? Чи можете ви поясніть, будь ласка? Дякую.
Сандеш Ядав

3

Я знаходжу трохи більш чистий спосіб, використовуючи навантаження на додаток entіCondition та поле.

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'story')
  ->propertyCondition('status', 1)
  ->fieldCondition('field_story_image', 'fid', 'NULL', '!=');
$result = $query->execute();

if (isset($result['node'])) {
  $stories = $result['node'];

  // At first we need to get field's id. If you already know field id, you can ommit this step
  // Get all fields attached to a given node type
  $fields = field_info_instances('node', 'story');

  // Get id of body field
  $field_id = $fields['field_story_image']['field_id'];

  // Attach a field of selected id only to get value for it
  field_attach_load('node', $stories, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

  // Get values of our node field
  $output = field_get_items('node', $stories, 'field_story_image');
}

З публікації щоденника http://timonweb.com/loading-only-one-field-from-an-entity-or-node


0

Щоб уникнути завантаження вузла один за одним, який має велику кількість NID, ви можете використовувати node_load_multiple()який буде завантажувати кілька вузлів за один раз:

node_load_multiple($nids = array(), $conditions = array(), $reset = FALSE)

Зазвичай завантаження вузлів кешується, і це швидко, якщо ви використовуєте кешування пам’яті (наприклад, запам’ятоване), але це може бути повільно, якщо у вас встановлено занадто багато модулів (наприклад, Pathauto тощо).

Інший спосіб - повторне використання існуючого об'єкта, тому перевірте, чи можете ви завантажити його безпосередньо з кешу (наприклад, через, form_get_cacheякщо це частина форми) або з $_POSTзапиту.

Інший спосіб - використання EntityFieldQueryз декількома NID, наприклад

$query->entityCondition('entity_id', array(17, 21, 422), 'IN')

який отримає значення безпосередньо з бази даних.

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