Woocommerce如何使用自定义html单选按钮而不是下拉菜单将可变产品的添加到购物车按钮ajaxify - 没有插件

如何解决Woocommerce如何使用自定义html单选按钮而不是下拉菜单将可变产品的添加到购物车按钮ajaxify - 没有插件

我正在尝试将这个拼图的所有部分拼凑在一起。在过去的 3 天里,我一直在阅读有关此主题的所有问题和答案。所以我遵循的总体蓝图如下:

  1. 在单个产品页面上,首先检查产品类型是“简单”还是“可变”。
  2. 如果产品是“可变的”,那么我使用 woocommerce_variable_add_to_cart(); 函数来输出正确的 html。
  3. 然后尝试使用默认 html(即“下拉菜单”)和 woocommerce 挂钩生成新的和自定义的 html(即“单选按钮”)。
  4. 然后尝试使用 javascript 为新的和自定义的 html(即“单选按钮”)提供功能。
  5. 然后使用 css 隐藏默认下拉菜单。
  6. 然后尝试向 wordpress 发送 ajax 请求。
  7. 然后尝试在后端处理该 ajax 请求并将产品添加到购物车。

这是我每个部分的代码:

  1. 在单个产品页面上检查产品类型是否“可变”:
global $post;

$product = wc_get_product($post->ID);

$product_type = $product->get_type();

  1. 如果产品类型是“变量”,则输出正确的 html:
if($product_type == 'variable'):
  woocommerce_variable_add_to_cart();
endif;
  1. 使用 php 和 woocommerce 挂钩生成新的和自定义的 html(单选按钮):
add_filter('woocommerce_dropdown_variation_attribute_options_html','my_theme_variation_radio_buttons',20,2);

function my_theme_variation_radio_buttons($html,$args)
{
  $args = wp_parse_args(apply_filters('woocommerce_dropdown_variation_attribute_options_args',$args),array(
    'options'          => false,'attribute'        => false,'product'          => false,'selected'         => false,'name'             => '','id'               => '','class'            => '','show_option_none' => __('Choose an option','woocommerce'),));

  if (false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product) {
    $selected_key     = 'attribute_' . sanitize_title($args['attribute']);
    $args['selected'] = isset($_REQUEST[$selected_key]) ? wc_clean(wp_unslash($_REQUEST[$selected_key])) : $args['product']->get_variation_default_attribute($args['attribute']);
  }

  $options               = $args['options'];
  $product               = $args['product'];
  $attribute             = $args['attribute'];
  $name                  = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title($attribute);
  $id                    = $args['id'] ? $args['id'] : sanitize_title($attribute);
  $class                 = $args['class'];
  $show_option_none      = (bool)$args['show_option_none'];
  $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __('Choose an option','woocommerce');

  if (empty($options) && !empty($product) && !empty($attribute)) {
    $attributes = $product->get_variation_attributes();
    $options    = $attributes[$attribute];
  }

  $radios = '<div class="variation-radios">';

  if (!empty($options)) {
    if ($product && taxonomy_exists($attribute)) {
      $terms = wc_get_product_terms($product->get_id(),$attribute,array(
        'fields' => 'all',));

      foreach ($terms as $term) {
        if (in_array($term->slug,$options,true)) {
          $id = $name . '-' . $term->slug;
          $radios .= '<input type="radio" data-checked="no" id="' . esc_attr($id) . '" name="' . esc_attr($name) . '" value="' . esc_attr($term->slug) . '" ' . checked(sanitize_title($args['selected']),$term->slug,false) . '><label for="' . esc_attr($id) . '">' . esc_html(apply_filters('woocommerce_variation_option_name',$term->name)) . '</label>';
        }
      }
    } else {
      foreach ($options as $option) {
        $id = $name . '-' . $option;
        $checked    = sanitize_title($args['selected']) === $args['selected'] ? checked($args['selected'],sanitize_title($option),false) : checked($args['selected'],$option,false);
        $radios    .= '<input type="radio" id="' . esc_attr($id) . '" name="' . esc_attr($name) . '" value="' . esc_attr($option) . '" id="' . sanitize_title($option) . '" ' . $checked . '><label for="' . esc_attr($id) . '">' . esc_html(apply_filters('woocommerce_variation_option_name',$option)) . '</label>';
      }
    }
  }

  $radios .= '</div>';

  return $html . $radios;
}


add_filter('woocommerce_variation_is_active','my_theme_variation_check',10,2);

function my_theme_variation_check($active,$variation)
{
  if (!$variation->is_in_stock() && !$variation->backorders_allowed()) {
    return false;
  }
  return $active;
}
  1. 使用 javascript 为“单选按钮”提供功能:
jQuery(document).ready($ => {
  $(document).on('change','.variation-radio input',function () {
    $('.variation-radio input:checked').each(function (index,element) {

      var radioElement = $(element);
      var radioName = radioElement.attr('name');
      var radioValue = radioElement.attr('value');

      $('select[name="' + radioName + '"]').val(radioValue).trigger('change');
    });
  });
  $(document).on('woocommerce_update_variation_values',function () {
    $('.variation-radio input').each(function (index,element) {
      var radioElement = $(element);
      var radioName = radioElement.attr('name');
      var radioValue = radioElement.attr('value');
      radioElement.removeAttr('disabled');
      if ($('select[name="' + radioName + '"] option[value="' + radioValue + '"]').is(':disabled')) {
        radioElement.prop('disabled',true);
      }
    });
  });
  $("a.reset_variations").click(function () {
    $('input:radio[name="attribute_size"]').prop('checked',false); $(this).css('display','none');
  });
})
  1. 使用 css 隐藏默认下拉菜单:
table.variations select{
  display: none;
} 
  1. 向 wordpress 发送 ajax 请求:
jQuery(document).ready($ => {
  $("button.single_add_to_cart_button").on('click',function (e) {
    e.preventDefault();
    var myBtn = $(this),$form = myBtn.closest('form.variations_form'),product_qty = $form.find('input[name=quantity]').val() || 1,product_id = $form.find('input[name=product_id]').val(),variation_id = $form.find('input[name=variation_id]').val() || 0,variation = {},keys = [],values = [];
    // Looping through the attributes names and save them as the keys array
    $('table tr td.label label').each(function (index,element) {
      let radioElement = $(element);
      keys[index] = radioElement.text();
    });
    // Looping through the attributes values and save them as the values array
    $('.variation-radios input:checked').each(function (index,element) {
      let radioElement = $(element);
      values[index] = radioElement.val();
    });
    // Looping through the variation object and save keys and values in that object
    $.each(keys,function (index,element) {
      variation[element] = values[index]
    })
    console.log(variation);

    var data = {
      action: 'woocommerce_add_variation_to_cart',product_id: product_id,quantity: product_qty,variation_id: variation_id,var: variation
    };

    $(document.body).trigger('adding_to_cart',[myBtn,data]);

    $.ajax({
      type: 'post',url: wc_add_to_cart_params.ajax_url,data: data,beforeSend: function (response) {
        myBtn.removeClass('added').addClass('loading');
      },complete: function (response) {
        myBtn.addClass('added').removeClass('loading');
      },success: function (response) {
        console.log(response);
        if (response.error && response.product_url) {
          window.location = response.product_url;
          return;
        } else {
          $(document.body).trigger('added_to_cart',[response.fragments,response.cart_hash,myBtn]);
        }
      },});

    return false;
  });
})
  1. 在后端处理 ajax 请求并将产品添加到购物车:
add_action('wp_ajax_nopriv_woocommerce_add_variation_to_cart','my_theme_testing_add_to_cart_variable');

add_action('wp_ajax_woocommerce_add_variation_to_cart','my_theme_testing_add_to_cart_variable');

function my_theme_testing_add_to_cart_variable()
{
  if (isset($_POST['product_id']) && $_POST['product_id'] > 0) {
    $product_id = apply_filters('woocommerce_add_to_cart_product_id',absint($_POST['product_id']));

    $quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);

    $variation_id = isset($_POST['variation_id']) ? absint($_POST['variation_id']) : '';

    $attributes   = explode(',',$_POST['var']);

    $variation    = array();

    foreach ($attributes as $values) {

      $values = explode(':',$values);

      $variation['attributes_' . $values[0]] = $values[1];

    }

    $passed_validation = apply_filters('woocommerce_add_to_cart_validation',true,$product_id,$quantity);

    if ($passed_validation && WC()->cart->add_to_cart($product_id,$quantity,$variation_id,$variation)) {

      do_action('woocommerce_ajax_added_to_cart',$product_id);

      if (get_option('woocommerce_cart_redirect_after_add') == 'yes') {
        wc_add_to_cart_message($product_id);
      }

      WC_AJAX::get_refreshed_fragments();

    } else {

      $data = array(
        'error' => true,'product_url' => apply_filters('woocommerce_cart_redirect_after_error',get_permalink($product_id),$product_id)
      );

      wp_send_json($data);
    }

    die();
  }
}

问题

在第 7 步之前一切正常,没有错误,但是当我运行整个程序时,单个产品页面会刷新,并且变量产品不会添加到购物车中。并且 wordpress 错误显示“{您的属性字段} 是必填字段”!

我认为当我尝试将变体对象发送到后端时,错误可能在 ajax 调用中的某个地方。

虽然,我在后端获得的数据非常好,但它没有将其添加到购物车中。


我尝试调试的东西

我尝试将 ajax 调用中的数据作为数组发送,但也没有奏效。 我还尝试同时使用 =: 来分解变异数据,但都没有奏效!

蹄子!到目前为止,这是漫长的一周:\ 充满了调试、头痛和挫折。现在,当我尝试运行整个 shebang 时,我无法让它工作,而且我一直在阅读所有 Qs 和 As on SO 但找不到错误!我想我已经想了几天了,而且还有很多部分。

所以我想我需要一些额外的眼睛来检测错误。

谢谢,我感谢您的任何见解!


另外,向这些我从中学到很多东西的人大喊:


编辑

代码工作正常,错误不在代码中,而是在我提供的数据中。我会把代码留在这里以防将来有人需要它。

解决方法

简短回答

代码运行良好,我会把它留在这里以防将来有人需要它。错误不在代码中,而是在我提供的数据中。


详细说明

代码运行良好。我的客户出于某些原因对我提供的数据进行了操作,因此每个可变产品都不是真正的可变产品,但同时标签被输入为可变产品(是的,我知道这很混乱,而不是标准练习),这就是为什么每当我尝试将它们添加到购物车时,它都会给出错误,指出 {your-attribute} 是必填字段。

因此,我们删除了每个产品数据,然后将其作为真实的可变产品重新添加回来,然后代码就可以工作了,而我们无需更改其中的任何内容。


外卖
所以请记住,无论何时开发您的应用程序,这枚硬币总是有两个方面!一方面是您的代码,另一方面是您正在处理的数据。

因此,始终始终,确保您使用的数据是它应有的方式/格式。另外,如果您在代码中找不到任何错误,请记住检查/调试另一端的数据。
如果您不先检查数据或在任何调试阶段都没有检查数据,那么以后就很难找到问题所在!

这个错误导致项目延迟了很长一段时间(大约需要 2 周时间才能找到数据中的错误)。所以一定要经常检查硬币的两面:

  • 首先,您使用的数据
  • 其次,您编写的代码。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res