Диагностика проблемы: почему нельзя исключить товар из распродажи стандартными средствами WooCommerce
В WooCommerce встроена возможность устанавливать цену распродажи для товара, что автоматически выводит его в категорию распродажных. Однако иногда нужно, чтобы товар с установленной ценой распродажи не отображался в разделе распродаж или не участвовал в любых автоматических фильтрах по скидкам. Стандартных настроек для этого нет — WooCommerce не предусматривает исключение товаров из распродажи без удаления цены распродажи.
Проверить, что ваш товар участвует в распродажах, можно в админке: откройте карточку товара, убедитесь, что в поле Цена распродажи установлено значение. На фронтенде товар появится в категории «Распродажа» и в виджетах с акциями.
Пошаговое решение: как исключить товар из распродажи через кастомный код
1. Добавляем мета-поле для исключения товара из распродажи
В карточке товара нужно добавить чекбокс «Исключить из распродажи». Для этого используем хук woocommerce_product_options_general_product_data и сохраняем значение через woocommerce_process_product_meta.
add_action('woocommerce_product_options_general_product_data', function() {
woocommerce_wp_checkbox([
'id' => '_exclude_from_sale',
'label' => 'Исключить из распродажи',
'description' => 'Отметьте, чтобы товар не отображался в распродажах',
]);
});
add_action('woocommerce_process_product_meta', function($post_id) {
$exclude = isset($_POST['_exclude_from_sale']) ? 'yes' : 'no';
update_post_meta($post_id, '_exclude_from_sale', $exclude);
});2. Исключаем товар из списка распродаж на фронтенде
Для фильтрации товаров с распродажной ценой используем фильтр woocommerce_product_is_on_sale. В нем проверяем мета-поле и отменяем статус распродажи у такого товара.
add_filter('woocommerce_product_is_on_sale', function($on_sale, $product) {
$exclude = get_post_meta($product->get_id(), '_exclude_from_sale', true);
if ($exclude === 'yes') {
return false;
}
return $on_sale;
}, 10, 2);3. Исключаем товар из виджетов и страниц с распродажами
WooCommerce выводит распродажные товары через WP_Query с параметром 'meta_query' => [ ['key' => '_sale_price', 'value' => '', 'compare' => '!='] ]. Чтобы исключить товары с чекбоксом, добавим фильтр woocommerce_product_query_meta_query и расширим запрос.
add_filter('woocommerce_product_query_meta_query', function($meta_query, $query) {
$meta_query[] = [
'key' => '_exclude_from_sale',
'value' => 'yes',
'compare' => '!=',
];
return $meta_query;
}, 10, 2);Проверка результата после внедрения
- В админке в карточке товара появился чекбокс «Исключить из распродажи».
- Если включить этот чекбокс для товара с установленной ценой распродажи, он не должен отображаться в разделе распродаж и виджетах.
- Товар не должен попадать в автоматические фильтры и списки распродаж.
- Если снять чекбокс, товар снова появляется в распродажах.
Частые ошибки и как их исправить
- Чекбокс не сохраняется — проверьте, что в функции сохранения вы используете правильный
post_idи проверяете наличие поля в$_POST. - Товар отображается в распродажах несмотря на исключение — убедитесь, что фильтр
woocommerce_product_is_on_saleзарегистрирован с приоритетом не ниже 10 и принимает два аргумента. - Исключение не работает в кастомных запросах — если на сайте кастомные WP_Query для распродаж, добавьте дополнительную проверку для
meta_queryв этих запросах.
Практические советы по безопасности и производительности
- Используйте префиксы для своих мета-ключей, чтобы избежать конфликтов — в примере используется
_exclude_from_sale. - Не добавляйте тяжелые запросы или сложные JOIN в фильтры WP_Query — используйте мета-запросы с индексируемыми полями.
- Для массового обновления товаров используйте WP-CLI или SQL-запросы, чтобы проставить мета-значения без загрузки админки.
- Проверяйте совместимость кода с кеширующими плагинами — при необходимости применяйте очистку кеша при сохранении товара.
Сравнение способов исключения товара из распродажи
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Удаление цены распродажи | Просто убрать цену распродажи в админке | Простая реализация | Товар теряет скидку, не подходит для всех случаев |
| Кастомный чекбокс + фильтры (код из статьи) | Добавление мета-поля и фильтрация через хуки | Гибко, сохраняет цену распродажи, исключение без потерь | Требуется писать код, возможны ошибки при кастомных запросах |
| Использование плагинов | Плагины с расширенным управлением скидками и условиями | Простота для непрофессионалов, готовые настройки | Нагрузка на сайт, платные решения, не всегда подходят для кастомных задач |