将特定产品与 WooCommerce 中的主要产品一起添加到购物车

问题描述 投票:0回答:1

我尝试做一些类似于“产品插件”的事情,但是是手动的。我不会有一些简单的产品,必须作为伴侣。他们的 id 是相同的。 我想把它们做成复选框,上面有照片、名称和价格。如果选中复选框 - 该产品必须与产品页面上的主产品一起添加到购物车。这是一个代码,已经被 gpt 调整过

// Function to display checkboxes for additional products
function display_additional_products_checkboxes() {
    $additional_products_ids = array(220, 222, 224, 226); // Replace with your product IDs

    echo '<div class="additional-products">';
    echo '<h3>Additional Products</h3>';

    foreach ($additional_products_ids as $product_id) {
        $additional_product = wc_get_product($product_id);
        if ($additional_product) {
            $product_name = $additional_product->get_name();
            $product_price = $additional_product->get_price_html();
            $product_id_sanitized = sanitize_title($additional_product->get_slug());

            echo '<div class="additional-product">';
            echo '<label for="additional_product_' . $product_id_sanitized . '">';
            echo '<input type="checkbox" name="additional_products[]" id="additional_product_' . $product_id_sanitized . '" value="' . $product_id . '">';
            echo $product_name . ' - ' . $product_price;
            echo '</label>';
            echo '</div>';
        }
    }

    echo '</div>';
}
add_action('woocommerce_before_add_to_cart_button', 'display_additional_products_checkboxes');

// Function to process additional products checkboxes
function add_additional_products_to_cart($cart_item_data, $product_id, $variation_id) {
    if (isset($_POST['additional_products']) && !empty($_POST['additional_products'])) {
        $additional_products = wc_clean(wp_unslash($_POST['additional_products']));
        $cart_item_data['additional_products'] = $additional_products;
    }
    return $cart_item_data;
}
add_filter('woocommerce_add_cart_item_data', 'add_additional_products_to_cart', 10, 3);

// Function to display additional products in cart
function display_additional_products_in_cart($item_data, $cart_item) {
    if (isset($cart_item['additional_products']) && !empty($cart_item['additional_products'])) {
        $additional_products = $cart_item['additional_products'];
        $additional_products_names = array();

        foreach ($additional_products as $product_id) {
            $product = wc_get_product($product_id);
            if ($product) {
                $additional_products_names[] = $product->get_name();
            } else {
                error_log("Failed to get additional product with ID: $product_id");
            }
        }

        $item_data[] = array(
            'key'   => __('Additional Products', 'woocommerce'),
            'value' => implode(', ', $additional_products_names),
        );
    }

    return $item_data;
}
add_filter('woocommerce_get_item_data', 'display_additional_products_in_cart', 10, 2);

// Function to add additional products to order
function add_additional_products_to_order($item, $cart_item_key, $values, $order) {
    if (isset($values['additional_products']) && !empty($values['additional_products'])) {
        $additional_products = $values['additional_products'];

        foreach ($additional_products as $product_id) {
            $product = wc_get_product($product_id);
            if ($product) {
                $item->add_meta_data(__('Additional Product', 'woocommerce'), $product->get_name());
            } else {
                error_log("Failed to get additional product with ID: $product_id");
            }
        }
    }
}
add_action('woocommerce_checkout_create_order_line_item', 'add_additional_products_to_order', 10, 4);

// Function to add additional products as separate line items in the cart
function add_additional_products_as_separate_items($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) {
    if (isset($cart_item_data['additional_products']) && !empty($cart_item_data['additional_products'])) {
        if (!isset(WC()->session->additional_products_added)) {
            WC()->session->set('additional_products_added', array());
        }
        $processed = WC()->session->get('additional_products_added');

        $additional_products = $cart_item_data['additional_products'];

        foreach ($additional_products as $additional_product_id) {
            if (!in_array($additional_product_id, $processed)) {
                $additional_product = wc_get_product($additional_product_id);
                if ($additional_product) {
                    error_log("Adding additional product to cart: " . $additional_product->get_name());
                    WC()->cart->add_to_cart($additional_product_id);
                    $processed[] = $additional_product_id; // Mark this additional product as processed
                } else {
                    error_log("Failed to add additional product with ID: $additional_product_id");
                }
            }
        }

        WC()->session->set('additional_products_added', $processed);
    }
}
add_action('woocommerce_add_to_cart', 'add_additional_products_as_separate_items', 10, 6);

// Clear session data after checkout
function clear_additional_products_session() {
    if (isset(WC()->session->additional_products_added)) {
        WC()->session->__unset('additional_products_added');
    }
}
add_action('woocommerce_checkout_order_processed', 'clear_additional_products_session');

但是我仍然遇到同样的问题,而 gpt 也无能为力 - 我一次又一次地遇到这个问题。 日志显示类似

[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One
[25-Jun-2024 04:21:09 UTC] Adding additional product to cart: Present One

就像无限循环。 Gpt 试图帮助解决会话时刻,但没有帮助。也许有人会更清楚我错在哪里?

php woocommerce bundle product cart
1个回答
0
投票

你让事情变得比应有的更复杂。您不需要使用 WC 会话,不需要显示附加产品的功能,因为您将它们添加到购物车,并且不需要将附加产品添加为订单项目的功能。

主要问题是使用

woocommerce_add_to_cart
时会产生无限循环:
由于
woocommerce_add_to_cart
钩子位于 WC_Cart add_to_cart() 方法中,因此当将其他产品添加到购物车时,它们会一次又一次地触发自己
woocommerce_add_to_cart
...

下面我在 WooCommerce 管理产品设置中添加了一个多选字段,允许您在产品级别定义其他产品:

// Display a multi select field to Admin Product edit pages
add_action('woocommerce_product_options_general_product_data', 'add_admin_product_custom_field');
function add_admin_product_custom_field() {
    global $post, $product_object;

    $field_key = 'bundled_ids';

    printf('<div class="options_group"><p class="form-field"><label for="%s">%s</label>
    <select class="wc-product-search" multiple="multiple" style="%s" id="%s" name="%s[]" '.
    'data-placeholder="%s" data-action="woocommerce_json_search_products_and_variations" data-exclude="%d">',
    $field_key, esc_html__('Bundled products', 'woocommerce'), 'width: 50%;', $field_key, 
    $field_key, esc_attr__('Search for a product&hellip;', 'woocommerce'), intval($post->ID) );

    $product_ids = (array) $product_object->get_meta('_'.$field_key);

    foreach ( $product_ids as $product_id ) {
        $product = wc_get_product( $product_id );
        if ( is_object( $product ) ) {
            echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
        }
    }
    
    echo '</select>' . wc_help_tip( __( 'Bundled products are products that will be added to cart optionally.', 'woocommerce' ) ); // WPCS: XSS ok.
    echo '</p></div>';
}

// Save custom field values from product edit page
add_action('woocommerce_admin_process_product_object', 'save_admin_product_custom_field_value');
function save_admin_product_custom_field_value( $product ) {
    $field_key = 'bundled_ids';
    $product->update_meta_data('_'.$field_key, isset($_POST[$field_key]) ? wc_clean( wp_unslash($_POST[$field_key]) ) : array());
}

您将得到:

enter image description here

然后这是您修改后的代码,显示附加产品复选框并将所选附加产品作为单独的购物车项目添加到购物车(已注释)

// Display checkbox(es) for additional product(s)
add_action('woocommerce_before_add_to_cart_button', 'display_additional_products_checkboxes');
function display_additional_products_checkboxes() {
    global $product;

    if ( $bundled_product_ids = $product->get_meta('_bundled_ids') ) {
        echo '<div class="additional-products">
        <h3>'. __('Additional Products') .'</h3>';

        foreach ($bundled_product_ids as $_product_id) {
            $_product = wc_get_product($_product_id);

            if ( is_object($_product) ) {
                printf('<div class="form-row"><label for="bundled-products-%d">
                <input type="checkbox" name="bundled_products[]" id="bundled-products-%d" value="%d">
                &nbsp;%s: %s</label></div>', 
                $_product_id, $_product_id, $_product_id, $_product->get_name(), $_product->get_price_html() );
            }
        }

        echo '</div><br>';
    }
}

// Add selected additional product IDs as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'set_bundled_products_as_custom_item_data', 10 );
function set_bundled_products_as_custom_item_data( $cart_item_data ) {
    if ( ! isset($cart_item_data['parent_id']) 
    && isset($_POST['bundled_products']) && ! empty($_POST['bundled_products']) ) {
        $cart_item_data['bundled_products'] = wc_clean( wp_unslash($_POST['bundled_products']) );
    }
    return $cart_item_data;
}

// Add selected additional products as separated cart items
add_action( 'template_redirect', 'add_to_cart_bundled_products' );
function add_to_cart_bundled_products( $cart_item_data ) {
    if ( isset($_POST['bundled_products']) && ! empty($_POST['bundled_products']) ) {
        // Get the additional products
        $bundled_products = wc_clean( wp_unslash($_POST['bundled_products']) );

        // Get the parent bundle product ID
        $parent_id = isset($_POST['add-to-cart']) && $_POST['add-to-cart'] > 0 ? intval($_POST['add-to-cart']) : null;
        $parent_id = isset($_POST['variation_id']) && $_POST['variation_id'] > 0 ? intval($_POST['variation_id']) : $parent_id ;

        // Loop through additional selected product IDs
        foreach ( $bundled_products as $product_id ) {
            $product     = wc_get_product($product_id); // Get the product Object
            $is_variation = $product->is_type('variation'); // Is it a variation

            if ( is_object($product) ) {
                $variation_id = $is_variation ? $product_id : 0;
                $product_id = $is_variation ? $product->get_parent_id() : $product_id;
                $attributes = $is_variation ? $product->get_variation_attributes() : [];

                // Add additional product to cart (with the parent bundle product ID as custom cart item data)
                WC()->cart->add_to_cart($product_id, 1, $variation_id, $attributes, ['parent_id' => $parent_id ]);
            }
        }
    }
}

代码位于子主题的functions.php 文件中(或插件中)。已测试并可以使用。

现在附加产品也作为单独的项目添加到购物车。


如果您想像代码中一样使用产品 ID 数组,请替换:

if ( $bundled_product_ids = $product->get_meta('_bundled_ids') ) {

与:

$bundled_product_ids = array(220, 222, 224, 226); // Define your product IDs

if ( $bundled_product_ids ) {

用于测试

在页脚中显示购物车商品数据(和自定义数据):

add_action('wp_footer', 'wp_footer_output_cart_items_data_for_test', 10);
function wp_footer_output_cart_items_data_for_test() {
    echo '<pre>'. print_r( WC()->session->get('cart'), true ) . '</pre>'; 
}
© www.soinside.com 2019 - 2024. All rights reserved.