GravityView 如何显示另一表单的 payment status
结论
不要使用 gform_entry_id_pre_save_lead。这个钩子用于在提交表单时指定或替换即将保存的 Entry ID,无法让 GravityView 在渲染 Form A 时读取 Form B 的条目。使用不当还可能覆盖已有条目。
可以按下面的方式处理:
- 根据当前登录用户的 ID 查询 Form B;
- 检查该用户是否有支付成功的 Entry;
- 将查询结果封装成 shortcode;
- 在 GravityView 的 Custom Content 字段中调用这个 shortcode。
实现代码
将以下代码添加到子主题的 functions.php 或自定义功能插件中,并把 $payment_form_id 改为 Form B 的实际表单 ID。
<?php
add_shortcode( 'form_b_payment_status', 'my_form_b_payment_status_shortcode' );
function my_form_b_payment_status_shortcode( $atts ) {
$atts = shortcode_atts(
array(
'form_id' => 2,
'paid_text' => '已付款',
'unpaid_text' => '未付款',
),
$atts,
'form_b_payment_status'
);
if ( ! is_user_logged_in() || ! class_exists( 'GFAPI' ) ) {
return esc_html( $atts['unpaid_text'] );
}
$user_id = get_current_user_id();
$payment_form_id = absint( $atts['form_id'] );
if ( ! $payment_form_id ) {
return esc_html( $atts['unpaid_text'] );
}
/*
* 同一个页面中的 GravityView 可能渲染多行。
* 使用静态缓存,避免每一行都重复查询 Form B。
*/
static $payment_cache = array();
$cache_key = $payment_form_id . ':' . $user_id;
if ( isset( $payment_cache[ $cache_key ] ) ) {
return $payment_cache[ $cache_key ];
}
$search_criteria = array(
'status' => 'active',
'field_filters' => array(
'mode' => 'all',
array(
'key' => 'created_by',
'value' => $user_id,
),
array(
'key' => 'payment_status',
'value' => 'Paid',
),
),
);
$sorting = array(
'key' => 'date_created',
'direction' => 'DESC',
'is_numeric' => false,
);
$paging = array(
'offset' => 0,
'page_size' => 1,
);
$total_count = 0;
$entries = GFAPI::get_entries(
$payment_form_id,
$search_criteria,
$sorting,
$paging,
$total_count
);
$is_paid = ! is_wp_error( $entries ) && ! empty( $entries );
$payment_cache[ $cache_key ] = esc_html(
$is_paid ? $atts['paid_text'] : $atts['unpaid_text']
);
return $payment_cache[ $cache_key ];
}
然后在 GravityView 的 Custom Content 字段中填写:
[form_b_payment_status form_id="2"]
显示文字也可以自定义:
[form_b_payment_status form_id="2" paid_text="付款已完成" unpaid_text="尚未付款"]
为什么不能直接使用 {payment_status}
当前 View 的数据源是 Form A,所以 Custom Content 中的 Gravity Forms merge tag 默认以当前 Form A Entry 为上下文。
{payment_status} 表示当前 Entry 的支付状态。它不会自动切换到 Form B,也不会查找当前用户在 Form B 中的 Entry,更无法判断多条 Form B Entry 中哪一条代表有效付款。
因此,需要先确定 Form A 和 Form B 之间的关联条件。这里使用 Gravity Forms Entry 的 created_by 属性,也就是当前登录用户的 WordPress 用户 ID。
支付状态需要确认
示例把以下条件视为支付成功:
'payment_status' => 'Paid'
Paid 是 Gravity Forms 支付 Entry 中常见的成功状态,但实际值可能受到支付插件、支付流程和历史数据的影响。使用前应先检查 Form B 中的实际 Entry 数据。
如果实际的成功状态不是 Paid,请将代码中的值改为对应状态。不要根据前端显示的文字来猜测,因为数据库中的 payment_status 通常使用英文状态值。
如果需要显示 Form B 的原始状态
如果要显示最近一条 Form B Entry 的实际 payment_status,而不是简单显示“已付款”或“未付款”,可以只按 created_by 查询,然后读取:
$payment_status = rgar( $entries[0], 'payment_status' );
这种做法还需要明确一条业务规则:如果最近一次支付失败,是否要覆盖用户此前成功付款的记录。若要判断“用户是否曾经完成付款”,直接查询 payment_status = Paid 通常更符合要求。
注意事项
- 用户必须登录。匿名提交的 Entry 通常没有可靠的
created_by,此时应通过订单号、邮箱或自定义关联字段连接两个表单。 - 邮箱不适合作为唯一关联键,因为用户可能修改邮箱,也可能出现大小写或格式差异。
- 支付状态可能由支付网关的 webhook 异步更新,因此提交 Form B 后,页面不一定会立即显示为已付款。
- 如果 View 要显示每一行所属用户的付款状态,而不是当前登录用户的付款状态,就不能使用
get_current_user_id()。此时应从当前 Form A Entry 中读取对应的用户 ID,再查询 Form B。 - 只有需要保存付款时的历史快照,或者需要按付款状态排序、筛选时,才建议把状态同步到 Form A。如果只是展示状态,动态查询 Form B 可以避免两份数据不一致。
备注:内容仅供参考。
