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

基于日期自动更新ACF字段及关联课时状态的技术求助

问题描述

需求:当当前日期达到或超过文章设定的日期时,自动关闭该文章的True/False类型Advanced Custom Fields(ACF)选项;同时关闭该文章关联课程下课时的Sample Lesson True/False选项。

最初仅使用init钩子调用update_sample_child_lessons函数,但仅在手动点击文章更新按钮时生效。后尝试通过Cron任务实现自动执行,但未能成功运行,附上相关代码寻求可行解决方案。

原代码

//CRON JOB TO RUN EVERYDAY
function myprefix_custom_cron_schedule( $schedules ) {
    $schedules['every_day'] = array(
        'interval' => 86400, //24 HOURS IN SECONDS
        'display'  => __( 'Every 24 hours' ),
    );
    return $schedules;
}
add_filter( 'cron_schedules', 'myprefix_custom_cron_schedule' );

if ( ! wp_next_scheduled( 'myprefix_cron_hook' ) ) {
    wp_schedule_event( time(), 'every_day', 'myprefix_cron_hook' );
}

//AUTOMATICALLY ADJUSTS SAMPLE LESSON FREE OPTIONS AND FREE BANNER IF DATE IS PASSED
add_action( 'myprefix_cron_hook', 'update_sample_child_lessons' );
function update_sample_child_lessons() {
  $allcourses = array(
    'post_type' => 'sfwd-courses', //CUSTOM POST TYPE: COURSES
    'posts_per_page' => -1 //QUERY ALL OF THEM
  );
  $query = new WP_Query($allcourses);

  if ($query->have_posts()) {
    global $post;
    if ( ( in_array( $post->post_type, array( 'sfwd-courses' ), true ) )) { //ONLY DO ACTION IF ON CPT OF COURSES
      while ($query->have_posts()) {
        $query->the_post();
        $course_id = learndash_get_course_id( $post->ID ); //GET THE COURSE ID
        $free = get_field('display_free_lessons', $course_id); //GET THE FREE COURSE OPTION (TRUE/FALSE TICKER)
        if (!empty($free)) { //ONLY DO REST OF CODE IF FREE OPTION IS TURNED ON
          $freeDate = get_field('free_until', $course_id); //GET THE DATE FIELD THAT THE COURSE IS FREE UNTIL
          $currentDate = date('Ymd'); //GET CURRENT DATE
          $diff = strtotime($freeDate) - strtotime($currentDate); //GET THE DIFFERENCE BETWEEN THE TWO DATES
          if ($diff <= 0) { //ONLY DO REST OF CODE IF DATE DIFFERENCE IS LESS THAN OR EQUAL TO ZERO
            $value = '';
            update_field('display_free_lessons', $value, $course_id); //UPDATES THE FREE OPTION FIELD TO FALSE(OR NOTHING)

            //LESSON CODE
            $lessons = array_slice(learndash_course_get_lessons($course_id), 1); //GET ALL THE LESSONS FROM THE COURSE EXCEPT FOR THE FIRST ONE
            foreach ($lessons as $lesson) {
              $lessonID = $lesson->ID; //GET THE LESSON ID
              $lesson_meta = get_post_meta($lessonID); //GET THE METADATA FOR THE LESSON
              if ( is_array( $lesson_meta ) ) {
                foreach ( $lesson_meta as $meta_key => $meta_value ) {
                  if ( '_sfwd-lessons' === $meta_key ) {
                    $lesson_settings = maybe_unserialize( $meta_value[0] ); //SOME OF THE ARRAYS ARE SERIALIZED, SO UNSERIALIZE IF NEEDED
                    if ( isset( $lesson_settings['sfwd-lessons_sample_lesson'] ) ) {
                      $lesson_settings['sfwd-lessons_sample_lesson'] = ''; //TURN OFF THE SAMPLE LESSON OPTION ON THE LESSONS
                    }
                    update_post_meta( $lessonID, $meta_key, $lesson_settings );
                  }
                }
              }
            } //END FOREACH
          } //END IF DIFF IS 0
        wp_reset_postdata();
        } 
      }
    }
  }
}

问题分析

原代码存在几个关键问题导致Cron任务失效或逻辑错误:

  • Cron事件调度时机错误:直接在全局作用域执行wp_schedule_event,可能在WordPress核心初始化完成前触发,导致调度失败
  • 全局$post判断无效:在WP_Query循环外判断$post->post_type,此时$post并非当前循环的课程文章,逻辑无意义
  • wp_reset_postdata()位置错误:放在了if (!empty($free))代码块内,导致循环未完成就重置了查询上下文,后续循环无法正常获取文章数据
  • 日期处理兼容性问题:strtotime($freeDate)若ACF日期字段格式非标准,可能解析失败导致日期判断错误
  • Lesson元数据更新逻辑冗余:无需遍历所有post meta,可直接获取并更新LearnDash的Lesson设置

修复后的完整代码

// 注册每日执行的Cron调度
function myprefix_custom_cron_schedule( $schedules ) {
    $schedules['every_day'] = array(
        'interval' => 86400, // 24小时对应的秒数
        'display'  => __( '每24小时执行一次' ),
    );
    return $schedules;
}
add_filter( 'cron_schedules', 'myprefix_custom_cron_schedule' );

// 在WordPress初始化完成后调度Cron事件
function myprefix_schedule_daily_cron() {
    if ( ! wp_next_scheduled( 'myprefix_cron_hook' ) ) {
        // 设置每天凌晨0点执行,避免随机时间影响
        $midnight = strtotime( 'today midnight' );
        wp_schedule_event( $midnight, 'every_day', 'myprefix_cron_hook' );
    }
}
add_action( 'init', 'myprefix_schedule_daily_cron' );

// 自动处理过期课程的免费选项和Sample Lesson设置
add_action( 'myprefix_cron_hook', 'update_sample_child_lessons' );
function update_sample_child_lessons() {
    // 查询所有课程自定义文章类型
    $allcourses = array(
        'post_type'      => 'sfwd-courses',
        'posts_per_page' => -1,
        'post_status'    => 'publish' // 仅处理已发布的课程
    );
    $query = new WP_Query( $allcourses );

    if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();
            $course_id = get_the_ID(); // 直接获取课程ID,无需额外函数
            
            // 获取ACF的免费显示选项
            $free_enabled = get_field( 'display_free_lessons', $course_id );
            if ( ! $free_enabled ) {
                continue; // 免费选项未开启,跳过当前课程
            }

            // 获取ACF的免费截止日期,统一格式为Ymd
            $free_until_date = get_field( 'free_until', $course_id );
            if ( empty( $free_until_date ) ) {
                continue; // 未设置截止日期,跳过
            }
            
            $current_date = date( 'Ymd' );
            // 转换日期为时间戳进行比较
            $free_until_timestamp = strtotime( $free_until_date );
            $current_timestamp = strtotime( $current_date );

            if ( $free_until_timestamp <= $current_timestamp ) {
                // 关闭课程的免费显示选项
                update_field( 'display_free_lessons', false, $course_id );

                // 获取课程下的所有课时(排除第一个)
                $lessons = array_slice( learndash_course_get_lessons( $course_id ), 1 );
                foreach ( $lessons as $lesson ) {
                    $lesson_id = $lesson->ID;
                    // 直接获取LearnDash的Lesson设置
                    $lesson_settings = get_post_meta( $lesson_id, '_sfwd-lessons', true );
                    if ( is_array( $lesson_settings ) && isset( $lesson_settings['sfwd-lessons_sample_lesson'] ) ) {
                        // 关闭Sample Lesson选项
                        $lesson_settings['sfwd-lessons_sample_lesson'] = false;
                        update_post_meta( $lesson_id, '_sfwd-lessons', $lesson_settings );
                    }
                }
            }
        }
        // 循环结束后重置查询上下文
        wp_reset_postdata();
    }
}

关键修复说明

  • Cron调度时机修正:将Cron事件调度放在init钩子内,确保WordPress完全初始化后再执行,避免调度失败
  • 移除无效判断:删除了循环外的全局$post类型判断,直接通过WP_Query循环处理课程文章
  • 调整重置位置:将wp_reset_postdata()移到循环结束后,保证整个循环的查询上下文正常
  • 日期处理优化:统一日期格式转换逻辑,确保ACF日期字段能正确解析为时间戳,避免比较错误
  • 简化Lesson更新逻辑:直接获取_sfwd-lessons元数据,无需遍历所有post meta,提升执行效率
  • 增加容错处理:添加了对未设置截止日期、免费选项未开启的课程的跳过逻辑,避免无效操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:33:54