xandeadx.ru Блог музицирующего веб-девелопера

Drupal → Программное изменение значения поля без вызова entity_save()

Пример программного изменения значения поля field_category у материала типа article:

Способ 1

$node = node_load(123);
$node->original = $node;
$node->field_category['und'][0]['tid'] = 456;
foreach (field_info_instances('node', 'article') as $field_name => $field_info) {
  // Удаляем все поля кроме field_category
  if ($field_name != 'field_category') {
    unset($node->{$field_name});
  }
}
field_attach_presave('node', $node);
field_attach_update('node', $node);

Замечание: способ обнуляет значения полей типа File или Image. Обойти баг можно не удаляя из $node эти поля.

По материалам Saving node's fields without saving the node itself.

Способ 2

$node = node_load(123);
$node->field_category['und'][0]['tid'] = 456;
$field_info = field_info_field('field_category');
field_sql_storage_field_storage_write('node', $node, 'update', array($field_info['id']));
cache_clear_all("field:node:{$node->nid}", 'cache_field');

Замечание: при таком способе не вызывается никаких хуков из Field API, т.е. обновлённое поле не будет проиндексировано и т.п.

По тестам, обновление поля у 2000 нод занимает около 7 секунд с учётом node_load(). Если отказаться от node_load(), то тот же тест будет выполняться уже за 4 секунды:

$node = (object)array(
  'nid' => 123,
  'vid' => 123,
  'type' => 'article',
);
$node->field_category['und'][0]['tid'] = 456;
$field_info = field_info_field('field_category');
field_sql_storage_field_storage_write('node', $node, 'update', array($field_info['id']));
cache_clear_all("field:node:{$node->nid}", 'cache_field');

По материалам How To Insert and Update Only Specific Fields Of Your Entity In Drupal 7.

Написанное актуально для Drupal 7
Похожие записи

Комментарии RSS

Если hook_entity_update не вызывается при таком трюке, то я бы воздержался от его использования.

Кстати, может через field_update_field будет проще?

field_update_field для другого

Чёрт, лоханулся )

ерунда) если найдёшь более красивый рабочий способ, буду только рад ;)

Есть ещё варианты с field_sql_storage_*:
1. http://timonweb.com/how-insert-and-update-only-specific-fields-your-enti...
2. http://greenash.net.au/thoughts/2012/11/batch-updating-drupal-7-field-data/
3. не нашла ссылку :(

kalabro, спасибо, потестирую

еще есть некоторое кол-во оберток у ctools, которые используются в fape
полагаю, что лучше копать в их сторону так как именно они взяты командой spark для edit

Это: $node->original = $node; - точно нужно?
У меня сущность через ECK сделана и работает без этого?!

можно без этого

А так можно загрузить только одно поле (взято здесь)

$query = new EntityFieldQuery();
 $query->entityCondition('entity_type', 'node')
   ->entityCondition('bundle', 'article')
   ->propertyCondition('status', 1)
   ->fieldCondition('field_image', 'fid', 'NULL', '!=');
 $results = $query->execute();
 $articles = $results['node'];
 $fields = field_info_instances('node', 'article');
 $field_id = $fields['field_image']['field_id'];
 field_attach_load('node', $articles, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

Правда, у меня цепляются все поля. Не пойму, как сделать, чтобы было только одно. $field_id вроде бы указан :/

Когда использовал ваш метод при создании rules components для использования через Views BO, то поля не обновлялись. Cработал только node_save(). Интересно почему?

Добрый день!
Существует ли способ изменения entity properties без вызова функции сохранения entity?

нет

А почему field_update_field не подходит?
http://drupal.stackexchange.com/questions/64833/fast-saving-single-field...

Спасибо, способ 2 очень помогло.
Кстати, там кэш не правильно чистится, должно быть
cache_clear_all("field:node:{$node->nid}", 'cache_field');

Все бы хорошо, да только при изменении поля, Rules абсолютно не реагирует на событие "После обновления существующего материала"

Поддерживаю, как сделать чтобы рулсы срабатывали при изменении полей программно?

Для 8-го будет решение?)

Оставить комментарий

Содержимое этого поля является приватным и не будет отображаться публично. Если у вас есть аккаунт в Gravatar, привязанный к этому e-mail адресу, то он будет использован для отображения аватара.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступные HTML теги: <a> <i> <b> <strong> <code> <ul> <ol> <li> <blockquote> <em> <s>
  • Строки и параграфы переносятся автоматически.
  • Подсветка кода осуществляется с помощью тегов: <code>, <css>, <html>, <ini>, <javascript>, <sql>, <php>. Поддерживаемые стили выделения кода: <foo>, [foo].

Подробнее о форматировании