Drupal7 无需保存节点使用field_attach_update批量更新字段方案
Drupal批量字段更新实现方案
一、可复用批量更新函数
你可以把以下代码放到自定义模块的.module文件中,或者单独存为.php文件放在Drupal根目录供drush调用:
/** * 批量更新节点指定字段值 * @param array $nids 待更新的节点ID数组 * @param string $field_name 要修改的字段机器名 * @param mixed $field_value 要设置的字段值 * @param int $batch_size 每批处理的节点数量,默认50个 */ function custom_batch_update_node_field($nids, $field_name, $field_value, $batch_size = 50) { // 把nid数组分批,避免一次性加载过多节点占满内存 $batches = array_chunk($nids, $batch_size); foreach ($batches as $batch_nids) { // 批量加载当前批次的节点,比单次循环node_load性能高 $nodes = node_load_multiple($batch_nids); foreach ($nodes as $node) { // 仅修改指定字段值,不改动其他节点属性 if (isset($node->{$field_name}[LANGUAGE_NONE][0])) { $node->{$field_name}[LANGUAGE_NONE][0]['value'] = $field_value; // 仅更新字段,跳过节点其他属性的写入和钩子触发,性能更高 field_attach_update('node', $node); } } // 清理当前批次的节点缓存,释放内存,避免2万条数据导致内存溢出 entity_get_controller('node')->resetCache($batch_nids); // 如果服务器性能极低,可以取消下方注释添加毫秒级延时,一般场景不需要 // usleep(50000); // 延时50毫秒 } }
二、通过Drush运行的方法
方法1:直接写drush运行脚本
在Drupal根目录新建batch_update_field.php,内容如下:
<?php // 引导Drupal内核 define('DRUPAL_ROOT', getcwd()); require_once DRUPAL_ROOT . '/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // 这里替换成你自己的待更新nid数组 $target_nids = [123,124,/* 你的2万个nid */]; // 替换成实际要修改的字段名和值 custom_batch_update_node_field($target_nids, 'field_fieldname', '要设置的目标值'); echo "更新完成";
然后在命令行进入Drupal根目录执行:drush php-script batch_update_field.php
方法2:封装为自定义drush命令(适合长期复用)
如果需要频繁使用该功能,可以把函数封装成drush命令,在自定义模块下新建modulename.drush.inc添加命令声明即可,调用时直接执行drush your-custom-command即可。
三、注意事项
- 正常场景不需要添加计时器,只要做好分批处理和内存释放即可,2万条节点默认每批50个的情况下不会造成服务器负载过高
- 如果你的字段是多值字段,或者需要处理多语言,把
LANGUAGE_NONE和[0]的下标逻辑修改为对应场景即可 field_attach_update不会触发节点的hook_node_presave、hook_node_update等钩子,如果你的业务依赖这些钩子,可以把field_attach_update替换为node_save($node),性能会稍低但功能更完整
内容的提问来源于stack exchange,提问作者pesaw
相关产品推荐
相关产品推荐

