Диагностика проблемы: зачем удалять товары с нулевым остатком
В интернет-магазинах на WooCommerce часто появляется необходимость автоматически удалять товары, у которых закончился запас (остаток равен нулю), чтобы не показывать их покупателям и не усложнять каталог. Особенно актуально для магазинов с большим ассортиментом и частыми изменениями наличия.
Проверить наличие товаров с нулевым остатком можно через админ-панель WooCommerce или базу данных, запросом:
SELECT ID, post_title FROM wp_posts
JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_postmeta.meta_key = '_stock' AND wp_postmeta.meta_value = '0' AND post_type = 'product' AND post_status = 'publish';
Пошаговое решение: автоматическое удаление товаров с нулевым остатком с помощью кода
1. Создаем функцию для удаления товаров с нулевым остатком
Добавьте следующий код в файл functions.php вашей дочерней темы или в отдельный плагин:
function wp_puzzle_delete_zero_stock_products() {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_stock',
'value' => '0',
'compare' => '=',
'type' => 'NUMERIC'
),
),
'post_status' => 'publish',
'fields' => 'ids',
);
$products = get_posts($args);
if (!empty($products)) {
foreach ($products as $product_id) {
wp_trash_post($product_id); // перемещаем товар в корзину
// Если нужно удалить полностью, использовать wp_delete_post($product_id, true);
}
}
}
2. Запускаем функцию по расписанию с WP-Cron
Чтобы не запускать вручную, добавим задачу по расписанию, например, ежедневно:
if (!wp_next_scheduled('wp_puzzle_daily_delete_zero_stock')) {
wp_schedule_event(time(), 'daily', 'wp_puzzle_daily_delete_zero_stock');
}
add_action('wp_puzzle_daily_delete_zero_stock', 'wp_puzzle_delete_zero_stock_products');
3. Очистка запланированных задач при деактивации
function wp_puzzle_deactivate() {
$timestamp = wp_next_scheduled('wp_puzzle_daily_delete_zero_stock');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wp_puzzle_daily_delete_zero_stock');
}
}
register_deactivation_hook(__FILE__, 'wp_puzzle_deactivate');
Проверка результата после внедрения
- Запустите функцию вручную из админки (через временный вызов) или дождитесь выполнения WP-Cron.
- Проверьте, что товары с остатком 0 были перемещены в корзину (Trash) или удалены.
- В базе данных в таблице
wp_postsдля этих товаров должен измениться статус наtrash(если используетсяwp_trash_post). - Проверьте, что товары больше не отображаются в каталоге и поиске.
Частые ошибки и как их исправить
- Функция не запускается по расписанию
Проверьте, активен ли WP-Cron и заходите на сайт регулярно, т.к. WP-Cron запускается при посещении.
Для теста можно вызвать функцию вручную. - Товары не удаляются
Убедитесь, что мета-ключ_stockдействительно содержит числовое значение и товары публикуются.
Проверьте, нет ли конфликтов с другими плагинами, блокирующими удаление. - Некорректная работа с вариациями товаров
Если у вас вариативные товары, то остаток указывается у вариаций. Для них нужно расширить запрос, чтобы удалять товары с нулевым остатком на уровне вариаций.
Практические советы по безопасности и производительности
- Используйте
wp_trash_post, чтобы можно было восстановить товары при ошибке, вместо полного удаления. - Для крупных магазинов с тысячами товаров рекомендуем разбивать процесс удаления на батчи, чтобы не превышать лимит памяти и времени выполнения.
- Регулярно создавайте резервные копии базы данных перед массовым удалением.
- Для вариативных товаров расширьте логику, проверяя остатки на уровне вариаций (meta_key:
_stockуproduct_variation). - Для контроля логируйте ID удаляемых товаров в отдельный файл или базу, чтобы отслеживать изменения.
Сравнение вариантов реализации
| Метод | Преимущества | Недостатки |
|---|---|---|
| Плагин (например, WP All Import + фильтры) | Простота, готовый интерфейс, поддержка | Платный, нагрузка, ограниченная кастомизация |
| Собственный код с WP-Cron | Полный контроль, бесплатный, легко интегрируется | Требует навыков, возможны баги без тестирования |
| Удаление вручную через админку | Простота, без кода | Трудоемко, не подходит для большого каталога |