Сортировка статей по количеству комментариев в WordPress

Доводим до ума WP_Query::get_posts()

Начну с кода:

[-]
View Code PHP
return 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):

[-]
View Code PHP
  1. $allowed_keys = array('author', 'date', 'category', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand');
[-]
View Code PHP
  1. if ( in_array($orderby_array[$i], $allowed_keys) )
  2.     $q['orderby'] .= (($i == 0) ? '' : ',') . $orderby;
[-]
View Code PHP
  1. if ( empty($q['orderby']) )
  2.     $q['orderby'] = "$wpdb->posts.post_date ".$q['order'];

То есть если заданного поля нет в списке разрешенных полей, то оно игнорируется; если не заданы поля для сортировки (либо они были отбракованы), то сортировка производится по дате статьи.

С причинами разобрались, теперь поговорим о способах решения.

Я вижу два способа: один из них простой ("в лоб"), другой посложнее.

  1. Первый способ заключается в том, что для выборки статей используется самостоятельно сконструированный запрос: например, для примера из начала статьи он мог выглядеть так:
    [-]
    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 предпочтительнее использования прямых обращений к базе данных.
  2. Второй способ заключается в исправлении исходного кода 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 патч придётся накладывать ещё раз (если разработчики это не исправят).
Автор: ; опубликовано в: Патчи;
20
Сен
2008

RSS Комментарии к статье «Сортировка статей по количеству комментариев в WordPress» (6)  »

  1. Можно отписать разработчикам.

  2. grang

    Недостатки: при обновлении WordPress патч придётся накладывать ещё раз (если разработчики это не исправят).

    До сих пор не исправили.

  3. Евгения

    ща проверю, заранее спасибо за коды!

  4. Патч для 2.7RC1 (тестировал на nightly build):

    [-]
    Download query.php.diff
    --- query.php.orig      2008-11-24 08:14:40.000000000 +0200
    +++ 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;
                                    }
  5. Немного не вкурил, а нафига весь этот геморрой? Ты, что хочешь, чтобы у тебя вверху постоянно статьи с большим количеством комментов висели? Нафига?

Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.

Оставить комментарий к записи «Сортировка статей по количеству комментариев в WordPress»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя

गते गते पारगते पारसंगते बोधि स्वाहा