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 абсолютно не реагирует на событие "После обновления существующего материала"

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

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

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

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