Хто є більш ефективним: entit_metadata_wrapper або field_get_items?


10

Отримати значення від сутності, є два способи:

  • Використовуйте field_get_itemsта отримуйте значення поля
  • Використовуйте entity_metadata_wrapperта отримуйте значення поля

Хоча entity_metadata_wrapperабстрагує мовні відмінності, його API іноді все ще незручно, особливо коли використовується PHP 5.3. Наприклад, отримання значення довгого текстового поля зазвичай йде цим маршрутом:

$field = $wrapper->field->value();
print $field['safe_value'];

До щастя, PHP 5.4 підтримує цей синтаксис: print $wrapper->field->value()['safe_value'];.

Але моє питання більше стосується продуктивності. Як вони обидва працюють? Вони запитують базу даних кожен раз, коли вони вимагають значення? Чи entity_metadata_wrapperзапитує все відразу? (Зробити field_get_itemбільш придатним для однозначного пошуку.)

Я не хоробрий, щоб зануритися вглиб Друпальського джерела.


1
field_view_field()призначений для візуалізації поля. Функція отримання значення поля - field_get_items () .
kiamlaluno

І має field_get_items()нульові накладні дані, тому я думаю, що це досить відкритий і закритий випадок :)
Клайв

@Clive як приходить field_get_items()нульові накладні дані? Він повинен десь отримати свої дані, правда?
Флоріан Маргаїн

Крім того, мені дуже цікаво знати, як entity_metadata_wrapperпрацює, наскільки ефективно.
Флоріан Маргаїн

2
Ви передаєте повністю завантажений об'єкт сутності, field_get_items()щоб накладні витрати вже були понесені ... це трохи задушений маршрут у D7, якщо чесно
Клайв

Відповіді:


12

Коротка відповідь: field_get_items () є більш ефективною, ніж entity_metadata_wrapper ().

Перевірте код цих функцій:

Обидва вимагають пройти вздовж сутності, яка вже була завантажена з бази даних . Наприклад:

$node = node_load(123);
$items = field_get_items('node', $node, 'field_my_field_name');
print $items[0]['value'];

або, як ви вже запропонували:

$wrapper = entity_metadata_wrapper('node', $node);
$field = $wrapper->field_my_field_name->value();
print $field['safe_value'];

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

Ви можете просто зробити, print $node->field_my_field_name[LANGUAGE_NONE][0]['value'];але це призведе до помилок повідомлення PHP, якщо поле не має значення, оскільки ви намагаєтеся отримати доступ до масивів, які можуть не існувати (тобто [LANGUAGE_NONE][0]['value']). Останнім часом я часто можу це робити:

if ($field = field_get_items('node', $node, 'field_my_field_name')) {
  print $field[0]['value'];
}

що набагато чистіше, ніж робити:

if (isset($node->field_my_field_name[LANGUAGE_NONE]) && isset($node->field_my_field_name[LANGUAGE_NONE][0])) {
  print $node->field_my_field_name[LANGUAGE_NONE][0]['value'];
}

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

Редагувати: Оскільки field_get_items()запуски field_language(), насправді буде більший показник продуктивності, ніж просто перевірка мови, тому, якщо ви вже знаєте, що існує $ entitet-> мова, ви можете просто написати власну функцію супервиконання:

function my_super_performant_field_value_getter($entity, $field_name) {
  return isset($entity->{$field_name}[{$entity->language}]) ? $entity->{$field_name}[{$entity->language}] : FALSE;
}

Гаразд, окрім цих перевірок, сутність завантажується один раз, незалежно від того, скільки разів я їх використовую? Навіть якщо я використовую посилання на юридичну особу?
Флоріан Маргаїн

Так, це насправді досить класна особливість API сутності в D7. Щойно ви завантажуєте об'єкт, він кешується протягом тривалості цього запиту. Отже, якщо ви робите $node = node_load(123);в одному сценарії і робите це знову в іншому місці, ви не несете накладні витрати на повне завантаження об'єкта та збирання - Drupal просто призначає цій змінній копію існуючої сутності. Якщо ви хочете завантажити нову копію, вам потрібно перейти $reset = TRUEдо функції завантаження сутності. Крім того, дивіться мої зміни стосовно того, хто отримує супер виконавців.
Чарлі Шліссер

1
if (isset($node->field_my_field_name[LANGUAGE_NONE]) && isset($node->field_my_field_name[LANGUAGE_NONE][0])) {не потрібно, isset($node->field_my_field_name[LANGUAGE_NONE][0]достатньо.

@chx Я згоден, але чи не так isset($node->field_my_field_name[LANGUAGE_NONE]), оскільки мова не буде встановлена ​​на порожньому полі? Я думаю, що це дельта / [0]що є зайвим.
Чарлі Шліссер

1
@GilesB, більше запитів до бази даних найчастіше не краще, ніж приєднується. Швидке завантаження - це техніка оптимізації. Але навіть кажучи це, я думаю, що ваше припущення помилкове, і EntityMetadataWrapper, ймовірно, повільніше, але це набагато приємніше використовувати. Це також мікрооптимізація ОП, не потрібно думати при роботі з Drupal.
Микола Рууну
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.