十一年专注,只做WordPress定制开发一件事

Woocommerce如何实现不同产品添加到不同的购物车?

王超
2023-04-03
Woocommerce开发
980 次

最近再给一个企业做技术顾问期间,他们使用woocommerce做了一个电商平台,他们除了商品的常规销售外,还允许批发,但是想要实现批发产品加入购物车后和常规常规销售的产品加入购物车后有个区分,可以理解为视觉上的两个购物车,一个专门显示批发产品,一个专门显示常规销售的产品,且结账的时候批发产品和常规产品分开结账,比如我单独结算批发产品的时候,常规产品不参与结算,仍然保留在购物车中。

而且批发产品的价格和常规产品的价格是不同的,还有最低批发数量。根据以上需求,我们经过测试实验出了一个有效的思路,思路如下:

1、首先为产品数据添加新的选项卡和自定义字段,这样我们可以设置具体的某个产品是否支持批发,批发的价格,以及最低批发数量等信息;

//添加产品设置新的选项卡
add_filter('woocommerce_product_data_tabs', function ($tabs)
{
    $tabs[ 'custom_tab' ] = [
        'label'    => "批发设置",
        'target'   => 'product_wholesal_settings',
        'class'    => [ 'show_if_simple','show_if_variable','show_if_grouped','show_if_external'],
        'priority' => 25,
    ];

    return $tabs;
});
//添加产品字段到新添加的选项卡
add_action('woocommerce_product_data_panels', function ()
{
    ?>
    <!--下面的id要和上面创建的选项卡的target保持一致-->
    <div id="product_wholesal_settings" class="panel woocommerce_options_panel hidden">
        <?php
            $pro_custom_title = get_post_meta(get_the_ID(),'pro_custom_title',true);
            $is_wholesal = get_post_meta(get_the_ID(),'is_wholesal',true); 
            $product_power = get_post_meta(get_the_ID(),'product_power',true); 
            $wholesal_mini_count = get_post_meta(get_the_ID(),'wholesal_mini_count',true); 
            $wholesal_price = get_post_meta(get_the_ID(),'wholesal_price',true); 
            woocommerce_wp_text_input([
                'id'            => 'pro_custom_title',
                'label'         => '自定义标题',
                'value' => $pro_custom_title,
            ]);
            woocommerce_wp_checkbox([
                'id'            => 'is_wholesal',
                'label'         => '是否支持批发',
                'value' => $is_wholesal,
            ]);
            woocommerce_wp_text_input([
                'id'            => 'product_power',
                'label'         => '产品功率',
                'value' => $product_power,
                'type'  => 'number'
            ]);
            woocommerce_wp_text_input([
                'id'            => 'wholesal_mini_count',
                'label'         => '起批数量',
                'value' => $wholesal_mini_count,
                'type'  => 'number'
            ]);
            woocommerce_wp_text_input([
                'id'            => 'wholesal_price',
                'label'         => '批发价格',
                'value' => $wholesal_price,
                'type'  => 'number'
            ]);
        ?>
    </div>
<?php
});

//保存自定义字段数据到产品
add_action('woocommerce_process_product_meta', function ($post_id)
{
    $product = wc_get_product($post_id);

    $product->update_meta_data('pro_custom_title', sanitize_text_field($_POST[ 'pro_custom_title' ]));

    $is_wholesal = isset($_POST[ 'is_wholesal' ]) ? 'yes' : '';
    $product->update_meta_data('is_wholesal', $is_wholesal);

    $product->update_meta_data('product_power', sanitize_text_field($_POST[ 'product_power' ]));

    $product->update_meta_data('wholesal_mini_count', sanitize_text_field($_POST[ 'wholesal_mini_count' ]));

    $product->update_meta_data('wholesal_price', sanitize_text_field($_POST[ 'wholesal_price' ]));

    $product->save();
});

2,客户需要批发和常规销售区分开展示,所以我们添加了一个自定义页面模板文件,用来显示批发产品,以及批发产品加入购物车,其中批发产品不是默认显示出来的,而是根据用户在表单中输入的信息筛选出来多套批发方案,每套方案里有多个产品,加入购物车按钮点击的时候是将指定方案里的所有产品一键加入购物车。所以我们前端做了ajax请求,把产品信息传递到后端,然后通过后端将产品加入到购物车,因为批发价格是自定义字段里设置的,所以不能使用产品默认的价格设置,后端还对价格进行了处理,而且给从批发页面添加到购物车的产品添加了特殊的标识。前端代码就不列举了,一下是后端代码:

function add_wholesale_product_to_cart( $product_id, $quantity ) {
    $cart = WC()->cart->get_cart();
    $special_flag = 'wholesale'; // 设置特殊标记
    $product = wc_get_product( $product_id );
    $wholesal_price = (float) $product->get_meta( 'wholesal_price', true ); // 获取产品自定义字段的价格
    $cart_item_data = array( 'special_flag' => $special_flag,'wholesal_price'=>$wholesal_price);
    $cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, 0, array(), $cart_item_data );
}
// Change price of items in the cart
add_action( 'woocommerce_before_calculate_totals', 'add_custom_item_price', 1 );
function add_custom_item_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;
    foreach ( $cart->get_cart() as $cart_item ) {
        // ID 650 is the cleaning equipment id
        if( isset( $cart_item['wholesal_price'] ) ) { 
            // Get the calculated custom price
            $new_price = (float) $cart_item['wholesal_price'];
                        // set the new item price in cart
            $cart_item['data']->set_price( $new_price );
        }
    }
}
function wholesal_add_to_cart() {
    $dataArray = $_POST['dataArray'];
    $nonce = $_POST['nonce'];
    if ( ! wp_verify_nonce( $nonce, 'wholesal_add_to_cart_nonce' ) ) {
        die( 'Invalid nonce' );
    }
    if ( $dataArray ) {
        foreach( $dataArray as $data ) {
            $product_id = $data['product'];
            $quantity = $data['quantity'];
            add_wholesale_product_to_cart( $product_id, $quantity );
        }
        $response = array(
            'redirect' => add_query_arg( array('wholesal' => ''), wc_get_cart_url())
        );
        wp_send_json($response);
    }
    wp_die();
}
add_action( 'wp_ajax_wholesal_add_to_cart', 'wholesal_add_to_cart' );
add_action( 'wp_ajax_nopriv_wholesal_add_to_cart', 'wholesal_add_to_cart' );

3、为了区分批发购物车和常规购物车,我们通过给购物车页面(我的其实是结账页面,因为我把购物车和结账页面合并了)url添加传参的方法来区分,有传参的是批发的,只显示批发产品,没有传参的是常规的,只显示常规的,当然有些钩子中无法通过$_GET方法获取到url中的参数,所以,我们先判断如果有传参就给wc的session里储存一个值,然后大部分的时候通过这个session来判断和区分批发和常规产品;

//将url中传参wholesal储存到sessinon
function save_wholesal_parameter_to_session() {
    if ( isset( $_GET['wholesal'] ) ) {
        WC()->session->set( 'wholesal_parameter', true );
    } else {
        WC()->session->set( 'wholesal_parameter', null );
    }
}
add_action( 'template_redirect', 'save_wholesal_parameter_to_session' );

4、我们需要去重新定义购物车页面的代码,里面输出的产品要根据session和购物车中的产品特殊标进行分开显示,这个就不列举代码了。

5、然后我们还需要对订单预览和创建订单做一些相关的处理,确保批发产品和常规产品能分开结算,且不会把不符合条件的产品从购物车中清除;相关代码如下,大家可以参考;

// Show only wholesale products in cart
function show_wholesale_products_in_cart( $cart_contents ) {
    $wholesal_parameter = WC()->session->get( 'wholesal_parameter' );
    if ( $wholesal_parameter ) {
        foreach ( $cart_contents as $key => $cart_item ) {
            if ( ! isset( $cart_item['special_flag'] ) || $cart_item['special_flag'] !== 'wholesale' ) {
                $cart_contents[ $key ]['data']->set_price(0); // 非批发产品设为0价格
            }
        }
    } else {
        foreach ( $cart_contents as $key => $cart_item ) {
            if ( isset( $cart_item['special_flag'] ) && $cart_item['special_flag'] === 'wholesale' ) {
                $cart_contents[ $key ]['data']->set_price(0); // 批发产品设为0价格
            }
        }
    }
    return $cart_contents;
}
add_filter( 'woocommerce_cart_contents', 'show_wholesale_products_in_cart', 10, 1 );

// Calculate total only for wholesale products
function calculate_total_for_wholesale_products( $total ) {
    $wholesal_parameter = WC()->session->get( 'wholesal_parameter' );
    if ( $wholesal_parameter) {
        $total = 0;
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            if ( isset( $cart_item['special_flag'] ) && $cart_item['special_flag'] === 'wholesale' ) {
                $total += $cart_item['line_total'];
            }
        }
    } else {
        $total = 0;
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            if ( !isset( $cart_item['special_flag'] )) {
                $total += $cart_item['line_total'];
            }
        }
    }
    return $total;
}
add_filter( 'woocommerce_calculated_total', 'calculate_total_for_wholesale_products', 10, 1 );

//创建订单时计算订单总价
function calculate_total_for_wholesale_products_order( $cart ) {
    $wholesal_parameter = WC()->session->get( 'wholesal_parameter' );
    if ( $wholesal_parameter ) {
        $total = 0;
        foreach ( $cart->get_cart() as $cart_item ) {
            if ( isset( $cart_item['special_flag'] ) && $cart_item['special_flag'] === 'wholesale' ) {
                $total += $cart_item['line_total'];
            }
        }
        $cart->set_total( $total );
    }
}
add_action( 'woocommerce_calculate_totals', 'calculate_total_for_wholesale_products_order' );
//更新购物车小计
function calculate_subtotal_for_wholesale_products( $subtotal, $compound, $cart ) {
    $wholesal_parameter = WC()->session->get( 'wholesal_parameter' );
    if ( $wholesal_parameter && $wholesal_parameter === true) {
        $subtotal = 0;
        foreach ( $cart->get_cart() as $cart_item ) {
            if ( isset( $cart_item['special_flag'] ) && $cart_item['special_flag'] === 'wholesale' ) {
                $subtotal += $cart_item['line_subtotal'];
            }
        }
    } else {
        $subtotal = 0;
        foreach ( $cart->get_cart() as $cart_item ) {
            if ( ! isset( $cart_item['special_flag'] ) ) {
                $subtotal += $cart_item['line_subtotal'];
            }
        }
    }
    return wc_price( $subtotal );
}
add_filter( 'woocommerce_cart_subtotal', 'calculate_subtotal_for_wholesale_products', 10, 3 );


//订单预览按条件显示
add_filter( 'woocommerce_checkout_cart_item_visible', 'hide_product_at_checkout', 10, 3 );
function hide_product_at_checkout( $visible, $cart_item, $cart_item_key ) {
    $show_only_special_products = WC()->session->get( 'wholesal_parameter' );
    $special_flag = 'wholesale'; // 设置特殊标记
    if ($show_only_special_products) {
        if ( isset( $cart_item['special_flag'] ) && $cart_item['special_flag'] === $special_flag ) {
            return $visible;
        } else {
            return false;
        }
    } else {
        if ( isset( $cart_item['special_flag'] ) && $cart_item['special_flag'] === $special_flag ) {
            return false;
        } else {
            return $visible;
        }
    }
    return $visible;
}
//给结账页面添加隐藏字段儿,用来判断提交订单时时批发的还是常规的
add_action( 'woocommerce_checkout_before_order_review', 'add_custom_hidden_field' );
function add_custom_hidden_field() {
    $show_only_special_products = WC()->session->get( 'wholesal_parameter' );
    echo '<input type="hidden" name="is_wholesal_submit" value="' . esc_attr( $show_only_special_products ) . '">';
}

//结算的时候把不符合条件的产品存到session中,然后从购物车中删除
add_action( 'woocommerce_checkout_process', 'exclude_special_products_from_checkout' );
function exclude_special_products_from_checkout() {
    $is_wholesal_submit = isset( $_POST['is_wholesal_submit'] ) ? sanitize_text_field( $_POST['is_wholesal_submit'] ) : '';
    $special_flag = 'wholesale'; // 设置特殊标记
    $excluded_products = array();
    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        if($is_wholesal_submit){
            // 如果购物车中的产品没有特殊标记,则将其添加到数组中
            if ( ! isset( $cart_item['special_flag'] ) || $cart_item['special_flag'] !== $special_flag ) {
                $excluded_products[ $cart_item_key ] = $cart_item;
                WC()->cart->remove_cart_item( $cart_item_key );
            }
        } else {
            // 如果购物车中的产品有特殊标记,则将其添加到数组中
            if ( isset( $cart_item['special_flag'] ) || $cart_item['special_flag'] === $special_flag ) {
                $excluded_products[ $cart_item_key ] = $cart_item;
                WC()->cart->remove_cart_item( $cart_item_key );
            }
        }
    }
    
    // 将排除的产品添加到 session 中
    WC()->session->set( 'excluded_products', $excluded_products );
}
//订单创建成功后,把不符合条件的产品重新添加到购物车
add_action( 'woocommerce_thankyou', 'add_products_to_cart_after_order', 10, 1 );
function add_products_to_cart_after_order( $order_id ) {
    // 从 session 中获取不符合条件的产品
    $excluded_products = WC()->session->get( 'excluded_products', array() );
    foreach ( $excluded_products as $cart_item_key => $cart_item ) {
        WC()->cart->add_to_cart( $cart_item['product_id'], $cart_item['quantity'], $cart_item['variation_id'], $cart_item['variation'], $cart_item );
    } 
    // 清空 session 中的排除产品数据
    WC()->session->set( 'excluded_products', array() );
}

以上就是整体的思路,当然里面并没有完全顾及到所有的细节,如果大家有类似需求的,可以做个参考。

文章标签:

WordPress日记主要承接WordPress主题定制开发PSD转WordPressWordPress仿站以及以WordPress为管理后端的小程序、APP,我们一直秉持“做一个项目,交一个朋友”的理念,希望您是我们下一个朋友。如果您有WordPress主题开发需求,可随时联系QQ:919985494 微信:18539976310

搜索

嘿,有问题找我来帮您!