Я кодирую сайт WooCommerce. На странице моего магазина мне удалось вставить код «удалить из корзины» со страницы корзины, но когда я нажимаю на кнопку, это первый продукт (в алфавитном порядке) из корзины, который был удален. Как я могу сказать, мой код для удаления продукта, с которого я нажал
Изображение моего сайта здесь: my-shop-page
Я поместил этот код в content-product. php:
<form class="woocommerce-cart-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post">
<table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents" cellspacing="0">
<?php
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'] );
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
}
break;
}
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-remove">
<?php
echo apply_filters( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'woocommerce_cart_item_remove_link',
sprintf(
'<a href="%s" class="remove" aria-label="%s" data-product_id="%s" data-product_sku="%s">×</a>',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
esc_html__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
),
$cart_item_key
);
?>
</td>
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '<a href="%s">%s</a>', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
?>
</td>
<td class="product-name" data-title="<?php esc_attr_e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' ' );
} else {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '<a href="%s">%s</a>', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );
}
do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key );
// Meta data.
echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok.
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>', $product_id ) );
}
?>
</td>
</tr>
</table>
</form>
и у меня есть это JS, но я думаю, что проблема в PHP
/* global wc_cart_params */
jQuery( function( $ ) {
// wc_cart_params is required to continue, ensure the object exists
if ( typeof wc_cart_params === 'undefined' ) {
return false;
}
// Utility functions for the file.
/**
* Gets a url for a given AJAX endpoint.
*
* @param {String} endpoint The AJAX Endpoint
* @return {String} The URL to use for the request
*/
var get_url = function( endpoint ) {
return wc_cart_params.wc_ajax_url.toString().replace(
'%%endpoint%%',
endpoint
);
};
/**
* Check if a node is blocked for processing.
*
* @param {JQuery Object} $node
* @return {bool} True if the DOM Element is UI Blocked, false if not.
*/
var is_blocked = function( $node ) {
return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
};
/**
* Block a node visually for processing.
*
* @param {JQuery Object} $node
*/
var block = function( $node ) {
if ( ! is_blocked( $node ) ) {
$node.addClass( 'processing' ).block( {
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
} );
}
};
/**
* Unblock a node after processing is complete.
*
* @param {JQuery Object} $node
*/
var unblock = function( $node ) {
$node.removeClass( 'processing' ).unblock();
};
/**
* Update the .woocommerce div with a string of html.
*
* @param {String} html_str The HTML string with which to replace the div.
* @param {bool} preserve_notices Should notices be kept? False by default.
*/
var update_wc_div = function( html_str, preserve_notices ) {
var $html = $.parseHTML( html_str );
var $new_form = $( '.woocommerce-cart-form', $html );
var $new_totals = $( '.cart_totals', $html );
var $notices = $( '.woocommerce-error, .woocommerce-message, .woocommerce-info', $html );
// No form, cannot do this.
if ( $( '.woocommerce-cart-form' ).length === 0 ) {
window.location.reload();
return;
}
// Remove errors
if ( ! preserve_notices ) {
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
}
if ( $new_form.length === 0 ) {
// If the checkout is also displayed on this page, trigger reload instead.
if ( $( '.woocommerce-checkout' ).length ) {
window.location.reload();
return;
}
// No items to display now! Replace all cart content.
var $cart_html = $( '.cart-empty', $html ).closest( '.woocommerce' );
$( '.woocommerce-cart-form__contents' ).closest( '.woocommerce' ).replaceWith( $cart_html );
// Display errors
if ( $notices.length > 0 ) {
show_notice( $notices );
}
// Notify plugins that the cart was emptied.
$( document.body ).trigger( 'wc_cart_emptied' );
} else {
// If the checkout is also displayed on this page, trigger update event.
if ( $( '.woocommerce-checkout' ).length ) {
$( document.body ).trigger( 'update_checkout' );
}
$( '.woocommerce-cart-form' ).replaceWith( $new_form );
$( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true );
if ( $notices.length > 0 ) {
show_notice( $notices );
}
update_cart_totals_div( $new_totals );
}
$( document.body ).trigger( 'updated_wc_div' );
};
/**
* Update the .cart_totals div with a string of html.
*
* @param {String} html_str The HTML string with which to replace the div.
*/
var update_cart_totals_div = function( html_str ) {
$( '.cart_totals' ).replaceWith( html_str );
$( document.body ).trigger( 'updated_cart_totals' );
};
/**
* Shows new notices on the page.
*
* @param {Object} The Notice HTML Element in string or object form.
*/
var show_notice = function( html_element, $target ) {
if ( ! $target ) {
$target = $( '.woocommerce-notices-wrapper:first' ) || $( '.cart-empty' ).closest( '.woocommerce' ) || $( '.woocommerce-cart-form' );
}
$target.prepend( html_element );
};
/**
* Object to handle AJAX calls for cart shipping changes.
*/
var cart_shipping = {
/**
* Initialize event handlers and UI state.
*/
init: function( cart ) {
this.cart = cart;
this.toggle_shipping = this.toggle_shipping.bind( this );
this.shipping_method_selected = this.shipping_method_selected.bind( this );
this.shipping_calculator_submit = this.shipping_calculator_submit.bind( this );
$( document ).on(
'click',
'.shipping-calculator-button',
this.toggle_shipping
);
$( document ).on(
'change',
'select.shipping_method, :input[name^=shipping_method]',
this.shipping_method_selected
);
$( document ).on(
'submit',
'form.woocommerce-shipping-calculator',
this.shipping_calculator_submit
);
$( '.shipping-calculator-form' ).hide();
},
/**
* Toggle Shipping Calculator panel
*/
toggle_shipping: function() {
$( '.shipping-calculator-form' ).slideToggle( 'slow' );
$( document.body ).trigger( 'country_to_state_changed' ); // Trigger select2 to load.
return false;
},
/**
* Handles when a shipping method is selected.
*/
shipping_method_selected: function() {
var shipping_methods = {};
$( 'select.shipping_method, :input[name^=shipping_method][type=radio]:checked, :input[name^=shipping_method][type=hidden]' ).each( function() {
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
} );
block( $( 'div.cart_totals' ) );
var data = {
security: wc_cart_params.update_shipping_method_nonce,
shipping_method: shipping_methods
};
$.ajax( {
type: 'post',
url: get_url( 'update_shipping_method' ),
data: data,
dataType: 'html',
success: function( response ) {
update_cart_totals_div( response );
},
complete: function() {
unblock( $( 'div.cart_totals' ) );
$( document.body ).trigger( 'updated_shipping_method' );
}
} );
},
/**
* Handles a shipping calculator form submit.
*
* @param {Object} evt The JQuery event.
*/
shipping_calculator_submit: function( evt ) {
evt.preventDefault();
var $form = $( evt.currentTarget );
block( $( 'div.cart_totals' ) );
block( $form );
// Provide the submit button value because wc-form-handler expects it.
$( '<input />' ).attr( 'type', 'hidden' )
.attr( 'name', 'calc_shipping' )
.attr( 'value', 'x' )
.appendTo( $form );
// Make call to actual form post URL.
$.ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
},
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
}
} );
}
};
/**
* Object to handle cart UI.
*/
var cart = {
/**
* Initialize cart UI events.
*/
init: function() {
this.update_cart_totals = this.update_cart_totals.bind( this );
this.input_keypress = this.input_keypress.bind( this );
this.cart_submit = this.cart_submit.bind( this );
this.submit_click = this.submit_click.bind( this );
this.apply_coupon = this.apply_coupon.bind( this );
this.remove_coupon_clicked = this.remove_coupon_clicked.bind( this );
this.quantity_update = this.quantity_update.bind( this );
this.item_remove_clicked = this.item_remove_clicked.bind( this );
this.item_restore_clicked = this.item_restore_clicked.bind( this );
this.update_cart = this.update_cart.bind( this );
$( document ).on(
'wc_update_cart added_to_cart',
function() { cart.update_cart.apply( cart, [].slice.call( arguments, 1 ) ); } );
$( document ).on(
'click',
'.woocommerce-cart-form :input[type=submit]',
this.submit_click );
$( document ).on(
'keypress',
'.woocommerce-cart-form :input[type=number]',
this.input_keypress );
$( document ).on(
'submit',
'.woocommerce-cart-form',
this.cart_submit );
$( document ).on(
'click',
'a.woocommerce-remove-coupon',
this.remove_coupon_clicked );
$( document ).on(
'click',
'.woocommerce-cart-form .product-remove > a',
this.item_remove_clicked );
$( document ).on(
'click',
'.woocommerce-cart .restore-item',
this.item_restore_clicked );
$( document ).on(
'change input',
'.woocommerce-cart-form .cart_item :input',
this.input_changed );
$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true );
},
/**
* After an input is changed, enable the update cart button.
*/
input_changed: function() {
$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false );
},
/**
* Update entire cart via ajax.
*/
update_cart: function( preserve_notices ) {
var $form = $( '.woocommerce-cart-form' );
block( $form );
block( $( 'div.cart_totals' ) );
// Make call to actual form post URL.
$.ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
dataType: 'html',
success: function( response ) {
update_wc_div( response, preserve_notices );
},
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
$.scroll_to_notices( $( '[role="alert"]' ) );
}
} );
},
/**
* Update the cart after something has changed.
*/
update_cart_totals: function() {
block( $( 'div.cart_totals' ) );
$.ajax( {
url: get_url( 'get_cart_totals' ),
dataType: 'html',
success: function( response ) {
update_cart_totals_div( response );
},
complete: function() {
unblock( $( 'div.cart_totals' ) );
}
} );
},
/**
* Handle the <ENTER> key for quantity fields.
*
* @param {Object} evt The JQuery event
*
* For IE, if you hit enter on a quantity field, it makes the
* document.activeElement the first submit button it finds.
* For us, that is the Apply Coupon button. This is required
* to catch the event before that happens.
*/
input_keypress: function( evt ) {
// Catch the enter key and don't let it submit the form.
if ( 13 === evt.keyCode ) {
var $form = $( evt.currentTarget ).parents( 'form' );
try {
// If there are no validation errors, handle the submit.
if ( $form[0].checkValidity() ) {
evt.preventDefault();
this.cart_submit( evt );
}
} catch( err ) {
evt.preventDefault();
this.cart_submit( evt );
}
}
},
/**
* Handle cart form submit and route to correct logic.
*
* @param {Object} evt The JQuery event
*/
cart_submit: function( evt ) {
var $submit = $( document.activeElement ),
$clicked = $( ':input[type=submit][clicked=true]' ),
$form = $( evt.currentTarget );
// For submit events, currentTarget is form.
// For keypress events, currentTarget is input.
if ( ! $form.is( 'form' ) ) {
$form = $( evt.currentTarget ).parents( 'form' );
}
if ( 0 === $form.find( '.woocommerce-cart-form__contents' ).length ) {
return;
}
if ( is_blocked( $form ) ) {
return false;
}
if ( $clicked.is( ':input[name="update_cart"]' ) || $submit.is( 'input.qty' ) ) {
evt.preventDefault();
this.quantity_update( $form );
} else if ( $clicked.is( ':input[name="apply_coupon"]' ) || $submit.is( '#coupon_code' ) ) {
evt.preventDefault();
this.apply_coupon( $form );
}
},
/**
* Special handling to identify which submit button was clicked.
*
* @param {Object} evt The JQuery event
*/
submit_click: function( evt ) {
$( ':input[type=submit]', $( evt.target ).parents( 'form' ) ).removeAttr( 'clicked' );
$( evt.target ).attr( 'clicked', 'true' );
},
/**
* Apply Coupon code
*
* @param {JQuery Object} $form The cart form.
*/
apply_coupon: function( $form ) {
block( $form );
var cart = this;
var $text_field = $( '#coupon_code' );
var coupon_code = $text_field.val();
var data = {
security: wc_cart_params.apply_coupon_nonce,
coupon_code: coupon_code
};
$.ajax( {
type: 'POST',
url: get_url( 'apply_coupon' ),
data: data,
dataType: 'html',
success: function( response ) {
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
show_notice( response );
$( document.body ).trigger( 'applied_coupon', [ coupon_code ] );
},
complete: function() {
unblock( $form );
$text_field.val( '' );
cart.update_cart( true );
}
} );
},
/**
* Handle when a remove coupon link is clicked.
*
* @param {Object} evt The JQuery event
*/
remove_coupon_clicked: function( evt ) {
evt.preventDefault();
var cart = this;
var $wrapper = $( evt.currentTarget ).closest( '.cart_totals' );
var coupon = $( evt.currentTarget ).attr( 'data-coupon' );
block( $wrapper );
var data = {
security: wc_cart_params.remove_coupon_nonce,
coupon: coupon
};
$.ajax( {
type: 'POST',
url: get_url( 'remove_coupon' ),
data: data,
dataType: 'html',
success: function( response ) {
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
show_notice( response );
$( document.body ).trigger( 'removed_coupon', [ coupon ] );
unblock( $wrapper );
},
complete: function() {
cart.update_cart( true );
}
} );
},
/**
* Handle a cart Quantity Update
*
* @param {JQuery Object} $form The cart form.
*/
quantity_update: function( $form ) {
block( $form );
block( $( 'div.cart_totals' ) );
// Provide the submit button value because wc-form-handler expects it.
$( '<input />' ).attr( 'type', 'hidden' )
.attr( 'name', 'update_cart' )
.attr( 'value', 'Update Cart' )
.appendTo( $form );
// Make call to actual form post URL.
$.ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
},
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
$.scroll_to_notices( $( '[role="alert"]' ) );
}
} );
},
/**
* Handle when a remove item link is clicked.
*
* @param {Object} evt The JQuery event
*/
item_remove_clicked: function( evt ) {
evt.preventDefault();
var $a = $( evt.currentTarget );
var $form = $a.parents( 'form' );
block( $form );
block( $( 'div.cart_totals' ) );
$.ajax( {
type: 'GET',
url: $a.attr( 'href' ),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
},
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
$.scroll_to_notices( $( '[role="alert"]' ) );
}
} );
},
/**
* Handle when a restore item link is clicked.
*
* @param {Object} evt The JQuery event
*/
item_restore_clicked: function( evt ) {
evt.preventDefault();
var $a = $( evt.currentTarget );
var $form = $( 'form.woocommerce-cart-form' );
block( $form );
block( $( 'div.cart_totals' ) );
$.ajax( {
type: 'GET',
url: $a.attr( 'href' ),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
},
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
}
} );
}
};
cart_shipping.init( cart );
cart.init();
} );
Пожалуйста, помогите мне:)