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

WordPress中The Events Calendar邮件门票过滤函数未生效问题

问题描述

我在使用WordPress的The Events Calendar(搭配Event Tickets Plus插件)时遇到问题:WooCommerce订单完成后会自动向客户发送包含门票的邮件,但我需要条件性排除特定门票(这类门票需在现场入口领取,无需发送邮件)。

我尝试通过挂钩tribe_tickets_ticket_email_recipient过滤器实现逻辑,在自定义函数中修改$tickets数组以移除指定门票。通过var_dump确认$tickets数组已按预期修改,但邮件仍包含所有门票,修改似乎未生效。

我的自定义代码如下:

add_filter( 'tribe_tickets_ticket_email_recipient', 'disable_specific_ticket_email', 1, 6 );

function disable_specific_ticket_email( $to, $post_id, $order_id, &$tickets, $provider, $args ) {
    
    // Dump initial state of $tickets
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/initial_var_dump.txt', var_export($tickets, true));
    
    $excluded_tickets = [];

    foreach ( $tickets as $key => $ticket ) {
        if (isset($ticket['event_id']) && isset($ticket['product_id'])) {
            $event_id = $ticket['event_id'];
            $product_id = $ticket['product_id'];

            // Check if this ticket should be excluded from the email
            if (
                ($event_id == 69629 && $product_id == 69632) ||
                ($event_id == 69641 && $product_id == 69644) ||
                ($event_id == 69651 && $product_id == 69660) ||
                ($event_id == 69833 && $product_id == 69842) ||
                ($event_id == 69801 && $product_id == 69816) ||
                ($event_id == 69994 && $product_id == 69997) ||
                ($event_id == 70006 && $product_id == 70008) ||
                ($event_id == 69744 && $product_id == 69753) ||
                ($event_id == 69755 && $product_id == 69758) ||
                ($event_id == 69765 && $product_id == 69770) ||
                
                ($event_id == 69675 && ($product_id == 69686 || $product_id == 69687))
            ) {
                $excluded_tickets[] = $key;
            }
        }
    }

    // Remove excluded tickets from the original $tickets array
    foreach ($excluded_tickets as $key) {
        unset($tickets[$key]);
    }
    

    // Dump final state of $tickets
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/final_var_dump.txt', var_export($tickets, true));
    
    // If there are still tickets left, send the email
    if (count($tickets) > 0) {
        return $to;
    }

    // If no tickets are left, disable the email
    return '';
}

我已经尝试的操作:

  • 通过var_dump确认$tickets数组已按预期移除目标门票
  • 调整add_filter的优先级(从1到更高数值),但无效果

核心疑问

  1. 为什么$tickets数组修改正确,但邮件仍发送全部门票?
  2. 应该在哪个钩子/位置应用此逻辑,才能让发送的邮件反映修改后的$tickets数组?

注:我使用的是旧版邮件系统,未启用新版系统;该问题也在The Event Calendar官网相关页面讨论过。


问题解答

1. 为什么修改$tickets数组后邮件仍包含全部门票?

tribe_tickets_ticket_email_recipient过滤器的核心作用是修改邮件收件人,而非直接控制邮件中展示的门票内容。虽然你通过引用传递修改了$tickets数组,但插件在后续生成邮件内容时,会重新从订单原始数据中读取门票信息,而非复用你修改后的这个数组。

简单来说:这个钩子的设计目的不是用来过滤邮件内的门票列表,你修改的数组没有被后续邮件渲染逻辑调用。

2. 正确的实现方案(针对旧版邮件系统)

针对旧版邮件系统,官方提供了专门用于过滤邮件门票列表的钩子:tribe_tickets_ticket_email_tickets。这个钩子的作用就是直接修改要在邮件中展示的门票数组,是处理这类需求的标准方式。

替换后的代码示例:

add_filter( 'tribe_tickets_ticket_email_tickets', 'filter_tickets_in_email', 10, 3 );

function filter_tickets_in_email( $tickets, $order_id, $args ) {
    $excluded_tickets = [];

    foreach ( $tickets as $key => $ticket ) {
        if (isset($ticket['event_id']) && isset($ticket['product_id'])) {
            $event_id = $ticket['event_id'];
            $product_id = $ticket['product_id'];

            // 保留原有排除条件
            if (
                ($event_id == 69629 && $product_id == 69632) ||
                ($event_id == 69641 && $product_id == 69644) ||
                ($event_id == 69651 && $product_id == 69660) ||
                ($event_id == 69833 && $product_id == 69842) ||
                ($event_id == 69801 && $product_id == 69816) ||
                ($event_id == 69994 && $product_id == 69997) ||
                ($event_id == 70006 && $product_id == 70008) ||
                ($event_id == 69744 && $product_id == 69753) ||
                ($event_id == 69755 && $product_id == 69758) ||
                ($event_id == 69765 && $product_id == 69770) ||
                ($event_id == 69675 && ($product_id == 69686 || $product_id == 69687))
            ) {
                $excluded_tickets[] = $key;
            }
        }
    }

    // 移除排除的门票
    foreach ($excluded_tickets as $key) {
        unset($tickets[$key]);
    }

    // 返回修改后的门票数组
    return $tickets;
}

// 补充:无门票时取消邮件发送
add_filter( 'tribe_tickets_ticket_email_recipient', 'disable_email_when_no_tickets', 10, 6 );

function disable_email_when_no_tickets( $to, $post_id, $order_id, $tickets, $provider, $args ) {
    // 此处$tickets已被上面的过滤器修改
    if ( empty($tickets) ) {
        return ''; // 无门票时不发送邮件
    }
    return $to;
}

代码说明:

  • tribe_tickets_ticket_email_tickets钩子直接接收并返回要在邮件中展示的门票数组,修改后的数据会被邮件渲染逻辑直接使用,这是官方推荐的过滤邮件门票列表的方式。
  • 保留tribe_tickets_ticket_email_recipient的逻辑是为了确保当所有门票都被排除时,直接取消邮件发送,避免发送空邮件给用户。

额外验证建议

  • 可以在filter_tickets_in_email函数中加入日志记录,确认修改后的$tickets数组是否正确传递到邮件渲染环节。
  • 钩子优先级保持默认的10即可,不需要设为1,避免过早执行导致数据未完全加载。

内容的提问来源于stack exchange,提问作者David O'Malley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:42:03