使用Cron事件调整WooCommerce Bookings提醒邮件发送时间遇异常
问题分析与解决方案
针对你遇到的WooCommerce Bookings提醒调度异常问题,核心原因大概率是插件默认逻辑覆盖自定义设置或代码执行顺序/参数匹配问题,以下是具体排查方向和修复方案:
核心问题排查点
1. 过滤器woocommerce_bookings_remind_before_days被覆盖
你的代码中使用了apply_filters('woocommerce_bookings_remind_before_days', $days_before_reminder_is_sent),这个过滤器可能被插件本身或其他主题/插件修改,导致你从数据库获取的2天被强制改回1天。
验证方式:在代码中添加日志输出,查看过滤后的值:
$filtered_days = absint( apply_filters( 'woocommerce_bookings_remind_before_days', $days_before_reminder_is_sent ) ); error_log('过滤后的提醒天数: ' . $filtered_days);
如果输出是1,说明有其他代码篡改了该值,直接移除过滤器调用即可:
// 替换原过滤代码,直接使用自定义天数 $scheduled_time = $timezone_addition + strtotime( '-' . absint($days_before_reminder_is_sent) . ' day', $event_start );
2. 钩子优先级导致插件默认逻辑后执行
你当前设置的钩子优先级(woocommerce_booking_confirmed为2,woocommerce_booking_paid为1)比插件默认调度逻辑的优先级(通常为10)更高,导致你的代码先执行,随后插件默认代码又重新调度了1天的提醒,覆盖了你的设置。
修复方式:将自定义函数的优先级设为更大的数值(更晚执行):
add_action('woocommerce_booking_confirmed', 'onReservationConfirmed', 20, 2); add_action('woocommerce_booking_paid', 'onReservationConfirmed', 20, 2);
3. Cron事件参数不匹配,无法取消原有事件
插件默认调度的wc-booking-reminder事件,可能使用了和你不同的参数格式(比如同时传入预订ID和对象),导致wp_next_scheduled无法找到原有事件,无法取消。
修复方式:
- 直接移除插件默认的提醒调度逻辑,避免冲突:
add_action('init', function() { // 移除插件默认的提醒调度函数(需确认函数名与插件源码一致) remove_action('woocommerce_booking_confirmed', 'wc_bookings_schedule_reminder', 10); remove_action('woocommerce_booking_paid', 'wc_bookings_schedule_reminder', 10); });
- 循环清理所有该预订的现有事件,确保彻底清除:
$next_event_timestamp = wp_next_scheduled('wc-booking-reminder', array($reservationId)); while ($next_event_timestamp) { error_log('取消现有事件: ' . $next_event_timestamp); wp_unschedule_event($next_event_timestamp, 'wc-booking-reminder', array($reservationId)); $next_event_timestamp = wp_next_scheduled('wc-booking-reminder', array($reservationId)); }
4. 时间计算逻辑验证
添加日志输出时间计算过程,确认提前2天的时间是否正确:
error_log('活动开始时间: ' . date('Y-m-d H:i:s', $event_start)); error_log('时区偏移: ' . $timezone_addition); error_log('计划提醒时间: ' . date('Y-m-d H:i:s', $scheduled_time));
如果时间计算有误,需检查wc_booking_timezone_offset()的返回值是否符合预期(该函数返回的是时区偏移秒数,比如东8区为28800)。
完整修复代码示例
// 移除插件默认的提醒调度逻辑 add_action('init', function() { remove_action('woocommerce_booking_confirmed', 'wc_bookings_schedule_reminder', 10); remove_action('woocommerce_booking_paid', 'wc_bookings_schedule_reminder', 10); }); // 自定义提醒调度函数(晚于插件默认逻辑执行) add_action('woocommerce_booking_confirmed', 'onReservationConfirmed', 20, 2); add_action('woocommerce_booking_paid', 'onReservationConfirmed', 20, 2); function onReservationConfirmed($reservationId, $reservation) { error_log('开始执行自定义提醒调度'); // 从数据库获取自定义提醒天数 $days_before_reminder_is_sent = get_current_reminder_days(); error_log('目标提醒天数: ' . $days_before_reminder_is_sent); // 计算提醒时间 $timezone_addition = -wc_booking_timezone_offset(); $event_start = $reservation->all_day ? strtotime('midnight', $reservation->start) : $reservation->start; $scheduled_time = $timezone_addition + strtotime('-' . absint($days_before_reminder_is_sent) . ' day', $event_start); error_log('活动开始时间: ' . date('Y-m-d H:i:s', $event_start)); error_log('计划提醒时间: ' . date('Y-m-d H:i:s', $scheduled_time)); // 彻底清除该预订的所有现有提醒事件 $next_event_timestamp = wp_next_scheduled('wc-booking-reminder', array($reservationId)); while ($next_event_timestamp) { error_log('取消现有事件: ' . $next_event_timestamp); wp_unschedule_event($next_event_timestamp, 'wc-booking-reminder', array($reservationId)); $next_event_timestamp = wp_next_scheduled('wc-booking-reminder', array($reservationId)); } // 调度新的提醒 wp_schedule_single_event($scheduled_time, 'wc-booking-reminder', array($reservationId)); error_log('自定义提醒调度完成'); }
内容的提问来源于stack exchange,提问作者codonoty
相关产品推荐
相关产品推荐

