Удаление комментариев вместе с ответами в WordPress
В этой статье мы рассмотрим, как удалить все дочерние комментарии, когда удаляется родительский комментарий. Это значит, что когда вы удаляете комментарий, все его ответные комментарии также удаляются, и так далее по цепочке. По сути, вместе с основным комментарием удаляется вся ветка ответов на него.
Как реализовать удаление ветки комментариев
Чтобы данная функция работала, добавьте код в файл functions.php
вашей темы.
/**
* Удаление всех дочерних комментариев (всего дерева) при удалении комментария
*/
add_action( 'delete_comment', 'del_child_comments_on_del_comment' );
function del_child_comments_on_del_comment( $comment_id ) {
global $wpdb;
$child_comments = $wpdb->get_col(
"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
);
// Если дочерних комментариев нет, выходим из функции
if( ! $child_comments ){
return;
}
foreach( $child_comments as $val ){
wp_delete_comment( $val );
}
}
Ключевые моменты
Данная функция использует два важных элемента:
- Хук:
delete_comment
- Функция:
wp_delete_comment()
Я потратил довольно много времени на написание этого кода, поскольку он использует рекурсию, которая может быть довольно запутанной.
Что такое рекурсия?
Рекурсия — это процесс, при котором функция вызывает саму себя (простая рекурсия) или через другие функции (сложная рекурсия). Например, функция A вызывает функцию B, а функция B вызывает функцию A. Глубина рекурсии — это количество вложенных вызовов функций.
В начале я пытался использовать рекурсию напрямую, но это не сработало. Код только увеличивался в размерах. В какой-то момент, когда готовил себе чай, меня осенило: закрытие происходит, когда срабатывает хук delete_comment
во время последующих вызовов функции wp_delete_comment()
. Не нужно вызывать функцию внутри самой себя в привычном виде, т.е. будет использована косвенная рекурсия.
Честно говоря, я не могу представить реальную ситуацию в обычном блоге, когда такое удаление комментариев было бы особенно необходимо. Однако это логично и может пригодиться. Лично я предпочел реализовать это так, чтобы при удалении комментария с дочерними комментариями не терялся их смысл. Иначе получится, что будут комментарии без контекста.
Перемещение в корзину
После решения задачи с удалением комментариев, я также добавил функцию для перемещения комментариев в корзину и восстановления их оттуда с той же логикой.
Принцип тот же, только теперь используются фильтры:
trash_comment
— перемещение в корзинуuntrash_comment
— восстановление из корзины
И соответствующие функции:
/**
* Перемещение всех дочерних комментариев в корзину (всё дерево) при удалении комментария
*/
add_action( 'trash_comment', 'trash_child_comments_on_trash_comment' );
function trash_child_comments_on_trash_comment( $comment_id ) {
global $wpdb;
// Если дочерних комментариев нет, выходим из функции
$child_comments = $wpdb->get_col(
"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
);
if( ! $child_comments ){
return;
}
foreach( $child_comments as $val ){
wp_trash_comment( $val );
}
}
add_action( 'untrash_comment', 'untrash_child_comments_on_untrash_comment' );
function untrash_child_comments_on_untrash_comment( $comment_id ) {
global $wpdb;
// Если дочерних комментариев нет, выходим из функции
$child_comments = $wpdb->get_col(
"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
);
if( ! $child_comments ){
return;
}
foreach( $child_comments as $val ){
wp_untrash_comment( $val );
}
}
Упрощенный код для перемещения в корзину
Вот очень интересный код для тех, кто понимает PHP: упрощенная версия вышеуказанного кода. Здесь интересно, как можно использовать функцию current_filter()
и необычный динамический вызов функции в PHP с помощью переменной $use_function( $val )
. В общем, посмотрите сами:
/**
* Перемещение всех дочерних комментариев в корзину (всё дерево) при удалении комментария
*/
add_action( 'trash_comment', 'trash_untrash_child_comments_with_parent' );
add_action( 'untrash_comment', 'trash_untrash_child_comments_with_parent' );
function trash_untrash_child_comments_with_parent( $comment_id ) {
global $wpdb;
// Если дочерних комментариев нет, выходим из функции
$child_comments = $wpdb->get_col(
"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
);
if( ! $child_comments ){
return;
}
foreach( $child_comments as $val ){
// Получаем wp_trash_comment или wp_untrash_comment
$use_function = 'wp_' . current_filter();
$use_function( $val );
}
}
Теперь вы знаете, как управлять комментариями и их дочерними элементами в WordPress. Эти простые функции помогут вам поддерживать порядок в комментариях на вашем сайте.