Search code examples
phpwordpresswoocommercecron

Need help solving a scheduled cron event issue that calls to a specific function on a Wordpress site that uses WooCommerce


I am trying to set up a scheduled cron event through cPanel that will trigger a PHP function in a specific PHP script file on a Wordpress site. For the sake of testing, I want the function to run every minute so it checks the database for new orders within a table with a specific status. If the rows exist, then use another method (Woocommerce) to update the order status to "completed".

The cron job is running without issue but the result--which is to update the status--is not working.

When triggered and tested with shortcode and var_dump(), the called function getPend() works fine and produces the desired change in status to all results without error. However, when run through the cPanel cron scheduler, I get this error:

PHP Fatal error: Uncaught Exception: Invalid order. in /home/path_to/public_html/site_folder/wp-content/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php:104

This is the cron line I have (which runs without error but does not produce the result):

* * * * * /usr/local/bin/php /home/path_to/public_html/site_folder/wp-content/themes/theme-child/pending.php >/dev/null 2>&1

So the cron runs without error and the getPend() function runs without error when I test both of these independently, but when I try to combine them, I get the aforementioned invalid order error.

Here is my script (pending.php):

<?php

getPend(); //call function

function getPend() {

    global $wpdb;

    $getPending = $wpdb->get_results( " SELECT order_id,status
                                        FROM wp_wc_order_stats
                                        WHERE status = 'wc-processing'"
    );

    if (!empty($getPending)) {

        $pending_group = array();
        foreach ($getPending as $pkey => $pitem) {
            $pending_meta = get_object_vars($pitem);
            foreach ($pending_meta as $meta_in => $pendingdetails) {
                $pending_group[$pitem->order_id]['oid'] = $pending_meta['order_id'];
                $pending_group[$pitem->order_id]['stat'] = $pending_meta['status'];
            }

        }
        $o_id = '';
        $o_stat = '';
        foreach($pending_group as $pend) {
            $o_id .= $pend['oid'];
            $o_stat .= $pend['stat'];

             $order = new WC_Order($o_id);
             if (!empty($order)) {
                $order->update_status( 'completed' );
             }
        }
        //var_dump($pending_group); //used with shortcode for testing
    }   
}
//add_shortcode('order-pending','getPend'); //used with var_dump() for testing

//$triedthisdidntwork = getPend();
//return $triedthisdidntwork;

?>

Ultimately, I need the getPend() script to run on a schedule so order statuses can be updated based on whether they exist in the wp_wc_order_stats table. I thought a cron set up through cPanel would be the best way to go about it. But could this issue be solved by setting it up to run as a wordpress scheduled event instead? If so, how could that be done? There is no hook I could use to implicitly trigger the function; it needs to be triggered explicitly...if that makes sense.


Solution

  • Okay...I ended up solving this using the Wordpress scheduler as follows:

    1. Setup a cron schedule on the server to run the WP_Cron every five minutes.

    */5 * * * * /usr/local/bin/php /home/path_to/public_html/site_folder/wp-cron.php >/dev/null 2>&1

    1. Add custom schedule to functions.php for Wordpress Cron:
        $schedules['every_five_minutes'] =   array(
                                                'interval' => 5 * MINUTE_IN_SECONDS, 
                                                'display' => __('Every 5 Minutes')
                                            );
        return $schedules;
    }
    add_filter( 'cron_schedules', 'addfive_cron_schedule' );
    
    1. Renamed getPend() to pendord_getPend() and created a custom hook in Wordpress functions.php:
    add_action( 'pendord_cronhook', 'pendord_getPend' );
    if (!wp_next_scheduled('pendord_cronhook')) {
        wp_schedule_event(time(), 'every_five_minutes', 'pendord_cronhook');
    }
    

    WP_Cron will run the pendord_getPend function every five minutes, and the server cron scheduler will run WP_Cron every five minutes.