Сортировка статей по количеству комментариев в WordPress
Доводим до ума WP_Query::get_posts()
Начну с кода:
array(
"numberposts" => 10,
"orderby" => "comment_count",
"post_status" => "publish",
"order" => "DESC",
)
);
Не работает! В смысле работает, но не так, как того хочется: возвращаемые данные не сортируются по количеству комментариев (сортировка производится по дате публикации). Сразу возникает вопрос: почему? Ведь поле comment_count присутствует в таблице wp_posts. Как оказалось, всё не так просто.
Причина кроется в методе WP_Query::get_posts(). Если не вдаваться в глубокие подробности, данный метод формирует SQL-запрос для получения данных по критериям, заданным в параметрах функции get_posts() либо метода WP_Query::query().
Теперь переходим к вопросу, почему оно не работает. Всё дело в том, что в методе WP_Query::get_posts() жёстко заданы поля, по которым может осуществляться сортировка. В случае WordPress 2.6.2 эти ограничения заданы так (файл wp-includes/query.php):
- $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand');
- if ( in_array($orderby_array[$i], $allowed_keys) )
- $q['orderby'] .= (($i == 0) ? '' : ',') . $orderby;
- if ( empty($q['orderby']) )
- $q['orderby'] = "$wpdb->posts.post_date ".$q['order'];
То есть если заданного поля нет в списке разрешенных полей, то оно игнорируется; если не заданы поля для сортировки (либо они были отбракованы), то сортировка производится по дате статьи.
С причинами разобрались, теперь поговорим о способах решения.
Я вижу два способа: один из них простой ("в лоб"), другой посложнее.
- Первый способ заключается в том, что для выборки статей используется самостоятельно сконструированный запрос: например, для примера из начала статьи он мог выглядеть так:
[-]View Code MySQLДостоинства: простота (но только в случае простых запросов).SELECT *
FROM `wp_posts`
WHERE
`post_status` = 'publish' AND
`post_type` = 'post'
ORDER BY `comment_count` DESC
LIMIT 10
Недостатки: некоторые плагины (например, Disclose Secret) имеют тенденцию переписывать запросы (путём установки обработчиков фильтровposts_where_request,posts_join_requestи т.п.). Подобный "грязный хак" плагинами замечен не будет (в результате они не отфильтруют результаты). Помимо этого, использование API предпочтительнее использования прямых обращений к базе данных. - Второй способ заключается в исправлении исходного кода WordPress (путём наложения магического патча).
А вот и магический патч (кастовать на
wp-includes/query.php):
Для версии WordPress 2.6.2:[-]Download query.php.diff--- query.php.orig 2008-09-01 20:01:47.000000000 +0300
+++ query.php 2008-09-20 01:04:30.000000000 +0300
@@ -1256,7 +1256,7 @@
$q['orderby'] = "$wpdb->posts.post_date ".$q['order'];
} else {
// Used to filter values
- $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand');
+ $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'comment_count', 'rand');
$q['orderby'] = urldecode($q['orderby']);
$q['orderby'] = addslashes_gpc($q['orderby']);
$orderby_array = explode(' ',$q['orderby']);
@@ -1275,6 +1275,9 @@
case 'rand':
$orderby = 'RAND()';
break;
+ case 'comment_count':
+ $orderby = "$wpdb->posts.comment_count";
+ break;
default:
$orderby = "$wpdb->posts.post_" . $orderby;
}Для версии WordPress 2.5.1:
[-]Download query.php.diffДостоинства: не нарушает работу сторонних плагинов.--- query.php.orig 2008-07-13 20:32:40.000000000 +0300
+++ query.php 2008-09-20 01:12:29.000000000 +0300
@@ -1238,7 +1238,7 @@
$q['orderby'] = "$wpdb->posts.post_date ".$q['order'];
} else {
// Used to filter values
- $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand');
+ $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'comment_count', 'rand');
$q['orderby'] = urldecode($q['orderby']);
$q['orderby'] = addslashes_gpc($q['orderby']);
$orderby_array = explode(' ',$q['orderby']);
@@ -1257,6 +1257,9 @@
case 'rand':
$orderby = 'RAND()';
break;
+ case 'comment_count':
+ $orderby = "$wpdb->posts.comment_count";
+ break;
default:
$orderby = "$wpdb->posts.post_" . $orderby;
}
Недостатки: при обновлении WordPress патч придётся накладывать ещё раз (если разработчики это не исправят).
Сен
2008
Комментарии к статье «Сортировка статей по количеству комментариев в WordPress» (6) »
Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.
Оставить комментарий к записи «Сортировка статей по количеству комментариев в WordPress»
गते गते पारगते पारसंगते बोधि स्वाहा
Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.


Можно отписать разработчикам.
Недостатки: при обновлении WordPress патч придётся накладывать ещё раз (если разработчики это не исправят).
До сих пор не исправили.
ща проверю, заранее спасибо за коды!
Патч для 2.7RC1 (тестировал на nightly build):
+++ query.php 2008-12-04 14:04:04.000000000 +0200
@@ -2023,7 +2023,7 @@
$q['orderby'] = "$wpdb->posts.post_date ".$q['order'];
} else {
// Used to filter values
- $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand');
+ $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'comment_count', 'rand');
if ( !empty($q['meta_key']) ) {
$allowed_keys[] = $q['meta_key'];
$allowed_keys[] = 'meta_value';
@@ -2050,6 +2050,9 @@
case 'meta_value':
$orderby = "$wpdb->postmeta.meta_value";
break;
+ case 'comment_count':
+ $orderby = "$wpdb->posts.comment_count";
+ break;
default:
$orderby = "$wpdb->posts.post_" . $orderby;
}
Немного не вкурил, а нафига весь этот геморрой? Ты, что хочешь, чтобы у тебя вверху постоянно статьи с большим количеством комментов висели? Нафига?
Хреновая трава… Например, для получения списка самых обсуждаемых статей в виджете.