Блог Михаила Крамера. PHP и JS

Вывод соседних записей рубрики

Итак, заказчиком поставлена была следующая задача: выводить к каждой записи 4 её "соседей" - ближайшие записи, созданные раньше и позже пользователем. Типа это улучшит индексацию сайта, и создаст дополнительное удобство пользователям. Причём, записи по возможности надо выводить - 2 добавленные ранее, и две добавленные после, чтоб название текущей оказалось в середине. Ну что просили, то мы и сделали


<?php
function neighbor_posts($post_id) {
    global $wpdb;

    // Нам нужна категория поста. Если у поста несколько категорий, будет взята первая
    // Решение делалось под конкретное задание, посему универсальностью не обладает
    $category = get_the_category($post_id);
    $cat_id = $category[0]->cat_ID;

    // Узнаём сколько записей добавлено до
    $all_left_num = $wpdb->get_var("select count($wpdb->posts.ID) from $wpdb->posts join $wpdb->term_relationships on  " .
                           "($wpdb->term_relationships.object_id = $wpdb->posts.ID) where ($wpdb->posts.ID < $post_id) " .
                           "and ($wpdb->term_relationships.term_taxonomy_id = $cat_id) and ($wpdb->posts.post_status='publish')");
    // А сколько после
    $all_right_num = $wpdb->get_var("select count($wpdb->posts.ID) from $wpdb->posts join $wpdb->term_relationships on  " .
                           "($wpdb->term_relationships.object_id = $wpdb->posts.ID) where ($wpdb->posts.ID > $post_id) " .
                           "and ($wpdb->term_relationships.term_taxonomy_id = $cat_id) and($wpdb->posts.post_status='publish')");

    $num_left = $num_right = 2; // Нам нужно по две записи с каждой стороны от нашей

    // Но всего должно получиться 5 (вместе с текущей), поэтому
    if ($all_left_num < 2) // Если слева нет 2 записей, компенсируем правыми
        $num_right += (2 - $all_left_num);
    if ($all_right_num < 2) // Если справа нет записей, компенсируем левыми
        $num_left += (2 - $all_right_num);

    // Теперь можно запросить сами записи. Для левых (предыдущих) задаём сортировку по ID по убыванию
    // Таким образом гарантируем, что это будут именно ближайшие записи
    $left = $wpdb->get_results("select $wpdb->posts.* from $wpdb->posts join $wpdb->term_relationships on  " .
                           "($wpdb->term_relationships.object_id = $wpdb->posts.ID) where ($wpdb->posts.ID < $post_id) " .
                           "and ($wpdb->term_relationships.term_taxonomy_id = $cat_id) and ($wpdb->posts.post_status='publish') " .
                           "order by $wpdb->posts.ID desc limit $num_left");

    // Для правых сортировку можно было не задавать, но так, по образу и подобию 
    $right = $wpdb->get_results("select $wpdb->posts.* from $wpdb->posts join $wpdb->term_relationships on  " .
                           "($wpdb->term_relationships.object_id = $wpdb->posts.ID) where ($wpdb->posts.ID > $post_id) " .
                           "and ($wpdb->term_relationships.term_taxonomy_id = $cat_id) and($wpdb->posts.post_status='publish') " .
                           "order by $wpdb->posts.ID asc limit $num_right");
    // здесь будут все посты, заголовки которых нам надо отобразить
    $posts = array ();

    // Левые отсортированы по убыванию, поэтому добавляем каждый следующий в начало $posts
    // Таким образом в $posts они будут отсортированы по возрастанию
    foreach ($left as $post)
        array_unshift($posts, $post);

    $posts[] = get_post($post_id);

    foreach ($right as $post)
        $posts[] = $post;

    // Выводим ссылки на всю эту фигню
    echo "<ul class='neighbor'>";
    foreach ($posts as $post) {
        echo "<li>";
        if ($post->ID != $post_id)
            echo sprintf("<a href='%s'>%s</a>", get_permalink($post->ID), $post->post_title);
        else
            echo $post->post_title;
        echo "</li>";
    }
    echo "</ul>";
}

Важное замечание

От нескольких читателей блога поступил вопрос, что код "не работает". Для тех, кто не знает, объясняю: код функции следует поместить в файл functions.php темы, а из шаблона поста single.php вызывать, передав ID текущего поста!

Ваш комментарий
Комментарии