如何解决Woocommerce如何使用自定义html单选按钮而不是下拉菜单将可变产品的添加到购物车按钮ajaxify - 没有插件
我正在尝试将这个拼图的所有部分拼凑在一起。在过去的 3 天里,我一直在阅读有关此主题的所有问题和答案。所以我遵循的总体蓝图如下:
- 在单个产品页面上,首先检查产品类型是“简单”还是“可变”。
- 如果产品是“可变的”,那么我使用
woocommerce_variable_add_to_cart();
函数来输出正确的 html。 - 然后尝试使用默认 html(即“下拉菜单”)和 woocommerce 挂钩生成新的和自定义的 html(即“单选按钮”)。
- 然后尝试使用 javascript 为新的和自定义的 html(即“单选按钮”)提供功能。
- 然后使用 css 隐藏默认下拉菜单。
- 然后尝试向 wordpress 发送 ajax 请求。
- 然后尝试在后端处理该 ajax 请求并将产品添加到购物车。
这是我每个部分的代码:
- 在单个产品页面上检查产品类型是否“可变”:
global $post;
$product = wc_get_product($post->ID);
$product_type = $product->get_type();
- 如果产品类型是“变量”,则输出正确的 html:
if($product_type == 'variable'):
woocommerce_variable_add_to_cart();
endif;
- 使用 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;
}
- 使用 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');
});
})
- 使用 css 隐藏默认下拉菜单:
table.variations select{
display: none;
}
- 向 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;
});
})
- 在后端处理 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 但找不到错误!我想我已经想了几天了,而且还有很多部分。
所以我想我需要一些额外的眼睛来检测错误。
谢谢,我感谢您的任何见解!
另外,向这些我从中学到很多东西的人大喊:
- LoicTheAztec 用于 this great answer 和 this 以及 this 等等。
- cfx 为 this great answer
- Anthony Grist 为 this answer
- helgatheviking 为 this answer
- 和其他人
编辑
代码工作正常,错误不在代码中,而是在我提供的数据中。我会把代码留在这里以防将来有人需要它。
解决方法
简短回答
代码运行良好,我会把它留在这里以防将来有人需要它。错误不在代码中,而是在我提供的数据中。
详细说明
代码运行良好。我的客户出于某些原因对我提供的数据进行了操作,因此每个可变产品都不是真正的可变产品,但同时标签被输入为可变产品(是的,我知道这很混乱,而不是标准练习),这就是为什么每当我尝试将它们添加到购物车时,它都会给出错误,指出 {your-attribute} 是必填字段。
因此,我们删除了每个产品数据,然后将其作为真实的可变产品重新添加回来,然后代码就可以工作了,而我们无需更改其中的任何内容。
外卖
所以请记住,无论何时开发您的应用程序,这枚硬币总是有两个方面!一方面是您的代码,另一方面是您正在处理的数据。
因此,始终始终,确保您使用的数据是它应有的方式/格式。另外,如果您在代码中找不到任何错误,请记住检查/调试另一端的数据。
如果您不先检查数据或在任何调试阶段都没有检查数据,那么以后就很难找到问题所在!
这个错误导致项目延迟了很长一段时间(大约需要 2 周时间才能找到数据中的错误)。所以一定要经常检查硬币的两面:
- 首先,您使用的数据
- 其次,您编写的代码。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。