Замена виджету WordPress для вывода последних записей или замена сложного кода для выборки последних записей
Выборка последних записей в WordPress производится не лучшим образом, а именно выбираются все значения строки в таблице wp_posts для каждой записи, хотя необходимо взять всего несколько значений. Так же, если выводить последние записи через виджет, то их практически невозможно настроить, а иногда это нужно.
Я к виджетам отношусь очень негативно - они ограничены, поэтому, по возможности вообще не использую виджеты, даже когда делаю что-нибудь на заказ.
На основе вышеизложенного предлагаю вашему вниманию, еще одну функцию - Вывод последних записей в WordPress. С её помощью можно более гибко настроить вывод, если вы хоть немного разбираетесь в хтмл и css. Так же, можно использовать эту функцию в любых местах шаблона. Напрмер, предположим, нам нужно вывести список последних записей из какой-либо категории на главной странице или наоборот, вывести список последних записей из всех категорий, кроме некоторых. Для этих целей эта функция подойдет как-нельзя лучше, потому что обычно, для этого используется функция WordPress get_posts(), или вывод оформляется через query_posts(), с последующим оформлением формата вывода, через foreach (получается громоздкий код).
Использование функции - последние записи в WordPress
Вставляем нижеследующую функцию в файл темы functions.php или в файл где, мы будем выводить последние записи (например, sidebar.php)
/** Последние записи
------------------------------------------------------
$post_num (5) = количество ссылок
$format ('') = {avatar} {author}: {date:j.M.Y} - {a}{title}{/a} ({comments})
$cat ('') = Категории из которых нужно выводить (5,15) или которые нужно исключить (-5,-15), через запятую (одновременно включение и исключение не работает (не имеет смысла) )
$list_tag (li) = Тег списка
*/
function kama_recent_posts ($post_num=5, $format='', $cat='', $list_tag='li', $echo=true){
global $post, $wpdb;
$cur_postID = $post->ID;
// исключим посты главного запроса (wp_query)
foreach( $GLOBALS['wp_query']->posts as $post )
$IDs .= $post->ID .',';
$AND_NOT_IN = ' AND p.ID NOT IN ('. rtrim($IDs, ',') .')';
if ($cat){
$JOIN = "LEFT JOIN $wpdb->term_relationships rel ON ( p.ID = rel.object_id )
LEFT JOIN $wpdb->term_taxonomy tax ON ( tax.term_taxonomy_id = rel.term_taxonomy_id ) ";
$DISTINCT = "DISTINCT";
$AND_taxonomy = "AND tax.taxonomy = 'category'";
$AND_category = "AND tax.term_id IN ($cat)";
//Проверка на исключение категорий
if( strpos($cat, '-')!==false )
$AND_category = 'AND tax.term_id NOT IN ('. str_replace( '-','', $cat ) .')';
}
//если нужно показать автора
if( strpos($format, '{author}')!==false ){
$JOIN .= " LEFT JOIN $wpdb->users u ON ( p.post_author = u.ID )";
$SEL = ", u.user_nicename AS author, u.user_email, u.user_url";
//если нужно показать аватар (gavatar)
if( strpos($format, '{avatar}')!==false )
$av = "<img src='http://www.gravatar.com/avatar/%1\$s?s=25' alt='' />";
}
$sql = "SELECT $DISTINCT p.ID, post_title, post_date, comment_count, guid $SEL
FROM $wpdb->posts p $JOIN
WHERE post_type = 'post' AND post_status = 'publish' $AND_category $AND_taxonomy $AND_NOT_IN
ORDER BY post_date DESC LIMIT $post_num";
$results = $wpdb->get_results($sql);
if (!$results)
return false;
preg_match ('@\{date:(.*?)\}@', $format, $date_m);
foreach ($results as $pst){
$x == 'li1' ? $x = 'li2' : $x = 'li1';
if ( $pst->ID == $cur_postID ) $x .= " current-item";
$Title = $pst->post_title;
$a = "<a href='". get_permalink($pst->ID) ."' title='{$Title}'>";
if ($format){
$avatar = $av ? sprintf( $av, md5($pst->user_email) ) : '';
$date = apply_filters('the_time', mysql2date($date_m[1], $pst->post_date));
$Sformat = str_replace ($date_m[0], $date, $format);
$Sformat = str_replace(
array('{title}', '{a}', '{/a}', '{author}', '{comments}', '{avatar}'),
array( $Title, $a, '</a>', $pst->author, $pst->comment_count, $avatar ),
$Sformat
);
}
else $Sformat = "$a$Title</a>";
$out .= "\n<$list_tag class='$x'>{$Sformat}</$list_tag>";
}
if ($echo)
return print $out;
return $out;
}
Там, где нужно вывести последние записи, вызываем функцию используя, следующий код:
<ul> <?php kama_recent_posts (5); ?> </ul> // где, 5 это количество выводимых записей.
Дополнительные возможности функции
- Можно настроить формат вывода (формат передается во втором параметре $format = '');
- Можно, исключить или наоборот, включить какие-либо категории;
- Можно изменить тег списка (вместо
liсписка использовать, например,div).
Для настройки формата вывода используйте:
- {comments} - покажет колличество комментариев у статьи;
- {title} - заголовок статьи;
- {date:j.M.Y} - дата в формате j.M.Y (11.Апр.2010);
- {a} и {/a} - тег ссылки. Открывается и закрывается.
Вызов будет таким:
<ul>
<?php kama_recent_posts (5, '{a}{title}{/a} ← {date:j.M.Y} // {comments}'); ?>
</ul>
// выведет список в формате - <li class='li1'><a href='http://ссылка' title='Заголовок статьи'>Заголовок статьи</a> ← дата // количество комментариев</li>
Пример исключения или включения каких-либо категорий:
Для исключения категорий в третьем параметре передаем ID категорий через запятую, со знаком "минус" (пример: -5,-15,-20)
Для вывода записей только из указанных категорий (включения категорий) передаем в третьем параметре ID категорий через запятую (пример: 5,15,20)
<ul>
<?php kama_recent_posts (5, '', '5,15,20'); ?>
</ul>
// выведет список последних записей только из категорий, ID которых равны 5, 15 или 20
<ul>
<?php kama_recent_posts (5, '', '-5,-15,-20'); ?>
</ul>
// выведет список последний записей из всех категорий, кроме 5, 15 или 20
Так же, как и обычно в функциях WordPress, к тегу li добавляется сласс current-item (<li class='li1 current-item'></li>), если ID просматриваемой записи равен ID записи из списка, т.е. если мы просматривает одну из записей, находящихся в списке. Используя этот класс, можно визуально выделить запись в списке, через css.
- Предыдущие записи
- Мой метод избавления от спама в комментариях, для WordPress ← 10 Май 2010 // 12
- Как запустить обработку формы используя JavaScript ← 10 Май 2010 // 4
- Файл шаблона functions.php в WordPress ← 6 Октябрь 2010 // 15
Ребята подскажите. Есть основной сайт на WP. Но хочу сделать так чтоб при заходе на сайт подгружалась страница навигации, т.е. на сам сайт на wp а просто index.html, где будут блоки и др. информация.
Встал вопрос. Каким образом подключить блок последних новостей в количестве 5 штук в блок в этот самый index.html
Пример чего хочу на этом сайте http://dance4life.focus-media.ru/ в левой колонке. Вот таким видом.
Плиз очень нужно. Подкиньте идейку)))))
Вам нужно в папку с темой добавить файл home.php (кодировку не забудьте поставить utf-8 with BOM)
потом в этот файл вставите код из index.php ну и вместо стандартного loop'a напишите туда функцию)
я для этого пользуюсь циклом WP get_post помоему меньше строк нужно писать, да и проще)
Здравствуйте, Тимур. Вопрос у меня такой:
Как можно исключить отображение в скрипте постов, которые уже отображаются на странице стандартным выводом? То есть, на главной последние посты отображаются и в сайдбаре с помощью вашего скрипта тоже. Как избежать дублей?
ЗЫ код сайдбара идет раньше.
Собрать ID постов, которые отображаются раньше и исключить их из кода, что позже. Как это будет выглядеть в коде - зависит от конкретного кода... Точнее сказать не могу.
Ну это необходимо будет делать после каждой новой записи...Так, чтоб автоматизировать этот процесс - нельзя?
Конечно нет! В коде автоматом собирать надо в массив ID первого цикла, и в других циклах вывода исключать эти собранные ID. Я не предлагал указывать ID постов числами, вы что...
Я неправильно понял, значит. Ну если на конкретном примере взять. Как решить поставленную задачу если код примерно таков (без лишего):
<?php get_sidebar() ?> <?php if( have_posts() ){ while( have_posts() ){ the_post(); ?> <div <?php post_class(); ?> id="post-<?php the_ID(); ?>"> <h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1> <?php the_content(); ?> </div> <?php } <div class="navigation"> <div class="next-posts"><?php next_posts_link(); ?></div> <div class="prev-posts"><?php previous_posts_link(); ?></div> </div> <?php } else echo "<h2>Записей нет.</h2>";То есть, вначале идет сайдбар(слева), в котором подключен ваш скрипт, далее - обычный цикл(справа). Главная сложность, помимо исключения дублей, думаю, в том, что исключать необходимо сначала в сайдбаре, а отображение в цикле должно быть нетронутым.
Я все таки не понял, если и тут и там выводятся последние записи, то что их исключать - они ведь все исключаться. Сайт покажите, плз.
Они все исключатся на главной, где такие же отображаются, а будут отображаться другие, более ранние. А вот на какой-нибудь 100-й странице ведь нет, все будут уникальными. Я думаю, эта опиция вообще должна быть по умолчанию, дубли создавать не комильфо.
Теперь понятно. Согласился с вашим мнением и доработал код функции, теперь она не будет выводить посты, которые уже есть в главном запросе wp_query.
Технически, добавил такой код в начало, и переменную $AND_NOT_IN в запрос:
// исключим посты из главного запроса foreach( $GLOBALS['wp_query']->posts as $post ) $IDs .= $post->ID .','; $AND_NOT_IN = ' AND p.ID NOT IN ('. rtrim($IDs, ',') .')';Не тестировал, отпишите плз как работает.
Спасибо за настойчивость и сорри за то, что не отвечал долго, так вот.
Блестяще работает! Низкий вам поклон.
Добрый день,
Прежде всего спасибо за полезную информацию.
Во вторых, хотел спросить вас, что надо изменить для вывода картинок в сайдбар для определенной категории, то есть кроме текста и тайтла новости, также вытягивалась картинка. А именно "Featured image".
Здравствуйте! Подскажите пожалуйста, в чем может быть причина появления кракозябр после изменения файла function.php ?
Заранее спасибо!
Кодировка файла изменилась.