Диагностика проблемы: зачем запрещать удаление товаров после продажи
В WooCommerce администраторы и менеджеры магазина иногда случайно удаляют товары, которые уже были куплены клиентами. Это приводит к потере данных о заказах и неправильному отображению истории покупок. Удаление товаров, которые участвовали в заказах, негативно сказывается на бухгалтерии, отчетах и пользовательском опыте.
Чтобы избежать таких ошибок, необходимо запретить удаление продуктов, если для них есть связанные заказы со статусом completed или processing. В противном случае администратор мог бы случайно удалить товар, нарушив целостность данных.
Пошаговое решение: блокируем удаление товаров с покупками через хук
WooCommerce хранит информацию о заказах в таблицах с мета-данными. Чтобы проверить, был ли товар куплен, нужно найти заказы, где этот товар присутствует. Мы запретим удаление такого товара на уровне админки, используя хук before_delete_post.
1. Добавление проверки в functions.php или в кастомный плагин
add_action('before_delete_post', 'wp3_prevent_product_deletion_if_purchased', 10, 1);
function wp3_prevent_product_deletion_if_purchased($post_id) {
// Проверяем, что это продукт WooCommerce
if (get_post_type($post_id) !== 'product') {
return;
}
global $wpdb;
// Ищем заказы, где есть этот товар
$query = $wpdb->prepare(
"SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items AS items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS itemmeta ON items.order_item_id = itemmeta.order_item_id
INNER JOIN {$wpdb->prefix}posts AS posts ON posts.ID = items.order_id
WHERE itemmeta.meta_key = '_product_id' AND itemmeta.meta_value = %d
AND posts.post_type = 'shop_order'
AND posts.post_status IN ('wc-completed', 'wc-processing')
LIMIT 1",
$post_id
);
$order_id = $wpdb->get_var($query);
if ($order_id) {
wp_die(__('Удаление товара невозможно: он уже был куплен в одном или нескольких заказах.', 'wp3'));
}
}2. Отладка и проверка
После добавления кода попробуйте удалить товар, который был куплен (создайте тестовый заказ с этим товаром). Админка должна вывести ошибку и запретить удаление. Для товаров без заказов удаление останется доступным.
Проверка результата после внедрения
- Создайте тестовый товар.
- Оформите заказ с этим товаром и переведите статус заказа в
completed. - Попытайтесь удалить этот товар в админке WooCommerce.
- Убедитесь, что появляется сообщение об ошибке и удаление не происходит.
- Создайте новый товар без заказов и проверьте, что его можно удалить без ошибок.
Частые ошибки и как их исправить
- Ошибка «функция wp_die не срабатывает»: убедитесь, что хук
before_delete_postправильно добавлен и не переопределяется другими плагинами. - Нет проверки статуса заказа: если не фильтровать статусы заказов, можно случайно заблокировать удаление товаров, которые только в черновиках заказов. В коде это учтено.
- Проблемы с производительностью: на больших магазинах запрос к базе может быть медленным. Для оптимизации можно добавить дополнительный индекс в таблицы WooCommerce или кэшировать результаты.
Практические советы по безопасности и производительности
- Регулярно создавайте резервные копии базы данных перед внесением изменений в функционал.
- Добавляйте индексы по полям
meta_keyиmeta_valueв таблицеwoocommerce_order_itemmetaдля ускорения запросов. - Для больших сайтов рассмотрите перенос проверки удаления в AJAX-запрос с кэшированием результата.
- Если у вас много заказов, используйте WP-CLI для периодической проверки целостности данных и выявления товаров с заказами.
Альтернативные варианты: плагин или код?
| Способ | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| Код в functions.php | Легко контролировать, бесплатно, быстро внедряется | Может конфликтовать с другими плагинами, требует навыков | Добавить логирование ошибок для отладки |
| Плагин блокировки удаления | Готовое решение, поддержка, настройки | Может нагружать сайт, ограниченная гибкость | Выбирать проверенный плагин с хорошими отзывами |
| Комбинация (код + плагин) | Оптимальное управление и безопасность | Сложнее поддерживать | Использовать плагин для UI и код для бизнес-логики |