woocommercesubscriptionmembershipwoocommerce-subscriptions

Woocommerce Subscriptions - Set owner programmatically


I'm using WooCommerce Subscriptions on a site to provide team-based memberships. I'd like to ensure that the owner of the Subscription matches the owner of the team (one user to rule them all...!)

It's possible to do this via admin by using the customer dropdown fields.

So, I have been trying to set this programmatically. As I understand it, there are getter and setter methods for all the Subscription data (and as a Subscription is extended from WC_Order, those methods should work too). However, I can't figure out what method to use to make this change.

I've tried creating both a subscription and an order instance from a subscription ID, but neither of the methods I've tried below work:

set_user_id(456)
set_customer_id(456)

When I print_r() the Subscription instance, the original customer_id is still there under the data array:

WC_Subscription Object
(
    [data:protected] => Array
    (
   ...
   [customer_id] => 123
   )
...
)

Given that the array is protected, I'm guessing there's a setter method I haven't tried yet. Can someone please help me with what type of instance and setter method I need for this please?

Cheers!


Solution

  • I'm pleased to say I've solved this one myself - posting here to hopefully help someone else from banging their heads against the walls!

    Turns out I was doing everything correctly, I just wasn't calling the save() method after I made my changes......! D'oh!

    I'm quite used to functions in WordPress having immediate effect - a valid call to update_post_meta, for example, will take effect straight away.

    Instead, WooCommerce stores changes via getters/setters within the local instance created through WC_Order (or other abstractions). These are only saved to the database* when you call the save() method. I believe this is to help prevent unnecessary database calls.

    *or data store if you're doing something very fancy.

    Code example for those who need it, for an order ID '123' and a new user ID '456':

    // Create order instance
    $order_instance = wc_get_order(123);
    
    // Set new customer id
    $order_instance->set_customer_id(456);
    
    // Save changes
    $order_instance->save();
    
    // To echo data back, use the get_data() method to create an array of data, which you can assign however needed. For example:
    
    $order_data = $order_instance->get_data();
    
    $customer_id = $order_data['customer_id']; 
    
    echo 'customer number = ' .  $customer_id;
    

    I found the information about why the data requires manually saving (it's only stored in the local instance) from the very helpful doc at Advanced Woo:

    "Setter methods update information in the WC_Data object held in working memory. However, one of the Database Operations Methods must be called to make the change in the database."

    https://advancedwoo.com/topic/wc_data-and-data-storage-manipulate/#/setters