Woocommerce预订 - 如何更改已在购物车中的商品元数据?

时间:2018-05-02 18:52:11

标签: php wordpress woocommerce woocommerce-bookings

我正在尝试更改所有 可预订产品 的元数据< 已经在购物车中 ,更具体地说 - end_date和duration,但已经好几天没有结果......我需要在woocommerce_before_calculate_totals动作中执行此操作。我试过这段代码:

if ( $my_condition ) {
    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        if ( isset( $cart_item['booking'] ) ) {
            $cart_item['booking']->set_duration( $my_new_duration );
        }
    }
}

还有数以千计的其他方式,但都没有成功。

类似的方法适用于set_price(),它会改变价格,但可预订的产品元如持续时间和结束日期似乎无法改变已经在购物车中的产品!谷歌似乎对此无能为力,因为在搜索天数时我只能找到如何改变价格本身,而不是持续时间或其他元素。

有人可以帮帮我吗?谢谢!

编辑: 简单地说,这就是我想要实现的目标 - 让我们说我在购物车中有这些物品:

  • 产品1预订2018-05-10 10:00至2018-05-10 16:00
  • 产品2预订2018-05-10 10:00至2018-05-10 17:00

当我的功能触发时,我的购物车中的这两种产品预订范围应该更改为2018-05-10 10:00到2018-05-10 13:30

2 个答案:

答案 0 :(得分:2)

  

当我的功能触发时,这两种产品的预订范围都在我的   购物车应改为2018-05-10 10:00至2018-05-10 13:30

如果您只想设置固定的结束时间 (例如13:30,请参阅以下示例function ,我已经尝试并使用WooCommerce 3.3.5和WooCommerce Bookings 1.11.1在WordPress 4.9.5上正常运行。

但是,预计产品的预订时间(位于管理员编辑产品页面的常规标签中) 客户定义的{n} 小时 块;即类型为customer,单位为hour

// Use `WC_Cart::set_cart_contents()` to actually update the cart (contents).
// See `recalc_bookings_duration()` for an example of how to use this function.
function change_booking_end_time( array &$cart_item, $end_time ) {
    if ( ! isset( $cart_item['data'] ) ) {
        return false;
    }

    if ( ! preg_match( '/^\d{2}:\d{2}$/', $end_time ) ) {
        return false;
    }

    if ( ! is_wc_booking_product( $cart_item['data'] ) ) {
        //echo 'Not a Bookable product..<br>';
        return false;
    }

    if (
        'hour' !== $cart_item['data']->get_duration_unit() ||
        'customer' !== $cart_item['data']->get_duration_type()
    ) {
        //echo 'Duration unit/type error.<br>';
        return false;
    }

    $booking_id = $cart_item['booking']['_booking_id'];
    $booking = get_wc_booking( $booking_id );

    if ( $booking ) {
        // Set the end time in 24-hour clock format.
        $new_end_time = $end_time;

        // Get the timestamp of the `$new_end_time`.
        $start_time = $booking->get_start();
        $end_time = @strtotime( $new_end_time, $start_time );
        if ( ! $end_time ) {
            return false;
        }

        // Update the booking data; in the database.
        $_end_time = (int) $booking->get_end();
        if ( $end_time !== $_end_time ) {
            $booking->set_end( $end_time );
            $booking->save();

            // Update failed.
            $_end_time = (int) $booking->get_end();
            if ( $end_time !== $_end_time ) {
                //echo '$booking->save() error.<br>';
                return false;
            }
        // The end time / duration already changed.
        } else {
            //echo 'End time already match.<br>';
            return false;
        }

        // Re-calculate the duration (number of hours).
        $duration = abs( $end_time - $start_time ) / ( 60 * 60 );
        $cart_item['data']->set_duration( $duration );

        // Check/adjust the maximum duration.
        $max_duration = $cart_item['data']->get_max_duration();
        if ( is_numeric( $max_duration ) && $duration > $max_duration ) {
            $cart_item['data']->set_max_duration( ceil( $duration ) );
        }

        // Check/adjust the minimum duration.
        $min_duration = $cart_item['data']->get_min_duration();
        if ( is_numeric( $min_duration ) && $duration < $min_duration ) {
            $cart_item['data']->set_min_duration( floor( $duration ) );
        }

        // Update the product data; in the cart.
        $cart_item['data']->apply_changes();

        // Update the booking data; in the cart.
        $cart_item['booking']['_duration'] = $duration;
        $cart_item['booking']['duration'] = $duration . ' ' .
            _n( 'hour', 'hours', $duration, 'woocommerce-bookings' );
        $cart_item['booking']['_end_date'] = $booking->get_end();

        return true;
    }
}

使用示例

add_action( 'woocommerce_before_calculate_totals', 'recalc_bookings_duration' );
function recalc_bookings_duration( WC_Cart $cart ) {
    $cart_items = $cart->get_cart_contents();
    $update_cart = false;

    foreach ( $cart_items as $cart_item_key => $cart_item ) {
        if ( change_booking_end_time( $cart_item, '13:30' ) ) {
            $cart_items[ $cart_item_key ] = $cart_item;
            $update_cart = true;
        }
    }

    if ( $update_cart ) {
        $cart->set_cart_contents( $cart_items );
    }
}

答案 1 :(得分:-1)

尝试使用set_end( $my_new_duration );代替set_duration( $my_new_duration );插件文件中没有函数set_duration();

但首先,请在使用变量$my_new_duration之前检查新时间的格式。以下是set_end();

的功能
public function set_end( $timestamp ) {
        $this->set_prop( 'end', is_numeric( $timestamp ) ? $timestamp : strtotime( $timestamp ) );
    }