修复WooCommerce变体图片无法删除及前端不显示问题
WooCommerce可变产品变体额外图片问题
近一周我编写自定义PHP与jQuery代码,为WooCommerce可变产品的每个变体添加额外图片上传功能,但遇到两个问题:
- 无法删除已选中的图片
- 上传的变体图片在前端页面完全不显示
参考LoicTheAztec的方案后,后台变体标签已能正常添加图片,但前端依然无展示效果,当前前端状态如图:
我使用的自定义代码
function custom_allow_multiple_variation_images($loop, $variation_data, $variation) { $variation_id = $variation->ID; $field_name = 'variation_image'; $attachment_ids = get_post_meta($variation_id, $field_name, true); echo '<div class="upload_variation_image">'; echo '<h4>Fotoğraf</h4>'; echo '<input type="hidden" name="' . $field_name . '[' . $loop . ']" id="' . $field_name . '" class="upload_image" value="' . esc_attr(implode(',', (array) $attachment_ids)) . '" />'; echo '<button class="upload_image_button button">Upload Image</button>'; if ($attachment_ids) { $attachment_ids = explode(',', $attachment_ids); foreach ($attachment_ids as $attachment_id) { $image_src = wp_get_attachment_image_src($attachment_id, 'thumbnail'); if ($image_src) { echo '<div class="uploaded_image_wrapper">'; echo '<img src="' . esc_url($image_src[0]) . '" alt="Uploaded Image" />'; echo '<span class="delete_variation_image" data-attachment_id="' . $attachment_id . '">Sil</span>'; echo '</div>'; } } } echo '</div>'; } add_action('woocommerce_variation_options', 'custom_allow_multiple_variation_images', 10, 3); function custom_save_variation_image($variation_id) { $field_name = 'variation_image'; $attachment_ids = isset($_POST[$field_name]) ? array_map('absint', explode(',', wc_clean($_POST[ $field_name][0]))) : array(); update_post_meta($variation_id, $field_name, implode(',', $attachment_ids)); } add_action('woocommerce_save_product_variation', 'custom_save_variation_image', 10, 1); add_action('woocommerce_save_product_variation', 'custom_save_variation_image', 10, 1); function custom_variation_image_scripts() { ?> <script> jQuery(document).ready(function($) { function custom_add_variation_image($wrapper) { var file_frame; if (file_frame) { file_frame.open(); return; } file_frame = wp.media.frames.file_frame = wp.media({ title: 'Variation Image Select', button: { text: 'Add Additional Image' }, multiple: true }); file_frame.on('select', function() { var attachment_ids = []; var selection = file_frame.state().get('selection'); selection.map(function(attachment) { attachment = attachment.toJSON(); attachment_ids.push(attachment.id); }); $wrapper.find('.upload_image').val(attachment_ids.join(',')); $wrapper.find('.uploaded_image_wrapper').remove(); attachment_ids.forEach(function(attachment_id) { var image_url = wp.media.attachment(attachment_id).get('url'); $wrapper.append('<div class="uploaded_image_wrapper"><img src="' + image_url + '" alt="Uploaded Image" /><span class="delete_variation_image" data-attachment_id="' + attachment_id + '">Sil</span></div>'); }); $wrapper.find('.upload_image').trigger('change'); // Trigger change event when selecting a variation image }); file_frame.open(); } function custom_remove_variation_image($wrapper, attachment_id) { var attachment_ids = $wrapper.find('.upload_image').val().split(','); var index = attachment_ids.indexOf(attachment_id); if (index !== -1) { attachment_ids.splice(index, 1); $wrapper.find('.upload_image').val(attachment_ids.join(',')); } $wrapper.find('.uploaded_image_wrapper[data-attachment_id="' + attachment_id + '"]').remove(); $wrapper.find('.upload_image').trigger('change'); // Trigger change event when removing a variation image } function custom_detect_variation_changes() { $('form.cart').on('change', '.variation-control', function() { $('.single_add_to_cart_button').prop('disabled', false); }); // When a variation image changes, enable "Add to Cart" button $('form.cart').on('change', '.upload_image', function() { $('.single_add_to_cart_button').prop('disabled', false); }); } // Medya yükleyici olaylarını ekle $(document).on('click', '.upload_image_button', function(e) { e.preventDefault(); custom_add_variation_image($(this).closest('.upload_variation_image')); }); $(document).on('click', '.delete_variation_image', function() { var attachment_id = $(this).data('attachment_id'); custom_remove_variation_image($(this).closest('.upload_variation_image'), attachment_id); }); custom_detect_variation_changes(); }); </script> <style> .uploaded_image_wrapper { margin: 10px 0; display: inline-block; } .uploaded_image_wrapper img { max-width: 100px; height: auto; margin-right: 10px; } .delete_variation_image { cursor: pointer; color: #a00; } </style> <?php } add_action( 'admin_footer', 'custom_variation_image_scripts' );
问题修复方案
1. 修复后台图片删除功能
你的删除函数中,尝试通过data-attachment_id选择容器,但后台渲染的.uploaded_image_wrapper未携带该属性,导致无法正确移除元素。同时ID类型不匹配也会导致数组索引查找失败,修改如下:
第一步:修改PHP渲染代码
给图片容器添加data-attachment_id属性:
echo '<div class="uploaded_image_wrapper" data-attachment_id="' . $attachment_id . '">'; echo '<img src="' . esc_url($image_src[0]) . '" alt="Uploaded Image" />'; echo '<span class="delete_variation_image" data-attachment_id="' . $attachment_id . '">Sil</span>'; echo '</div>';
第二步:修改JS删除函数
确保ID类型匹配,并正确选择容器:
function custom_remove_variation_image($wrapper, attachment_id) { var attachment_ids = $wrapper.find('.upload_image').val().split(','); var index = attachment_ids.indexOf(attachment_id.toString()); // 统一为字符串类型匹配 if (index !== -1) { attachment_ids.splice(index, 1); $wrapper.find('.upload_image').val(attachment_ids.join(',')); } $wrapper.find('.uploaded_image_wrapper[data-attachment_id="' + attachment_id + '"]').remove(); $wrapper.find('.upload_image').trigger('change'); }
第三步:删除重复钩子
代码中重复添加了保存钩子,删除其中一行:
// 删除此行重复代码 // add_action('woocommerce_save_product_variation', 'custom_save_variation_image', 10, 1);
2. 前端展示变体额外图片
添加前端监听与AJAX获取代码,实现变体切换时加载对应额外图片:
// 前端变体图片展示脚本 function custom_variation_frontend_scripts() { if (is_product() && wc_get_product()->is_type('variable')) { ?> <script> jQuery(document).ready(function($) { // 变体选中时加载额外图片 $('form.variations_form').on('show_variation', function(event, variation) { $.ajax({ url: wc_add_to_cart_params.ajax_url, type: 'POST', data: { action: 'get_variation_extra_images', variation_id: variation.variation_id }, success: function(response) { $('.variation-extra-images').remove(); if (response.success && response.data.images.length > 0) { var $container = $('<div class="variation-extra-images" style="margin-top:15px;"></div>'); response.data.images.forEach(function(img) { $container.append('<img src="' + img.src + '" alt="变体额外图片" style="max-width:200px; height:auto; margin-right:10px; margin-bottom:10px;" />'); }); $('.woocommerce-product-gallery').after($container); } } }); }); // 取消变体选择时清空图片 $('form.variations_form').on('hide_variation', function() { $('.variation-extra-images').remove(); }); }); </script> <?php } } add_action('wp_footer', 'custom_variation_frontend_scripts'); // AJAX接口:获取变体额外图片 function get_variation_extra_images() { if (!isset($_POST['variation_id']) || !is_numeric($_POST['variation_id'])) { wp_send_json_error('无效的变体ID'); } $variation_id = absint($_POST['variation_id']); $attachment_ids = get_post_meta($variation_id, 'variation_image', true); $images = array(); if ($attachment_ids) { foreach(explode(',', $attachment_ids) as $id) { $src = wp_get_attachment_image_src($id, 'medium')[0]; if ($src) $images[] = array('src' => $src); } } wp_send_json_success(array('images' => $images)); } add_action('wp_ajax_get_variation_extra_images', 'get_variation_extra_images'); add_action('wp_ajax_nopriv_get_variation_extra_images', 'get_variation_extra_images');
内容的提问来源于stack exchange,提问作者softwarEng92
相关产品推荐
相关产品推荐

