Пользовательские поля в WordPress

В продолжение статьи Custom Fields Hacks For WordPress1 хочу поделиться своим опытом использования пользовательских полей поста.

Автор и оригинал поста

Не секрет, что на сайте в основном опубликованы переводы статей, чтобы удобно указать автора и дать ссылку на оригинал я использую дополнительные поля author и original.

Пользовательские поля

Работа с этими полями выделена в плагин dfmAuthorOriginal.php

Автора подменяем с помощью фильтра:

add_filter('the_author', 'dfm_author_filter');

function dfm_author_filter($author) {
   
global $post;

    $custom_author
= get_post_meta($post->ID, 'author', true);
   
if($custom_author) {
       
if(is_feed()) {
            $custom_author
= strip_tags($custom_author);
       
}
       
return $custom_author;
   
} else {
       
return $author;
   
}
}

Для оригинала вводим функцию dfm_original:

function dfm_original($before = '<p>', $after = '</p>') {
   
global $post;

    $original
= get_post_meta($post->ID, 'original', true);
   
if($original) {
        echo $before
. $original . $after;
   
}
}

и вставляем ее в нужном месте шаблона:

php if(function_exists('dfm_original'))
    dfm_original
('

Оригинал: ', '

'
); ?>

Краткие заголовки постов

Для списка «Последние статьи» в сайдбаре используются краткие заголовки из поля short_title. В общем случае код должен выглядеть так:

function dfm_recent_posts($before='<li>', $after='</li>')
{
    $posts
= get_posts(array('numberposts' => 10));
    echo dfm_posts_list
($posts, $before, $after);
}

function dfm_posts_list($posts, $before='<li>', $after='</li>')
{
    $result
= array();
   
   
foreach($posts as $post) {
        $permalink
= get_permalink($post);
        $title
= get_post_meta($post->ID, 'short_title', true);
        $title
= empty($title) ? $post->post_title : $title;
       
        $result
[] = sprintf('%s<a href="%s" rel="bookmark">%s</a>%s',
                            $before
, $permalink, $title, $after);
   
}

   
return implode("\n", $result);
}

К сожалению, get_posts это 4 запроса к БД и если таким способом выводить блоки «Последние статьи», «Лучшие статьи» и «Похожие статьи» то количество запросов на сборку страницы будет более чем удвоено (22 вместо 10), благодаря чему хостер отключит сайт как раз в тот момент, когда на него появиться ссылка на популярном ресурсе, поэтому я использую менее универсальный, но быстрый метод:

function dfm_recent_posts($before='<li>', $after='</li>')
{
   
global $wpdb;
   
    $posts
= $wpdb->get_results(
       
"SELECT COALESCE({$wpdb->postmeta}.meta_value, post_title) AS post_title, post_name " .
       
"FROM {$wpdb->posts} " .
       
"LEFT JOIN {$wpdb->postmeta} ON post_id = ID AND {$wpdb->postmeta}.meta_key = 'short_title' " .
       
"WHERE post_status='publish' ORDER BY post_date DESC LIMIT 10"
   
);
   
    echo dfm_posts_list
($posts, $before, $after);
}

function dfm_posts_list($posts, $before='<li>', $after='</li>')
{
    $siteurl
= get_bloginfo('siteurl');
    $result
= array();
   
   
foreach($posts as $post) {
        $permalink
= $siteurl . '/posts/' . $post->post_name;
        $result
[] = sprintf('%s<a href="%s" rel="bookmark">%s</a>%s',
                            $before
, $permalink, $post->post_title, $after);
   
}
   
   
return implode("\n", $result);
}

Функцию dfm_recent_posts вставляем в шаблоне sidebar.php:

php if(function_exists('dfm_recent_posts')) : ?>
<h3>Последние статьи</h3>
<ul class="favorite">
   
php dfm_recent_posts(); ?>
</ul>
php endif; ?>

Похожие статьи

Для похожих статей используется поле related со списком идентификаторов похожих постов:

add_filter('the_content', 'dfm_related_articles_filter');

function dfm_related_articles_filter($content) {
   
global $post, $wpdb;

    $result
= '';
   
   
if(is_single() || is_feed()) {
        $related_IDs
= get_post_meta($post->ID, 'related', true);    
       
if(!empty($related_IDs)) {
            $related_posts
= $wpdb->get_results(
               
"SELECT post_title,post_name FROM {$wpdb->posts} " .
               
"WHERE post_status='publish' AND ID IN ($related_IDs) " .
               
"ORDER BY post_date DESC;"
           
);

           
if(!empty($related_posts)) {
                $result
= '<h2>Похожие статьи</h2><ul>';
               
               
foreach($related_posts as $p) {
                    $href
= get_bloginfo('siteurl') . '/posts/'. $p->post_name;
                    $result
.= sprintf('<li><a href="%s">%s</a></li>',
                                       $href
, $p->post_title);
               
}
                $result
.= '</ul>';
           
}
       
}
   
}

   
return $content . $result;
}

Идентификаторы смотрю на карте сайта2 с помощью FireBug, конечно, хорошо бы автоматизировать этот процесс, но все руки не доходят, да и не так уж часто приходится этим заниматься.