Задача: динамическая замена изображения товара после покупки
В стандартном WooCommerce изображение товара остается постоянным на всех страницах, включая страницы заказа и повторного просмотра. Иногда нужно показать покупателю, что товар уже куплен — например, заменить основное изображение на вариант «Куплено» или добавить водяной знак.
Рассмотрим, как реализовать замену изображения товара на страницах магазина и корзины после того, как пользователь приобрел данный товар, используя GeneratePress без сторонних плагинов.
Диагностика: как понять, что нужно менять именно изображение товара
В первую очередь, определите, где именно нужно менять изображение:
- Страница архива товаров (каталог)
- Страница отдельного товара
- Корзина и оформление заказа
Для каждой локации своя логика в WooCommerce и свои хуки для вывода изображения. Важно понять, где именно пользователь встречается с товаром и где должна отображаться модификация.
Для проверки, какие хуки используются, можно включить отладчик WooCommerce или посмотреть шаблоны темы GeneratePress в папке wp-content/themes/generatepress/woocommerce (если есть).
Пошаговое решение: замена изображения товара, если пользователь купил товар
1. Получаем список купленных товаров для текущего пользователя
function gp_get_purchased_product_ids( $user_id ) {
if ( ! $user_id ) {
return array();
}
$customer_orders = wc_get_orders( array(
'customer_id' => $user_id,
'limit' => -1,
'status' => array('completed', 'processing'),
'return' => 'ids',
) );
$purchased_ids = array();
foreach ( $customer_orders as $order_id ) {
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item ) {
$purchased_ids[] = $item->get_product_id();
}
}
return array_unique( $purchased_ids );
}2. Подменяем изображение товара в каталоге (страница архива)
Для изменения вывода изображения на странице магазина используем фильтр woocommerce_get_product_thumbnail:
add_filter( 'woocommerce_get_product_thumbnail', 'gp_replace_thumbnail_if_purchased', 10, 2 );
function gp_replace_thumbnail_if_purchased( $image, $product ) {
if ( ! is_user_logged_in() ) {
return $image;
}
$user_id = get_current_user_id();
$purchased = gp_get_purchased_product_ids( $user_id );
if ( in_array( $product->get_id(), $purchased ) ) {
// Путь к изображению "Куплено" или водяного знака
$replacement_url = get_template_directory_uri() . '/images/purchased-badge.png';
$image = '<img src="' . esc_url( $replacement_url ) . '" class="attachment-shop_catalog size-shop_catalog" alt="Куплено">';
}
return $image;
}3. Подмена изображения на странице отдельного товара
Для замены главного изображения используем фильтр woocommerce_single_product_image_thumbnail_html или переопределяем функцию вывода галереи с помощью woocommerce_before_single_product_summary. Но проще добавить фильтр woocommerce_single_product_image_thumbnail_html:
add_filter( 'woocommerce_single_product_image_thumbnail_html', 'gp_replace_single_image_if_purchased', 10, 2 );
function gp_replace_single_image_if_purchased( $html, $attachment_id ) {
if ( ! is_user_logged_in() ) {
return $html;
}
global $product;
$user_id = get_current_user_id();
$purchased = gp_get_purchased_product_ids( $user_id );
if ( in_array( $product->get_id(), $purchased ) ) {
$replacement_url = get_template_directory_uri() . '/images/purchased-badge.png';
$html = '<img src="' . esc_url( $replacement_url ) . '" alt="Товар куплен" />';
}
return $html;
}4. Изменение изображения в корзине
Для замены изображения в корзине используем фильтр woocommerce_cart_item_thumbnail:
add_filter( 'woocommerce_cart_item_thumbnail', 'gp_replace_cart_thumbnail_if_purchased', 10, 3 );
function gp_replace_cart_thumbnail_if_purchased( $thumbnail, $cart_item, $cart_item_key ) {
if ( ! is_user_logged_in() ) {
return $thumbnail;
}
$product_id = $cart_item['product_id'];
$user_id = get_current_user_id();
$purchased = gp_get_purchased_product_ids( $user_id );
if ( in_array( $product_id, $purchased ) ) {
$replacement_url = get_template_directory_uri() . '/images/purchased-badge.png';
$thumbnail = '<img src="' . esc_url( $replacement_url ) . '" alt="Куплено" class="wp-post-image" />';
}
return $thumbnail;
}Проверка результата после внедрения
- Залогиньтесь под пользователем, купившим товары.
- Перейдите на страницу каталога — изображения купленных товаров должны замениться на ваш «Куплено».
- Откройте страницу отдельного товара — изображение тоже должно измениться.
- Добавьте товар в корзину — изображение в корзине также заменится.
- Для незалогиненных пользователей и покупателей без купленных товаров изменения не должны проявляться.
Частые ошибки и как их исправить
- Ошибка: Изображения не меняются.
Причина: Неправильный путь к файлу или отсутствует файл в теме.
Решение: Проверьте, что файлpurchased-badge.pngлежит в папкеimagesвашей темы GeneratePress. Используйтеget_stylesheet_directory_uri()для дочерней темы. - Ошибка: Замена изображений происходит для всех пользователей.
Причина: Не проверяется статус залогинен ли пользователь или список купленных товаров пуст.
Решение: Добавьте проверкиis_user_logged_in()и убедитесь, что функция возвращает корректный массив. - Ошибка: Фильтры конфликтуют с плагинами кэширования.
Решение: Очистите кэш сайта и браузера, настройте исключения для страниц с контентом под пользователя.
Практические советы по безопасности и производительности
- Кэширование: Динамическая замена изображений зависит от пользователя, поэтому кэш страниц должен учитывать залогиненость. Используйте плагин с поддержкой пользовательского кэша (например, WP Rocket с опцией кэша для залогиненных).
- Оптимизация: Используйте сжатые изображения формата WebP для замены, чтобы не замедлять загрузку.
- Безопасность: Всегда проверяйте, что пользователь залогинен, и не раскрывайте информацию о купленных товарах незарегистрированным посетителям.
- Код: Подключайте кастомный код через дочернюю тему или плагин, чтобы не потерять изменения при обновлении GeneratePress.
Сравнение способов реализации замены изображения
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Фильтры WooCommerce (как в статье) | Гибко и без сторонних плагинов, легко кастомизировать | Нужно писать код, учитывать кэширование | Если нужно полное управление выводом изображений |
| Плагины для управления изображениями или статусы товаров | Простая установка, готовые решения | Часто ограничены в кастомизации, могут нагружать сайт | Для быстрых решений без навыков программирования |
| JS-решения на фронте | Не требует серверных изменений | Менее надежно, проблемы с SEO и доступностью | Если не хочется менять PHP-код |