comments_clauses хук-фильтр . WP 3.1.0

Click here to view original web page at wp-kama.ru

Позволяет изменить sql подзапросы (fields, join, where, orderby, limits, groupby) при выборке комментариев функцией get_comments().

Использование

add_filter( 'comments_clauses', 'filter_function_name_3910', 10, 2 );
function filter_function_name_3910( $pieces, $query ){
	// Изменяем...

	return $pieces;
}
$pieces(string[])
Ассоциативный массив с sql подзапросами типа fields, join, where, orderby, limits, groupby и так далее.
Текущий объект класса WP_Comment_Query. Классы в php передаётся по ссылке.

Примеры

#1 Пример данных в фильтре

В консоли админки в метабоксе "На виду" срабатывает функция wp_dashboard_site_activity(), которая в свою очередь использует функцию wp_dashboard_recent_comments() и в последующем get_comments() для вывода последних комментариев в метабоксе. Под администратором код запроса выглядит следующим образом:

$comments_query = array(
	'number' => 25,
	'offset' => 0,
);

get_comments( $comments_query )

Посмотрим, какие данных проходят через фильтр с помощью дебага WordPress:

add_filter( 'comments_clauses', function ( $args ) {
	error_log( print_r( $args, true ) );

	return $args;
} );

Получим

Array
(
	[fields] => wp_comments.comment_ID
	[join] =>
	[where] => ( ( comment_approved = '0' OR comment_approved = '1' ) )
	[orderby] => wp_comments.comment_date_gmt DESC
	[limits] => LIMIT 0,25
	[groupby] =>
)

#2 wpDiscuz: сортировка по популярным комментариям на основе данных WP Recall

В данном кейсе используются плагины wpDiscuz и WP Recall, которые дают возможность оценивать комментарии (лайкать). Так как комментарии выводит wpDiscuz, то и сортировку он делает на основе своих данных, хранящихся в метаполях под ключом wpdiscuz_votes. На сайте используется личный кабинет на основе WP Recall и оценивая комментарии через него, пользователь получает карму, на основе которой можно делать всякие плюшки.

Задача: оставить лайки от WP Recall, убрать лайки от wpDiscuz, но оставить возможность сортировать комментарии по популярности.

Данную задачу можно решить двумя способами

Дублирование данных

Можно копировать данных из таблицы {$wpdb->prefix}rcl_rating_totals плагина WP Recall в метаданные для wpDiscuz. Это можно делать по крону или на событии оценки комментария. Рабочий способ, но так мы способствуем росту базы данных, да и выборки по метаполям как известно не отличаются быстродействием.

Подмена запроса

Что если выборку по метаполям заменить на выборку по таблице WP Recall? Плагин wpDiscuz скуп на собственные фильтры, вмешаться тут не выйдет, но благодаря системному фильтру comments_clauses мы можем это сделать!

Посмотрим какие в оригинале данные проходят через фильтр:

add_filter( 'comments_clauses', function ( $args ) {
	error_log( print_r( $args, true ) );

	return $args;
} );

// Получим следующее (оставил только то, что относится к wpDiscuz)
Array
(
	[fields] => kw_comments.comment_ID
	[join] =>  LEFT JOIN kw_commentmeta AS `cm` ON kw_comments.comment_ID = `cm`.comment_id  AND (`cm`.meta_key = 'wpdiscuz_votes')
	[where] => ( ( comment_approved = '0' OR comment_approved = '1' ) ) AND comment_post_ID = 93644 AND comment_type NOT IN ('wpdiscuz_sticky') AND comment_parent = 0
	[orderby] =>  IFNULL(`cm`.meta_value,0)+0 DESC, kw_comments.`comment_ID` asc
	[limits] => LIMIT 0,51
	[groupby] =>
	[caller] => wpdiscuz-
)

Array
(
	[fields] => kw_comments.comment_ID
	[join] =>  LEFT JOIN kw_commentmeta AS `cm` ON kw_comments.comment_ID = `cm`.comment_id  AND (`cm`.meta_key = 'wpdiscuz_votes')
	[where] => ( ( comment_approved = '0' OR comment_approved = '1' ) ) AND comment_post_ID = 93644 AND comment_type IN ('wpdiscuz_sticky') AND comment_parent = 0
	[orderby] =>  IFNULL(`cm`.meta_value,0)+0 DESC, kw_comments.`comment_ID` asc
	[limits] =>
	[groupby] =>
	[caller] => wpdiscuz-
)

Увидя паттерн, можно изменить запрос на следующий:

add_filter( 'comments_clauses', function ( $args ) {
	global $wpdb;

	$is_wpdiscuz = isset( $args['caller'] ) && $args['caller'] === 'wpdiscuz-';

	if ( $is_wpdiscuz && strpos( $args['join'], 'wpdiscuz_votes' ) !== false ) {
		$args['join']    = "LEFT JOIN {$wpdb->prefix}rcl_rating_totals AS `cm` ON $wpdb->comments.comment_ID = `cm`.object_id";
		$args['orderby'] = str_replace( 'meta_value', 'rating_total', $args['orderby'] );
	}

	return $args;
}, 11 );

// Получим
Array
(
	[fields] => kw_comments.comment_ID
	[join] => LEFT JOIN kw_rcl_rating_totals AS `cm` ON kw_comments.comment_ID = `cm`.object_id
	[where] => ( ( comment_approved = '0' OR comment_approved = '1' ) ) AND comment_post_ID = 93644 AND comment_type NOT IN ('wpdiscuz_sticky') AND comment_parent = 0
	[orderby] =>  IFNULL(`cm`.rating_total,0)+0 DESC, kw_comments.`comment_ID` asc
	[limits] => LIMIT 0,51
	[groupby] =>
	[caller] => wpdiscuz-
)

Array
(
	[fields] => kw_comments.comment_ID
	[join] => LEFT JOIN kw_rcl_rating_totals AS `cm` ON kw_comments.comment_ID = `cm`.object_id
	[where] => ( ( comment_approved = '0' OR comment_approved = '1' ) ) AND comment_post_ID = 93644 AND comment_type IN ('wpdiscuz_sticky') AND comment_parent = 0
	[orderby] =>  IFNULL(`cm`.rating_total,0)+0 DESC, kw_comments.`comment_ID` asc
	[limits] =>
	[groupby] =>
	[caller] => wpdiscuz-
)

Заметьте, я использовал в коде несколько уточнений, чтобы он применился только в нужном месте, так как фильтр comments_clauses является системным и срабатывает всегда при вызове функции get_comments().

Список изменений

Где вызывается хук

Где используется хук в ядре WordPress

Использование не найдено.