Планировщик WordPress Cron запускает функцию несколько раз подряд

#wordpress #cron #wordpress-plugin-creation

#wordpress #хрон #wordpress-создание плагина

Вопрос:

У меня есть плагин, который позволяет пользователю устанавливать дату, чтобы запланировать отправку набора электронных писем. Когда они сохраняют настройки, создается запланированная задача, настроенная на еженедельный запуск. Кажется, все работает так, как и ожидалось. Я могу просмотреть запланированное задание для запуска с помощью плагина WP Crontrol.

Проблема в том, что как только начинается обратный отсчет, кажется, что функция запускается примерно 8 раз или около того, а не только один раз, поэтому она отправляет 15 электронных писем (по одному для каждого местоположения) x 8.

Я пытаюсь понять, правильно ли я все настроил. Я могу опубликовать свою конструкцию и метод, который она вызывает.

suddath_send_reviews это крючок

 public function __construct( $plugin_name, $version ) {
    
    $this->plugin_name = $plugin_name;
    $this->version     = $version;
    
    // Actions
    add_action( 'init', [ $this, 'create_reviews_location_taxonomy' ], 0 );
    add_action( 'admin_menu', [ $this, 'create_admin_menu_item' ] );
    add_action( 'admin_init', [ $this, 'update_general_settings' ] );
    // add_action( 'admin_menu', [ $this, 'add_tax_to_reviews' ] );
    add_action( 'site-reviews/review/created', [ $this, 'add_location_to_submitted_review' ], 10, 2 );
    add_action( 'wp_ajax_send_email_data', [ $this, 'get_reviews_one_location' ] );
    add_action( 'wp_ajax_nopriv_send_email_data', [ $this, 'get_reviews_one_location' ] );
    add_action( 'wp_ajax_send_all_email_data', [ $this, 'get_reviews_all_locations' ] );
    add_action( 'wp_ajax_nopriv_send_all_email_data', [ $this, 'get_reviews_all_locations' ] );
    add_action( 'admin_notices', [ $this, 'rr_updated_admin_notice' ]);
    add_action( 'acf/init', [ $this, 'rr_acf_add_local_field_groups' ]);
    
    // Filters
    add_filter( 'cron_schedules', [ $this, 'add_weekly_cron_schedule' ] );
    
    // get day/time options
    $day   = get_option( 'send_review_day' );
    $time  = get_option( 'send_review_time' );
    $am_pm = get_option( 'send_review_nightday' );
    
    wp_unschedule_hook( 'suddath_send_reviews' );
    
    // run scheduler based on options selected on plugin admin page
    // If it hasnt already been scheduled 
    if (
        !empty( $day ) amp;amp;
        !empty( $time ) amp;amp;
        !empty( $am_pm )
        ):
        $hour = explode( ':', $time )[0];
        if ( $am_pm === 'pm' ):
            $hour  = 12;
            $time = "$hour:00:00";
        endif;
        
        // Add 5 hours  because cron defaults to UTC -5
        if ( ! wp_next_scheduled( 'suddath_send_reviews' ) ):
            
            wp_schedule_event(
                strtotime( "this $day $time  5 hours" ),
                get_option( 'send_review_frequency' ),
                'suddath_send_reviews'
            );
            // else:
                //  wp_unschedule_hook( 'suddath_send_reviews' );
                //  wp_schedule_event(
                    //      strtotime( "this $day $time  5 hours" ),
                    //      get_option( 'send_review_frequency' ),
                    //      'suddath_send_reviews'
                    //  );
        endif;
        add_action( 'suddath_send_reviews', [ $this, 'get_reviews_all_locations' ] );
    endif;
}

public function get_reviews_all_locations(){
    $locations   = $this->get_review_locations_list();
    
    foreach( $locations as $location ):
        $assigned_to = get_field( 'location_id', $location );
        
        if( $assigned_to ):
            $args             = $this->get_review_args( $assigned_to );
            $location_reviews = $this->get_location_reviews( $args );
        endif;
        
        $this->create_html_template( $location, $location_reviews );
        $pdf_location = plugin_dir_path( __DIR__ ) . 'admin/partials/pdf.html';
        $this->generate_market_pdf( $pdf_location, $location->slug, $location->name );
    endforeach;
}
 

Ответ №1:

Существует множество возможностей для такой проблемы.

Попробуйте проверить, есть ли какое-либо событие расписания, привязанное к вашей функции, или нет. Это произойдет, если мы изменим время события для тестирования и забудем отменить расписание события.

Во-вторых, вполне возможно, что ваш хук выполняется более одного раза. Вы можете предотвратить выполнение hook более одного раза при использовании вашего конкретного кода did_action .

 if( did_action(suddath_send_reviews) < 1){ //Whenver this hook trigger, execute only once
    add_action( 'suddath_send_reviews', [ $this, 'get_reviews_all_locations' ] );
}