在 Woocommerce 中动态更改特定产品的购物车商品价格和名称

Change cart item price and name for a specific product dynamically in Woocommerce

在 WooCommerce 中,我有一个价格设置为 0 的特定产品 (产品 ID 为 2938

当通过 href="http://yourdomain.com/?add-to-cart=2938" 将该产品添加到购物车时,我试图根据当前用户的自定义 post 动态设置价格(这是一个有点复杂的计算,基于 posts 用户已创建,否则我将使用 groups/bundles。)

基于 "" 答案代码,这是我得到的:

add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {

    // ID of the product I've set up
    $product_id_to_change = 2938;

    $user_id = get_current_user_id();

    $studio_args = array(
        'post_type' => 'studio',
        'post_status' => 'published',
        'posts_per_page' => 1,
        'author' => $user_id
    );

    $studio_query = new WP_Query( $studio_args );

    foreach( $studio_query as $studio ) {
        $studio_listing_name = get_the_title();
        $studio_listing_option = get_post_meta( $studio->ID, 'wpcf-listing-option', true );
    }

    if ( $studio_listing_option = array( 1, 2 ) ) {
        $new_price = 180;
    } elseif ( $studio_listing_option = array( 3, 4 ) ) {
        $new_price = 345;
    } elseif ( $studio_listing_option = array( 5, 6, 7 ) ) {
        $new_price = 690;
    }

    $new_name = 'Payment for 2020 Listing: ' . $user_id . ' - ' . $studio_listing_name . ' - ' . 'Listing Option ' . $studio_listing_option;

    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $item ) {
        $item['data']->set_price( $new_price );
        $item['data']->set_name( $new_name );
    }

}

重要的是要注意每个用户只能有一个工作室。我认为我的 foreach 和 if ( $studio_listing_option = array( 1, 2 ) ) 检查是 wrong/can 可能做得更好。关于如何让它更好地工作有什么想法吗?

如何将计算限制为仅产品 ID 2938

此外,$studio_listing_name returns 空白,$studio_listing_option returns 数组。我可以改进它以使其正常工作吗?

首先,很难提供帮助,因为我们对您的 "studio" 自定义 post 类型以及如何为客户设置数据一无所知。

您的代码中存在一些错误和遗漏的内容,例如您的 IF 语句,您应该需要在其中使用 in_array() 条件函数。

我试图猜测数据是如何在 wpcf-listing-option 元数据中为您的 studio 自定义 post 类型设置的,我想这是 之间的数字1(一)和7(七)。

同样在您的代码中,当您循环 $studio_query$studio_listing_name$studio_listing_option 时,您将始终从循环的最后一项中获取值……所以有问题按照你的逻辑。

在下面的代码中,我只针对您指定的产品 ID (没有任何保证,即使它不能完全工作也应该有所帮助):

add_action( 'woocommerce_before_calculate_totals', 'customize_cart_item_details', 20, 1);
function customize_cart_item_details( $cart ) {

    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 || ! is_user_logged_in() )
        return;

    // ID of the product I've set up
    $defined_product_id = 2938;

    $customer_id = get_current_user_id();

    // Get "studio" custom post objects
    $studio_query = get_posts( array(
        'post_type' => 'studio',
        'post_status' => 'published',
        'posts_per_page' => 1,
        'author' => $customer_id
    ) );

    // Get the first "studio" post for the current user
    $studio = reset( $studio_query );

    $studio_name   = $studio->post_title;
    $studio_option = get_post_meta( $studio->ID, 'wpcf-listing-option', true );

    if ( in_array( $studio_option, array( 1, 2 ) ) ) {
        $new_price = 180;
    } elseif ( in_array( $studio_option, array( 3, 4 ) ) ) {
        $new_price = 345;
    } elseif ( in_array( $studio_option, array( 5, 6, 7 ) ) ) {
        $new_price = 690;
    }

    $new_name = sprintf( 
        __( "Payment for 2020 Listing: %s - %s - Listing Option %s", "woocommerce" ),
        $customer_id, $studio_name, $studio_option 
    );

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item ) {
        // Only for the defined product ID (or variation ID)
        if ( in_array( $defined_product_id, [ $cart_item['product_id'], $cart_item['variation_id'] ] ) ) {
            $cart_item['data']->set_price( $new_price );
            $cart_item['data']->set_name( $new_name );   
        }
    }
}