Search code examples
phpwordpresstemplateswoocommerceorders

Create a Woocommerce My Account Orders page showing only Completed orders


I deleted a previous question as it was poorly worded on my part. I'm trying to create a Woocommerce My Account Orders page that only shows completed orders. I have tried the following code but all of the orders still show regardless of status.

function woocommerce_orders() {
    $user_id = get_current_user_id();
    if ($user_id == 0) {
        return 
do_shortcode('[woocommerce_my_account]');
    } else {
        $orders = wc_get_orders(array(
            'customer' => $user_id,
            'status'   => 'completed', // You can 
modify the order status as needed
        ));
        $order_count = count($orders);
        ob_start();
        wc_get_template('myaccount/my-orders.php', 
array(
            'current_user' => get_user_by('id', 
$user_id),
            'order_count' => $order_count
        ));
        return ob_get_clean();
    }
}
add_shortcode('woocommerce_orders', 'woocommerce_orders');

Solution

  • Since WooCommerce 3 the template myaccount/my-orders.php is deprecated, no longer used and replaced by myaccount/orders.php.

    The difference between those templates is that the old one use a WP_Query hard-coded in the template itself and the newest one uses a WC_Query (compatible with WooCommerce HPOS).

    As you use myaccount/my-orders.php template (the deprecated one) in your shortcode, you need something different, to target customer completed orders:

    add_shortcode('woocommerce_orders', 'shortcode_my_account_orders');
    function shortcode_my_account_orders() {
        global $current_user;
    
        if ($current_user->ID > 0) {
            ob_start(); // Start buffering
    
            add_filter('woocommerce_my_account_my_orders_query', 'custom_my_account_my_orders_query', 10);
    
            wc_get_template('myaccount/my-orders.php', array(
                'current_user' => $current_user,
            ) );
    
            remove_filter('woocommerce_my_account_my_orders_query', 'custom_my_account_my_orders_query', 10);
    
            return ob_get_clean();
        } else {
            return do_shortcode('[woocommerce_my_account]');
        }
    }
    
    // Filter WP_Query for deprecated my-orders.php template
    function custom_my_account_my_orders_query( $query_args ) {
        // Only completed orders
        $query_args['post_status'] =['wc-completed'];
        
        return $query_args;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.