我想有一个特定的WooCommerce产品,客户可以输入他们自己的价格/价值的礼品卡.我发现了一个非常好的脚本,如果您创建一个价格值为0的简单产品,它几乎可以做到这一点,但有三个问题我无法解决:

  1. 使用此脚本,客户可以在类别页面上订购价格为0的产品.
  2. 客户还可以在价格字段中输入文本值,而不仅仅是数字值.
  3. 价格0在产品页面上可见,最好将其隐藏.我使用css代码来隐藏它,但我认为这不是一种非常巧妙的方式.

.single-product.postid-241982 div.product p.price {display: none;}

add_action( 'woocommerce_before_add_to_cart_button', 'bbloomer_product_price_input', 9 );
  
function bbloomer_product_price_input() {
   global $product;
   if ( 241982 !== $product->get_id() ) return;
   woocommerce_form_field( 'set_price', array(
      'type' => 'text',
      'required' => true,
      'label' => 'Set price ' . get_woocommerce_currency_symbol(),
   ));
}
  
add_filter( 'woocommerce_add_to_cart_validation', 'bbloomer_product_add_on_validation', 9999, 3 );
  
function bbloomer_product_add_on_validation( $passed, $product_id, $qty ) {
   if ( isset( $_POST['set_price'] ) && sanitize_text_field( $_POST['set_price'] ) == '' ) {
      wc_add_notice( 'Set price is a required field', 'error' );
      $passed = false;
   }
   return $passed;
}
  
add_filter( 'woocommerce_add_cart_item_data', 'bbloomer_product_add_on_cart_item_data', 9999, 2 );
  
function bbloomer_product_add_on_cart_item_data( $cart_item, $product_id ) {
   if ( 241982 !== $product_id ) return $cart_item;    
   $cart_item['set_price'] = sanitize_text_field( $_POST['set_price'] );
   return $cart_item;
}
 
add_action( 'woocommerce_before_calculate_totals', 'bbloomer_alter_price_cart', 9999 );
  
function bbloomer_alter_price_cart( $cart ) {
   if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
   if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
   foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
      $product = $cart_item['data'];
      if ( 241982 !== $product->get_id() ) continue;
      $cart_item['data']->set_price( $cart_item['set_price'] );
   } 
}

推荐答案

您的代码中存在一些错误和遗漏内容.请try 以下操作:

// Remove specific product displayed price on archive pages
add_action( 'woocommerce_after_shop_loop_item_title', 'remove_loop_specific_product_displayed_price', 1 );
function remove_loop_specific_product_displayed_price(){
    global $product;

    // Only for specific product ID
    if ( 241982 == $product->get_id() ) {
        // Remove price
        remove_action('woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
    }
}

// Remove specific product displayed price in single product
add_action( 'woocommerce_single_product_summary', 'remove_specific_product_displayed_price', 1 );
function remove_specific_product_displayed_price() {
    global $product;

    // Only for specific product ID
    if ( 241982 == $product->get_id() ) {
        // Remove price
        remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
    }
}

// Replace loop add to cart button with a link to the product page
add_filter( 'woocommerce_loop_add_to_cart_link', 'replace_specific_product_add_to_cart_link', 100, 3 );
function replace_specific_product_add_to_cart_link( $button, $product, $args ) {
    // Only for specific product ID
    if ( 241982 == $product->get_id() ) {
        $button = sprintf( '<a href="%s" class="%s" %s>%s</a>',
            esc_url( $product->get_permalink() ),
            esc_attr( 'button' ),
            isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
            esc_html__( 'Set a price', 'woocommerce' )
        );
    }
    return $button;
}

// Display price input field on specific single product
add_action( 'woocommerce_before_add_to_cart_button', 'display_product_price_input_field', 9 );
function display_product_price_input_field() {
    global $product;

    // Only for specific product ID
    if ( 241982 == $product->get_id() ) {
        woocommerce_form_field( 'custom_price', array(
            'type'      => 'text',
            'label'     => sprintf(__('Set price (%s)', 'woocommerce'), get_woocommerce_currency_symbol()),
            'required'  => true,
        ));
    }
}
   
// Add to cart field validation (Accept only a numerical value greater than zero)
add_filter( 'woocommerce_add_to_cart_validation', 'sov_product_add_on_validation' );
function sov_product_add_on_validation( $passed ) {
    if ( isset($_POST['custom_price']) ) {
        // Replace "," with "." for float numbers
        $custom_price = str_replace(',', '.', esc_attr($_POST['custom_price'])); 
        
        if ( empty($custom_price) || ! is_numeric($custom_price) || ! ($custom_price > 0) ) {
            wc_add_notice( 'Set price  is a required field (only accepts a numerical value greater than zero)', 'error' );
            $passed = false;
        }
    }
    return $passed;
}

// Add custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data', 10, 2 );
function filter_add_cart_item_data( $cart_item_data, $product_id ) { 
    if ( isset($_POST['custom_price']) ) {
        // Replace "," with "." for float numbers
        $custom_price = str_replace(',', '.', esc_attr($_POST['custom_price']));

        $cart_item_data['custom_price'] = floatval($custom_price);
        $cart_item_data['unique_key']   = md5(microtime().rand());
    }
    return $cart_item_data;
}

// Display the correct cart item custom price html
add_action( 'woocommerce_cart_item_price', 'filter_cart_displayed_price', 10, 2 );
function filter_cart_displayed_price($price, $cart_item) {
    if ( isset($cart_item['custom_price']) ) {
        $args = array('price' => floatval($cart_item['custom_price']));

        if ('incl' === get_option('woocommerce_tax_display_cart')) {
            $product_price = wc_get_price_including_tax($cart_item['data'], $args);
        } else {
            $product_price = wc_get_price_excluding_tax($cart_item['data'], $args);
        }
        return wc_price($product_price);
    }
    return $price;
}

// Set cart item custom price
add_action( 'woocommerce_before_calculate_totals', 'set_price_before_calculate_totals' );   
function set_price_before_calculate_totals( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) 
        return;

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        if ( isset($cart_item['custom_price']) ) {
            $cart_item['data']->set_price( $cart_item['custom_price'] );
        } 
    }
}

代码放在子主题的functions.php文件中(或插件中).测试和作品.

Note:一些主题使他们自己的定制,所以一些不同的东西可能需要在WooCommerce档案和单一产品页面to remove the displayed price.

Php相关问答推荐

MySQLi是否在事务错误时删除保存点(并且仅删除保存点)?

PHP:PHP手册-Manual

PHP原始数据读取引发max_input_vars错误

PHP MySQL求和子树并与父树累加

将一个情态形式放在细丝v3中的形式中间

是否重新排序多维数组元素以将所有子数组中的子数组移动到元素列表的底部?

WooCommerce在收据页面获取产品下载URL

将购物车按钮重定向到Checkout-Wooccommerce

Laravel 10.x在到达控制器之前将查询参数强制转换为正确的类型

未检测到laravel控制器

在 WooCommerce 更新结帐事件上动态更新自定义内容

PHP向API发送curl请求

Laravel Eloquent:复杂的多对多关系以及缺失关系的默认值

如何通过帖子自定义元数据进行查询

服务器遇到内部错误或配置错误,无法完成您的请求

如何更改或管理Carbon时区,使其不会来回移动时钟

PHP/Laravel 中的自定义时区

php-http/discovery 插件 1.15.1 是否仍在使用自己的模块 destruct Contao 4.13 中的composer 安装?

即使密码匹配,密码处理程序也会返回错误

标头内容类型:image/jpeg 无效