Товар уже лежит в корзине, но карточка об этом не знает и снова предлагает «В корзину». Покупатель нажимает второй раз — и получает две штуки вместо одной, а потом разбирается с количеством на странице оформления. Логичнее показать ему другую кнопку: «Перейти в корзину». Сделать это можно хуками, не трогая файлы шаблонов, — и для карточки товара, и для кнопок в каталоге.
Как узнать, что товар уже в корзине
У объекта корзины есть метод find_product_in_cart(). Он принимает идентификатор позиции корзины, который строится из ID товара функцией generate_cart_id(), и возвращает ключ позиции либо пустую строку. Вынесем проверку в отдельную функцию, чтобы использовать её в нескольких местах:
// Возвращает true, если простой товар уже есть в корзине
function shop_product_in_cart( $product_id ) {
if ( ! WC()->cart ) {
return false; // в админке и REST-запросах корзины может не быть
}
$cart_id = WC()->cart->generate_cart_id( $product_id );
return (bool) WC()->cart->find_product_in_cart( $cart_id );
}
Проверка работает для простых товаров. У вариативных в корзине лежит конкретная вариация, и сравнивать пришлось бы её ID и атрибуты — в карточке товара до выбора вариации это не имеет смысла, поэтому дальше речь о простых товарах.
Карточка товара
Кнопку в карточке выводит функция woocommerce_template_single_add_to_cart, подключённая к хуку woocommerce_single_product_summary с приоритетом 30. Если товар уже в корзине, снимаем её с хука и ставим на то же место свою ссылку. Делаем это на том же хуке, но раньше — с приоритетом 1, когда объект товара уже известен:
add_action( 'woocommerce_single_product_summary', 'shop_swap_add_to_cart_button', 1 );
function shop_swap_add_to_cart_button() {
global $product;
if ( ! $product || ! $product->is_type( 'simple' ) || ! shop_product_in_cart( $product->get_id() ) ) {
return;
}
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_single_product_summary', 'shop_go_to_cart_button', 30 );
}
function shop_go_to_cart_button() {
printf(
'<a href="%s" class="single_add_to_cart_button button alt">%s</a>',
esc_url( wc_get_cart_url() ),
esc_html__( 'Перейти в корзину', 'shop' )
);
}
Ссылка получает те же классы, что и стандартная кнопка, поэтому выглядит как она. Адрес корзины берётся из wc_get_cart_url(), а не пишется вручную: у корзины может быть другой ярлык, а у сайта — подпапка или несколько языков.
Кнопки в каталоге
В списках товаров кнопка формируется фильтром woocommerce_loop_add_to_cart_link, и заменить её ещё проще:
add_filter( 'woocommerce_loop_add_to_cart_link', 'shop_loop_go_to_cart_link', 10, 2 );
function shop_loop_go_to_cart_link( $html, $product ) {
if ( ! $product->is_type( 'simple' ) || ! shop_product_in_cart( $product->get_id() ) ) {
return $html;
}
return sprintf(
'<a href="%s" class="button">%s</a>',
esc_url( wc_get_cart_url() ),
esc_html__( 'Перейти в корзину', 'shop' )
);
}
Ajax-добавление в каталоге
В каталоге товар обычно добавляется без перезагрузки страницы, и после клика наша PHP-подмена сработает только при следующем открытии страницы. Чтобы кнопка менялась сразу, подпишитесь на событие added_to_cart, которое WooCommerce отправляет после успешного добавления, вместе со ссылкой на нажатую кнопку:
jQuery( function( $ ) {
$( document.body ).on( 'added_to_cart', function( event, fragments, hash, $button ) {
if ( ! $button || ! $button.length ) {
return;
}
$button.replaceWith(
'<a href="' + wc_add_to_cart_params.cart_url + '" class="button">Перейти в корзину</a>'
);
} );
} );
Адрес корзины здесь уже есть в объекте wc_add_to_cart_params, который WooCommerce передаёт своему скрипту добавления в корзину. Подключите этот код на страницах каталога с зависимостью от wc-add-to-cart.
Подводный камень: кеширование страниц
Содержимое корзины у каждого покупателя своё, а страница товара с такой подменой становится персональной. Если на сайте включён кеш страниц — плагин кеширования или CDN, — первый посетитель с товаром в корзине «запишет» в кеш версию с «Перейти в корзину», и её увидят все остальные. Вариантов два: исключить страницы товаров из кеша (дорого для нагрузки) или делать подмену на стороне браузера. Во втором случае PHP-часть не нужна: скрипт запрашивает содержимое корзины и меняет кнопки сам. Данные о корзине WooCommerce уже отдаёт на каждой странице через фрагменты (wc_fragments), а на новых версиях — через Store API по адресу /wp-json/wc/store/v1/cart. Для магазина без кеша страниц хуки выше — самый простой и надёжный путь.
Блочные темы
В блочных темах карточку товара собирает блок «Добавить в корзину с опциями». В ранних версиях он выводил те же PHP-шаблоны, и хук из раздела про карточку работал; в новых версиях WooCommerce блок переписан и рендерится иначе. После обновления проверьте страницу товара: если подмена перестала работать, используйте вариант со скриптом.
Коротко
Проверить, есть ли товар в корзине, помогает find_product_in_cart(). В карточке товара стандартную кнопку снимают с хука woocommerce_single_product_summary и ставят ссылку на wc_get_cart_url(), в каталоге — подменяют через фильтр woocommerce_loop_add_to_cart_link и дополняют обработчиком события added_to_cart. При включённом кеше страниц подмену переносят в браузер.
Частые вопросы
WC()->cart->find_product_in_cart( WC()->cart->generate_cart_id( $product_id ) ) вернёт ключ позиции, если товар есть, и пустую строку, если нет. Перед вызовом проверьте, что объект корзины существует.
Переопределённый шаблон перестаёт получать обновления WooCommerce, и его придётся сверять с каждой версией. Хуки дают тот же результат и не зависят от разметки шаблона.
В каталоге товар добавляется через Ajax, и PHP-подмена срабатывает только при следующей загрузке страницы. Добавьте обработчик события added_to_cart, который заменит нажатую кнопку сразу.
Страница товара попала в кеш страниц с версией для покупателя, у которого товар был в корзине. Исключите страницы товаров из кеша или перенесите подмену кнопки в браузер, опираясь на данные корзины из Store API.
Источники
- 1.WC_Cart::find_product_in_cart — WooCommerce Code Referencehttps://woocommerce.github.io/code-reference/classes/WC-Cart.html#method_find_product_in_cart
- 2.WooCommerce Hooks Reference — woocommerce_single_product_summary, woocommerce_loop_add_to_cart_linkhttps://woocommerce.github.io/code-reference/hooks/hooks.html
- 3.Store API — Cart (документация WooCommerce)https://developer.woocommerce.com/docs/apis/store-api/resources-endpoints/cart/



