I need to set up Woocommerce to automatically clean up old completed orders. Moving to trash would be OK, but I would really prefer to have them deleted. Here’s what I’m using now, but it doesn’t seem to work:
function expire_after_x_days(){
global $wpdb;
// Get current time
$today = date("mdy");
// set time to expire
$time_to_expire = "-180 days";
$expiration_date = date("mdy", strtotime( $today . $time_to_expire));
// Get orders with processing status
$result = $wpdb->get_results("SELECT * FROM $wpdb->posts WHERE post_type = 'shop_order' AND post_status = 'wc-completed'");
if( !empty($result)) foreach ($result as $order){
// Get order's time
$order_time = get_the_time('mdy', $order->ID );
// Compare order's time with current time -10 days
if ( $order_time < $expiration_date ){
// Update order status
wp_delete_post($order_id,true);
}
}
}
// Use the best HOOK for your case
add_action( 'admin_footer', 'expire_after_x_days' );
// OR simply call the function if you are pasting this in your functions.php
What am I doing wrong?
function expire_after_x_days(){
global $wpdb;
// Get current time
$today = date("mdy");
// set time to expire
$time_to_expire = "-180 days";
$expiration_date = date("mdy", strtotime( $today . $time_to_expire));
// Get orders with processing status
$result = $wpdb->get_results("SELECT * FROM $wpdb->posts WHERE post_type = 'shop_order' AND post_status = 'wc-completed'");
if( !empty($result)) foreach ($result as $order){
// Get order's time
$order_time = get_the_time('mdy', $order->ID );
// Compare order's time with current time -10 days
if ( $order_time < $expiration_date ){
// Update order status
wp_delete_post($order_id,true);
}
}
}
// Use the best HOOK for your case
add_action( 'admin_footer', 'expire_after_x_days' );
// OR simply call the function if you are pasting this in your functions.php
What am I doing wrong?
2
Answers
There are several issues with the code you’ve provided:
You’ve duplicated the expire_after_x_days() function. This will cause a fatal error in PHP.
The date format mdy is not an ideal choice for date comparisons. You should use a format that provides a more natural order, such as Ymd.
You are using get_the_time(‘mdy’, $order->ID ) to fetch the date. Instead, you should use get_post_time().
$order_id is not defined. It should be $order->ID.
Hooking this function to admin_footer is not an ideal choice. Every time an admin page is loaded, you’ll be querying and potentially deleting old orders. A scheduled event or a cron job is a better fit.
Using SQL directly can be risky, especially for important tasks. WooCommerce provides a way to query orders that should be preferred over direct SQL whenever possible.
This function makes use of the wc_get_orders() function from WooCommerce to fetch old completed orders. The function is then scheduled to run daily using WP Cron.
Use instead the following that will trash and delete all old completed orders (older than 180 days), by batch of 200 to avoid crashing your website. No need to use any WordPress scheduled actions that are really not reliable.
Here is a simplified and improved code version:
It should work.