You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Gravity Form动态创建字段保存至表单提交条目

问题说明
  • 基础场景:通过gform_pre_render_5、gform_pre_validation_5钩子为ID为5的Gravity Form动态添加选择字段,提交后动态字段值可以正常出现在通知邮件中,但不会被保存到表单entries(条目)数据中,仅后台手动创建的字段会被存入条目,需要实现动态字段值同步写入条目。
  • 扩展场景:单动态字段的存值方案可正常运行,但改为循环批量生成葡萄酒选择字段后方案失效,需要排查问题原因。

基础场景实现代码

add_filter('gform_pre_render_5', 'populate_wines');
add_filter('gform_pre_validation_5', 'populate_wines');

function populate_wines($form) {
    
    // 创建动态选择字段
    $props = array(
        'id'        => 51,
        'type'      => 'select',
        'label'     => 'Dynamic field label',
        'choices'   => array(
            array(
               'text'       => '',
               'value'      => '',
             ),
             array(
               'text'       => '1',
               'value'      => '1',
             ),
             array(
               'text'       => '2',
               'value'      => '2',
             ),
             array(
               'text'       => '3',
               'value'      => '3',
             ),
        )
    );
    $new_field = GF_Fields::create( $props );
    $form['fields'][] = $new_field;
    
    return $form;
}

循环批量生成字段的失效代码

function populate_wines($form) {
    
    // 选择项配置
    $select_choices = array(
            array(
               'text'       => '',
               'value'      => '',
             ),
             array(
               'text'       => '1',
               'value'      => '1',
             ),
             array(
               'text'       => '2',
               'value'      => '2',
             ),
             array(
               'text'       => '3',
               'value'      => '3',
             ),
        );
    
    
    // 循环生成葡萄酒选择字段
    if( have_rows('wine_options') ):
        $wine_count = 50;
        while( have_rows('wine_options') ) : the_row();
            $wine_ID = get_sub_field('wine_option');
            $wine_name = get_the_title($wine_ID);
    
                // 创建单个葡萄酒选择字段
                $props = array(
                    'id'        => $wine_count,
                    'type'      => 'select',
                    'label'     => $wine_name,
                    'choices'   => $select_choices
                );
                $new_field = GF_Fields::create( $props );
                $form['fields'][] = $new_field;
    
            $wine_count++;
        endwhile;
    endif;
    
    if ( GFForms::get_page() !== 'form_editor' ) {
        return $form;
    }
}
问题原因与解决方法

动态字段不存入条目的核心原因

仅挂载gform_pre_render、gform_pre_validation两个钩子只能覆盖前端渲染、提交校验两个流程,Gravity Forms在提交入库、后台加载条目结构时,无法识别到动态添加的字段,自然不会把对应值写入条目表。

单字段场景修复方式

需要把动态注入字段的逻辑同时挂载到以下4个钩子,覆盖表单全生命周期的结构加载节点:

  • gform_pre_render_{$form_id}:前端表单渲染
  • gform_pre_validation_{$form_id}:提交前校验
  • gform_pre_submission_{$form_id}:提交入库前字段识别
  • gform_admin_pre_render_{$form_id}:后台条目列表、详情页加载字段结构

GF识别到字段存在后,会自动把提交值写入条目表,不需要额外编写入库逻辑。


循环生成字段失效的排查与修复

循环版本失效是3个代码逻辑错误导致的,按优先级修复即可:

  1. Return逻辑完全写反
    原代码在所有字段生成完成后,仅当上下文不是表单编辑器时才返回$form,如果是表单编辑器页面、或者提交流程的其他上下文,函数没有返回值,会直接导致表单结构丢失。
    正确写法是把动态生成字段的逻辑包裹在「非表单编辑器」的判断中,函数末尾无条件返回$form。

  2. ACF字段取值上下文缺失
    前端渲染页面时存在全局$post对象,have_rows('wine_options')可以正常取到值,但表单提交走的是admin-post.php/admin-ajax.php接口,没有全局文章上下文,have_rows会直接返回false,根本不会生成任何动态字段。
    修复方式是给have_rows传入第二个参数,明确指定wine_options字段所属的对象ID,如果是选项页存的配置就传'option',如果是固定页面存的配置就传对应页面ID。

  3. 字段ID冲突风险
    循环起始ID设为50,需要先确认表单内手动创建的字段ID没有占用50及之后的号段,建议把起始ID设为比现有字段最大ID大10以上的数值,避免同ID字段被覆盖导致值无法匹配。

修复后可正常运行的循环代码示例

// 挂载全流程钩子
add_filter('gform_pre_render_5', 'populate_wines');
add_filter('gform_pre_validation_5', 'populate_wines');
add_filter('gform_pre_submission_5', 'populate_wines');
add_filter('gform_admin_pre_render_5', 'populate_wines');

function populate_wines($form) {
    // 表单编辑器页面不注入动态字段,避免破坏原有表单结构
    if ( GFForms::get_page() === 'form_editor' ) {
        return $form;
    }

    // 选择项配置
    $select_choices = array(
        array(
            'text'  => '',
            'value' => '',
        ),
        array(
            'text'  => '1',
            'value' => '1',
        ),
        array(
            'text'  => '2',
            'value' => '2',
        ),
        array(
            'text'  => '3',
            'value' => '3',
        ),
    );

    // 替换为你的wine_options所属对象ID,选项页填'option',固定页面填对应页面ID
    $acf_source_id = 'option';
    $wine_count = 100; // 起始ID设为100,避开原有字段ID段

    // 循环生成字段,明确传入ACF数据源ID
    if( have_rows('wine_options', $acf_source_id) ):
        while( have_rows('wine_options', $acf_source_id) ) : the_row();
            $wine_ID = get_sub_field('wine_option');
            $wine_name = get_the_title($wine_ID);

            $props = array(
                'id'        => $wine_count,
                'type'      => 'select',
                'label'     => $wine_name,
                'choices'   => $select_choices
            );
            $new_field = GF_Fields::create( $props );
            $form['fields'][] = $new_field;

            $wine_count++;
        endwhile;
    endif;

    // 始终返回表单结构
    return $form;
}

内容的提问来源于stack exchange,提问作者deeve007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 22:24:18