You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce:修复结账页供应商选择后post_author未保存及产品关联问题

Solution for WooCommerce Vendor Selection on Checkout

Let's work through your issues and implement the required features step by step:

1. Fix Selected Vendor ID Not Saving

Your current code only stores the vendor ID as order metadata, but it doesn't update the product's post_author as your requirement specifies. We'll adjust the checkout logic to both save the vendor association to the order and update the product's author ID.

2. Implement Product-Based Vendor Filtering

Right now you're pulling all available vendors, so we'll modify the vendor list function to only show vendors authorized to sell the single product in the cart (tailored for WCFM marketplace setups).

3. Enforce Single Product in Cart

Add a check to prevent users from adding more than one product to their cart at a time.

Full Modified Code

// Enforce single product in cart
add_filter( 'woocommerce_add_to_cart_validation', 'enforce_single_product_cart', 10, 3 );
function enforce_single_product_cart( $passed, $product_id, $quantity ) {
    if ( WC()->cart->get_cart_contents_count() >= 1 ) {
        wc_add_notice( __( 'You can only add one product to your cart at a time.', 'woocommerce' ), 'error' );
        $passed = false;
    }
    return $passed;
}

// Add vendor select field to checkout
add_action('woocommerce_before_order_notes', 'wps_add_select_checkout_field3');
function wps_add_select_checkout_field3( $checkout ) {
    // Get the single product from cart
    $cart_items = WC()->cart->get_cart();
    if ( empty( $cart_items ) ) return;
    
    $cart_item = reset( $cart_items );
    $product = $cart_item['data'];
    $product_id = $cart_item['product_id'];
    $current_vendor_id = get_post_field( 'post_author', $product_id );

    // Get filtered vendor list for this product
    function wcfm_get_product_vendors( $product_id ) {
        global $WCFM;
        $is_marketplace = wcfm_is_marketplace();
        $vendor_arr = array( '' => __('Choose Vendor ...', 'wc-frontend-manager' ) );
        
        if( !$is_marketplace || wcfm_is_vendor() ) return $vendor_arr;

        // Fetch vendors allowed to sell this product (WCFM-compatible)
        $allowed_vendor_ids = apply_filters( 'wcfm_product_allowed_vendors', array(), $product_id );
        
        $args = array(
            'role__in' => array( 'dc_vendor', 'vendor', 'seller' ),
            'orderby' => 'display_name',
            'order' => 'ASC',
            'include' => !empty($allowed_vendor_ids) ? $allowed_vendor_ids : array(),
            'count_total' => false,
            'fields' => array( 'ID', 'display_name' )
        );

        $all_users = get_users( $args );
        if( !empty( $all_users ) ) {
            foreach( $all_users as $all_user ) {
                $vendor_arr[$all_user->ID] = $all_user->display_name;
            }
        }

        // Pre-select current product vendor if available
        if ( isset($vendor_arr[$current_vendor_id]) ) {
            $checkout->set_value( 'post_author', $current_vendor_id );
        }

        return $vendor_arr;
    }

    $author_options = wcfm_get_product_vendors( $product_id );
    
    // Only show field if there are multiple vendors to choose from
    if ( count($author_options) > 1 ) {
        echo '<h4>'.__('Selectionner un établissement').'</h4>';
        woocommerce_form_field( 'post_author', array(
            'type' => 'select',
            'class' => array( 'wps-drop' ),
            'label' => __( 'Delivery options' ),
            'options' => $author_options
        ), $checkout->get_value( 'post_author' ));
    }
}

// Validate checkout vendor selection
add_action('woocommerce_checkout_process', 'wps_select_checkout_field_process');
function wps_select_checkout_field_process() {
    if ( isset($_POST['post_author']) && empty($_POST['post_author']) ) {
        wc_add_notice( '<strong>Please select a vendor</strong>', 'error' );
    }
}

// Update order meta AND product post_author
add_action('woocommerce_checkout_update_order_meta', 'wps_select_checkout_field_update_order_meta', 10, 2);
function wps_select_checkout_field_update_order_meta( $order_id, $posted_data ) {
    if ( isset($_POST['post_author']) && !empty($_POST['post_author']) ) {
        $vendor_id = esc_attr($_POST['post_author']);
        $vendor_name = get_the_author_meta('display_name', $vendor_id);
        
        // Save vendor details to order meta
        update_post_meta( $order_id, '_selected_vendor_id', $vendor_id );
        update_post_meta( $order_id, '_selected_vendor_name', $vendor_name );

        // Update the product's post_author (permanent change)
        $order = wc_get_order( $order_id );
        foreach ( $order->get_items() as $item ) {
            $product_id = $item->get_product_id();
            wp_update_post( array(
                'ID' => $product_id,
                'post_author' => $vendor_id
            ) );
        }
    }
}

// Display selected vendor in admin order page
add_action( 'woocommerce_admin_order_data_after_billing_address', 'wps_select_checkout_field_display_admin_order_meta', 10, 1 );
function wps_select_checkout_field_display_admin_order_meta($order){
    $vendor_id = get_post_meta( $order->get_id(), '_selected_vendor_id', true );
    $vendor_name = get_post_meta( $order->get_id(), '_selected_vendor_name', true );
    if ( $vendor_id && $vendor_name ) {
        echo '<p><strong>'.__('Selected Vendor').':</strong> ' . esc_html($vendor_name) . ' (ID: ' . esc_html($vendor_id) . ')</p>';
    }
}

// Add selected vendor to order emails
add_filter('woocommerce_email_order_meta_fields', 'wps_add_vendor_to_order_emails');
function wps_add_vendor_to_order_emails( $fields ) {
    $fields['_selected_vendor_name'] = array(
        'label' => __( 'Selected Vendor' ),
        'value' => get_post_meta( get_the_ID(), '_selected_vendor_name', true ),
    );
    return $fields;
}

Key Changes Explained

  • Single Product Enforcement: The enforce_single_product_cart function blocks adding additional products to the cart with a clear error message.
  • Filtered Vendors: The wcfm_get_product_vendors function now only pulls vendors associated with the cart product, using WCFM's built-in filter for product-vendor associations.
  • Proper Saving Logic: We now save vendor details to the order metadata and update the product's post_author to the selected vendor ID.
  • Improved Validation: Fixed checkout validation to properly check for an empty vendor selection.
  • Enhanced Admin/Email Display: Shows the vendor's name and ID in the order admin panel, and adds a clean, readable field to order confirmation emails.

Notes

  • If your WCFM setup uses a different method to link products to vendors (e.g., category-based vendor assignments), adjust the allowed_vendor_ids logic to match your workflow.
  • If you don't want to permanently change the product's owner, remove the wp_update_post section from the checkout update function.

内容的提问来源于stack exchange,提问作者benjfree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:11:27