Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
328 views
in Technique[技术] by (71.8m points)

wordpress - Why does this work outside a plugin's hook, but not inside?

please help me. What am I missing here?

I created a plugin that creates a coupon with an order. And with the following, I want to attach the coupon's code to an email. The coupon is stored in an array in a custom postmeta field _associated_coupons.

Right now, when I do vardump on $associated_coupons (at #ref2), it gives me string(0).

But when I place the code outside of the hook or plugin (which is very simple, no OOP) and use a manual order_id (which works inside the hook as well), this perfectly returns an array of the associated coupon IDs.

add_action( 'woocommerce_email_before_order_table', 'add_coupons_to_email', 10, 4 );
  
function add_coupons_to_email( $order, $sent_to_admin, $plain_text, $email ) {

    if ( $email->id == 'customer_completed_order' ) {

        //#ref1

        // get order ID
        $order_id = $order->get_id();

        // Check order for associated Coupons
        if ( metadata_exists( 'post', $order_id, '_associated_coupons' ) ) {

            $associated_coupons = get_post_meta( $order_id, '_associated_coupons', true );

            // #ref2

            // Check if 
            if ( count( $associated_coupons ) > 0 ) {
                // #ref3
                // get coupon data etc.
                // echo stuff;
            }
        }
    }
}

The hook itself works and I can put stuff in the email (e. g. at #ref1. Just the postmeta does not get through and I do not get to #ref3.

I probably missed something very basic.

Please help!

Update

As requested, here is the rest of the plugin, a hook that creates the coupon with an order:

add_action ( 'woocommerce_order_status_completed', 'create_coupon', 31, 1 );
 
function create_coupon( $order_id ) {

    if ( ! $order_id ) return;

    // Allow code execution only once 
    if ( ! get_post_meta( $order_id, '_created_coupon_on_completion', true ) ) {

        // Get an instance of the WC_Order object
        $order = wc_get_order( $order_id );

        $code = random_bytes(8);

        $coupon_ids = array();

        // Create a coupon with the properties you need
        $data = array(
            'discount_type'              => 'percent_product', // Type: fixed_cart, percent, fixed_product, percent_product
            'coupon_amount'              => 100, // value
            'individual_use'             => 'no',
            'product_ids'                => array(999),
            'exclude_product_ids'        => array(),
            'usage_limit'                => '1',
            'usage_limit_per_user'       => '',
            'limit_usage_to_x_items'     => '1',
            'usage_count'                => '',
            'expiry_date'                => date( 'Y-m-d', strtotime( '+3 years' ) ), // YYYY-MM-DD
            'free_shipping'              => 'no',
            'product_categories'         => array(),
            'exclude_product_categories' => array(),
            'exclude_sale_items'         => 'no',
            'minimum_amount'             => '',
            'maximum_amount'             => '',
            'customer_email'             => array(),
            'order_id'                   => $order_id
        );

        // Save the coupon in the database
        $coupon = array(
            'post_title' => $code,
            'post_content' => '',
            'post_status' => 'publish',
            'post_author' => 1,
            'post_type' => 'shop_coupon'
        );

        $new_coupon_id = wp_insert_post( $coupon );
                    
        // Write the $data values into postmeta table
        foreach ($data as $key => $value) {
            update_post_meta( $new_coupon_id, $key, $value );
        }

        $coupon_ids[] = $new_coupon_id;

        // Coupon IDs to order
        $order->update_meta_data( '_associated_coupons', $coupon_ids );
        
        // Flag the action as done (to avoid repetitions on reload for example)
        $order->update_meta_data( '_created_coupon_on_completion', true );
        $order->save();
    }
}

The raw value in the db is for example this: a:1:{i:0;i:12345;}

Can the problem relate to the priority or the order in which the hooks are called?

Update 2

As suggested, I tried hardcoding the $order_id which was successful.

Then I tried another way to get dynamically to the ID:

if ( $email->id == 'customer_completed_order' ) {

        $order = $email->object;

        $order_id = $order->get_id();

        var_dump($order_id);

        $associated_coupons = get_post_meta( $order_id, '_associated_coupons', true );

        var_dump($associated_coupons);

This leads to int(12345) string(0) "" (12345 is the correct order_id)

Might the sending of the email happen BEFORE there is anything in the table? Looking at the documentation of get_post_meta (respectively get_postmeta):

If the meta field does not exist, the result depends on get_metadata_default(). By default, an empty string is returned if $single is true, or an empty array if it’s false.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Okay, it was the priority. Put both at 10, now it works.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...