Search code examples
phpwordpresswoocommerceorderspost-meta

Using WordPress post meta functions with array variables on WooCommerce orders


I see in many places that WordPress will automatically serialize arrays with update_post_meta.

But, their docs state that you should serialize it before using update_post_meta. https://developer.wordpress.org/reference/functions/update_post_meta/

I am also getting different results when using get_post_meta that uses a serialized value or the array.

    $val = array();
    $val['one'] = 1;
    $val['two'] = 2;
    $val['threed']['x'] = 'ex';
    $val['threed']['y'] = 'why';

    $ser = serialize($val);

    update_post_meta($order_id, 'testing arr', $val);
    update_post_meta($order_id, 'testing ser arr', $ser);

    // This was saved in the table as...
    // a:3:{s:3:"one";i:1;s:3:"two";i:2;s:6:"threed";a:2:{s:1:"x";s:2:"ex";s:1:"y";s:3:"why";}}
    // s:88:"a:3:{s:3:"one";i:1;s:3:"two";i:2;s:6:"threed";a:2:{s:1:"x";s:2:"ex";s:1:"y";s:3:"why";}}";

    $testarr = get_post_meta($order_id, 'testing arr');
    $testarrser = get_post_meta($order_id, 'testing ser arr');
Using get_post_meta for each of the above and printing the array gives the following: 
NOTE 1: get_post_meta($id, $field, true) and get_post_meta($id, $field, false) return the same data structure.
NOTE 2: These were not unserialized - just print_r() the returned values.

testarr: Array(
    [0] => Array (
            [one] => 1
            [two] => 2
            [threed] => Array (
                    [x] => ex
                    [y] => why
                )
        )
)

testarrser: Array(
    [0] => a:3:{s:3:"one";i:1;s:3:"two";i:2;s:6:"threed";a:2:{s:1:"x";s:2:"ex";s:1:"y";s:3:"why";}}
)

Please explain the correct way to update_post_meta to retrieve the expected array.

Solution

  • No, you don't need to serialize an array before using WordPress add_post_meta() or update_post_meta() functions, as those functions will do that internally using included maybe_serialize() function.

    Now when using get_post_meta() set the 3rd parameter to true to get the correct initial saved array, like

    $testarr = get_post_meta($order_id, 'testing arr', true);
    

    Caution, for WooCommerce Orders (and HPOS compatibility):

    You should not use anymore WordPress post meta functions, instead you should use CRUD methods from the WC_Order object like:

    $data = array();
    $data['one'] = 1;
    $data['two'] = 2;
    $data['threed']['x'] = 'ex';
    $data['threed']['y'] = 'why';
    
    $order = wc_get_order( $order_id ); // Get the WC_Order Object (if needed)
    
    $order->update_meta_data( 'testing_arr', $data ); // Add the metadata
    $order->save(); // Save it to the database
    

    To get this array from the WC_Order object use:

    $order = wc_get_order( $order_id ); // Get the WC_Order Object (if needed)
    
    $data = $order->get_meta('testing_arr'); // Get the metadata
    

    This way is compatible with High Performance Orders Storage (HPOS) as WooCommerce is now using custom tables in the database.

    Related: