Удаление изображений вместе с товаром в WooCommerce
В WooCommerce многие разработчики замечают: удаляешь товар, а изображения остаются в медиабиблиотеке. Это не баг, а осознанная архитектура WordPress. В этой статье разберём:
- как связаны товары и изображения
- почему изображения не удаляются автоматически
- какие есть хуки для удаления
- готовые PHP-решения
- плагины для автоматической очистки медиатеки
Как WooCommerce хранит изображения товаров
Чтобы понять проблему, нужно разобраться в архитектуре WordPress.
1. Изображения — это отдельные записи (attachment)
В WordPress каждое изображение — это не “файл внутри товара”, а отдельный объект в базе данных:
- тип записи:
attachment - хранится в таблице
wp_posts - файл лежит в
/wp-content/uploads/
Товар (product) — это тоже запись в wp_posts, но с типом product.
Связь между ними — только через мета-поля:
_thumbnail_id— главное изображение товара_product_image_gallery— галерея (ID через запятую)
2. Важно: изображение может использоваться в разных местах
Одно изображение может быть:
- в товаре
- в записи блога
- в галерее
- в ACF-полях
- в Elementor
Поэтому WordPress НЕ удаляет его автоматически — иначе можно сломать сайт.
Почему изображения не удаляются при удалении товара
Это ключевой момент.
Причина 1: безопасность данных
Если удалить товар → удалить изображения → а они используются в другом месте → сайт ломается.
Поэтому WordPress выбирает безопасную стратегию: удаляем товар, но медиа оставляем
Причина 2: изображения не “принадлежат” товару
У товара нет “владения” файлами. Есть только ссылки (ID).
Причина 3: производительность
Автоматическая проверка “где используется файл”:
- дорогая операция
- замедляет удаление постов
- требует обхода всей базы
Причина 4: корзина (Trash)
Если товар в корзине — его можно восстановить.
Если бы изображения удалились сразу — восстановление было бы невозможным.
Как правильно удалять изображения товара
Есть несколько уровней решения.
1. Хук WooCommerce при удалении товара
Самый правильный способ — использовать хук:
add_action('before_delete_post', 'delete_woocommerce_product_images');
function delete_woocommerce_product_images($post_id) {
if (get_post_type($post_id) !== 'product') {
return;
}
$product = wc_get_product($post_id);
if (!$product) return;
// Главное изображение
$thumbnail_id = $product->get_image_id();
// Галерея
$gallery_ids = $product->get_gallery_image_ids();
$image_ids = array_merge([$thumbnail_id], $gallery_ids);
foreach ($image_ids as $image_id) {
if ($image_id) {
wp_delete_attachment($image_id, true);
}
}
}
Что делает код:
- ловит удаление товара
- получает ID изображений
- удаляет файлы + записи attachment
2. Альтернатива: хук WooCommerce
Можно использовать более “WooCommerce-специфичный” вариант:
add_action('woocommerce_delete_product', 'wc_delete_product_images');
function wc_delete_product_images($product_id) {
$product = wc_get_product($product_id);
if (!$product) return;
$images = array_merge(
[$product->get_image_id()],
$product->get_gallery_image_ids()
);
foreach ($images as $image_id) {
wp_delete_attachment($image_id, true);
}
}
3. Удаление только “неиспользуемых” изображений (умный вариант)
Если важно не сломать сайт:
function safe_delete_attachment($attachment_id) {
global $wpdb;
$used = $wpdb->get_var($wpdb->prepare("
SELECT post_id FROM $wpdb->postmeta
WHERE meta_value = %d
LIMIT 1
", $attachment_id));
if (!$used) {
wp_delete_attachment($attachment_id, true);
}
}
Удаляет только если изображение нигде не используется.
Плагины для автоматического удаления изображений
Если не хочется писать код:
1. Media Cleaner
- ищет “осиротевшие” изображения
- удаляет неиспользуемые файлы
- безопасный режим (dry run)
2. WP Bulk Delete
- массовое удаление товаров
- очистка привязанных данных
- поддержка WooCommerce
3. Advanced Database Cleaner
- чистит мета-данные
- удаляет мусорные attachment
- оптимизирует базу
Частые ошибки разработчиков
❌ Ошибка 1: удаление файла напрямую
unlink($file);
Плохо, потому что:
- остаётся запись attachment
- ломаются ссылки в базе
❌ Ошибка 2: удаление только главного изображения
Многие забывают про gallery:
$product->get_gallery_image_ids();
❌ Ошибка 3: удаление без проверки использования
Можно случайно удалить изображение, которое используется в блоге.
Как это делают крупные проекты
В больших WooCommerce-магазинах обычно:
- изображения НЕ удаляют сразу
- используют cron-очистку
- проверяют usage по всей базе
- делают “мягкое удаление” (soft delete)
Лучший практический подход
Рекомендуемая схема:
- При удалении товара — помечать изображения как “candidate for deletion”
- Через cron проверять использование
- Удалять только если нет связей
Вывод
WooCommerce не удаляет изображения автоматически по одной простой причине: изображения — это независимые сущности, которые могут использоваться в разных частях сайта.
Поэтому правильное решение зависит от проекта:
- маленький сайт → можно удалять через hook
- магазин → лучше проверка + cron
- крупный проект → система очистки медиатеки
Мы об этой фишке вордпресса узнали только после того как файловое пространство на хостинге забилось до 200 гигов, тариф стал очень дорогой, в то время как сам сайт небольшой и товаров не много. Наняли специалиста для проверки, а причина то была совсем простая, много неиспользуемых изображений, так как часто удаляли, заливали товары.
А куда писать этот код, хук?
В файл functions.php вашей темы
А вручную можно удалить?
Да, но способ не совсем безопасный. Можно зайти в раздел «Медиафайлы», отсортировать по неприкрепленным и вручную удалить. Заранее сделайте бэкап сайта. Проверьте отображение товаров. Для сайта с небольшим количеством товаров такой способ, возможно, подойдет, а вот если товаров много, то проверить все уже сложнее.
На одном моем проекте изображения в медиафайлах были неприкрепленными, хотя по факту привязаны к товарам, и при таком способе просто половина товаров осталась без картинок. Причину нашла чуть позже: неправильная работа плагина импорта, неправильная привязка фото к товару во время импорта товаров.