Search code examples
phpwordpresswoocommercehook-woocommerceorders

Automatically add custom order shipping item meta data in WooCommerce


I know how to add a meta on the order shipping method :

$shippingMethodItem->update_meta_data('num_packages', 0);

But I want to add/update this meta automatically when the order is placed OR when someone add/edit order items manually.

I already tried with no result :

add_action( 'woocommerce_checkout_create_order_shipping_item', [$this, 'actionCheckoutCreateOrderShippingItem'] );

...

public function actionCheckoutCreateOrderShippingItem ($shippingMethodItem, $package_key, $package, $order)
{
    $shippingMethodItem->update_meta_data( 'num_packages', 0);
    $shippingMethodItem->save();
}

Solution

  • The following will add custom specific order "shipping" item meta data on orders via checkout and/or manual admin orders too:

    // For new orders via checkout
    add_action( 'woocommerce_checkout_create_order_shipping_item', 'action_checkout_create_order_shipping_item', 10, 4 );
    function action_checkout_create_order_shipping_item ( $item, $package_key, $package, $order ){
        $item->update_meta_data( 'num_packages', 0 );
    }
    
    // For manual admin orders
    add_action( 'woocommerce_saved_order_items', 'action_saved_order_items_callback', 10, 2 );
    function action_saved_order_items_callback( $order_id, $items ) {
        if ( isset( $items['shipping_method_id'] ) ) {
            foreach( $items['shipping_method_id'] as $item_id ) {
                $num_packages = wc_get_order_item_meta($item_id, 'num_packages');
    
                if ( empty($num_packages) || $num_packages != 0 ) {
                    wc_update_order_item_meta( $item_id, 'num_packages', 0 );
                }
            }
        }
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.


    To use this code in a plugin with a class (OOP), add the following inside the constructor function:

    // For checkout order
    add_action( 'woocommerce_checkout_create_order_shipping_item', [$this, 'action_checkout_create_order_shipping_item'], 10, 4 );
    // For checkout order
    add_action( 'woocommerce_saved_order_items', [$this, 'action_saved_order_items_callback'], 10, 2 );
    

    And the following outside the constructor function:

    public function action_checkout_create_order_shipping_item ( $item, $package_key, $package, $order ){
        $item->update_meta_data( 'num_packages', 0 );
    }
    
    public function action_saved_order_items_callback( $order_id, $items ) {
        if ( isset( $items['shipping_method_id'] ) ) {
            foreach( $items['shipping_method_id'] as $item_id ) {
                $num_packages = wc_get_order_item_meta($item_id, 'num_packages');
    
                if ( empty($num_packages) || $num_packages != 0 ) {
                    wc_update_order_item_meta( $item_id, 'num_packages', 0 );
                }
            }
        }
    }