WordPress开发笔记

WordPress文章形式分类(Post Formats)的启用和应用

本文介绍如何在WordPress中配置、启用和使用文章形式分类(Post Formats),从后台配置到前台展示的全流程。

第一部分:配置和启用文章形式

1.1 在主题中启用文章形式支持

首先,我们需要在主题的functions.php文件中启用文章形式支持:

<?php
// 在主题的functions.php文件中添加以下代码

// 启用文章形式支持
function my_theme_setup() {
    // 添加文章形式支持
    add_theme_support('post-formats', array(
        'aside',   // 日志
        'gallery', // 相册
        'link',    // 链接
        'image',   // 图像
        'quote',   // 引用
        'status',  // 状态
        'video',   // 视频
        'audio',    // 音频
        'chat'     // 聊天
    ));
}
add_action('after_setup_theme', 'my_theme_setup');

1.2 自定义文章形式显示名称(可选)

如果你希望自定义文章形式的显示名称,可以添加如下示例代码:

// 自定义文章形式标签
function custom_post_format_strings($strings) {
    $strings['standard'] = __('文章', 'textdomain'); // 将"标准"改为"文章"
    $strings['aside'] = __('日志', 'textdomain');
    $strings['gallery'] = __('相册', 'textdomain');
    return $strings;
}
add_filter('gettext_with_context', 'custom_post_format_strings');

这段代码的目的是自定义WordPress文章形式(Post Formats)在后台界面中的显示名称,将默认的英文标签替换为更符合中文用户习惯的名称。

函数定义

  • 定义一个名为 custom_post_format_strings 的函数
  • 接收一个参数 $strings,这是WordPress默认的文章形式标签数组

自定义标签映射

$strings['standard'] = __('文章', 'textdomain'); // 将"标准"改为"文章"
$strings['aside'] = __('日志', 'textdomain');
$strings['gallery'] = __('相册', 'textdomain');
return $strings;

原始标签与自定义标签对照表:

原始标签自定义标签说明
standard文章将默认的”标准”格式改为”文章”
aside日志将”日志/随笔”格式改为”日志”
gallery相册将”相册”格式保持为”相册”

技术细节:

  • __() 是WordPress的翻译函数,用于国际化
  • 'textdomain' 应该替换为你主题的实际文本域

挂载过滤器

add_filter('gettext_with_context', 'custom_post_format_strings');
  • 将自定义函数挂载到 gettext_with_context 过滤器
  • 当WordPress获取带上下文的翻译文本时会触发此函数

完整改进版本1:完整覆盖所有文章形式

// 完整自定义所有文章形式标签
function custom_post_format_strings($translation, $text, $context, $domain) {
    // 只处理文章形式相关的翻译
    if ($context === 'Post format') {
        $custom_strings = array(
            'Standard' => '文章',
            'Aside'    => '日志',
            'Gallery'  => '相册',
            'Link'     => '链接',
            'Image'    => '图片',
            'Quote'    => '引用',
            'Status'   => '状态',
            'Video'    => '视频',
            'Audio'    => '音频',
            'Chat'     => '聊天'
        );

        if (isset($custom_strings[$text])) {
            return $custom_strings[$text];
        }
    }
    return $translation;
}
add_filter('gettext_with_context', 'custom_post_format_strings', 10, 4);

完整改进版本2:使用更精确的过滤器

// 方法1:使用专门的post_format_labels过滤器(推荐)
function custom_post_format_labels($labels) {
    return array(
        'standard' => _x('文章', 'Post format', 'your-textdomain'),
        'aside'    => _x('日志', 'Post format', 'your-textdomain'),
        'gallery'  => _x('相册', 'Post format', 'your-textdomain'),
        'link'     => _x('链接', 'Post format', 'your-textdomain'),
        'image'    => _x('图片', 'Post format', 'your-textdomain'),
        'quote'    => _x('引用', 'Post format', 'your-textdomain'),
        'status'   => _x('状态', 'Post format', 'your-textdomain'),
        'video'    => _x('视频', 'Post format', 'your-textdomain'),
        'audio'    => _x('音频', 'Post format', 'your-textdomain'),
        'chat'     => _x('聊天', 'Post format', 'your-textdomain'),
    );
}
add_filter('post_format_labels', 'custom_post_format_labels');

// 方法2:使用get_post_format_strings过滤器
function custom_post_format_strings($strings) {
    return array(
        'standard' => __('文章', 'your-textdomain'),
        'aside'    => __('日志', 'your-textdomain'),
        'gallery'  => __('相册', 'your-textdomain'),
        'link'     => __('链接', 'your-textdomain'),
        'image'    => __('图片', 'your-textdomain'),
        'quote'    => __('引用', 'your-textdomain'),
        'status'   => __('状态', 'your-textdomain'),
        'video'    => __('视频', 'your-textdomain'),
        'audio'    => __('音频', 'your-textdomain'),
        'chat'     => __('聊天', 'your-textdomain'),
    );
}
add_filter('get_post_format_strings', 'custom_post_format_strings');

实际效果展示

修改前(默认英文标签):

[ ] Standard   [ ] Aside   [ ] Gallery   [ ] Link
[ ] Image      [ ] Quote   [ ] Status    [ ] Video
[ ] Audio      [ ] Chat

修改后(自定义中文标签):

[ ] 文章   [ ] 日志   [ ] 相册   [ ] 链接
[ ] 图片   [ ] 引用   [ ] 状态   [ ] 视频
[ ] 音频   [ ] 聊天

使用注意事项

文本域替换

// 错误:使用默认的textdomain
$strings['standard'] = __('文章', 'textdomain');

// 正确:使用你主题的实际文本域
$strings['standard'] = __('文章', 'my-theme');

函数执行时机

确保代码在主题的 functions.php 文件中,并在 after_setup_theme 动作之后执行。

与其他过滤器的兼容性

如果有其他插件也修改文章形式标签,需要注意执行优先级:

// 设置较低的优先级,确保最后执行
add_filter('get_post_format_strings', 'custom_post_format_strings', 20);

调试技巧

如果需要确认修改是否生效,可以添加调试代码:

function debug_post_format_strings($strings) {
    error_log(print_r($strings, true)); // 在debug.log中查看当前标签
    return $strings;
}
add_filter('get_post_format_strings', 'debug_post_format_strings');

第二部分:后台文章编辑界面(参考)

2.1 添加文章形式选择框样式

为了让文章形式选择更加直观,我们可以添加一些CSS样式:

// 添加后台样式
function post_formats_admin_style() {
    echo '<style>
        .post-format-icon:before {
            font-family: dashicons;
            font-size: 20px;
            vertical-align: middle;
        }
        .post-format-icon.format-aside:before { content: "\f123"; }
        .post-format-icon.format-gallery:before { content: "\f161"; }
        .post-format-icon.format-link:before { content: "\f103"; }
        .post-format-icon.format-image:before { content: "\f128"; }
        .post-format-icon.format-quote:before { content: "\f122"; }
        .post-format-icon.format-status:before { content: "\f130"; }
        .post-format-icon.format-video:before { content: "\f126"; }
        .post-format-icon.format-audio:before { content: "\f127"; }
        .post-format-icon.format-chat:before { content: "\f125"; }
    </style>';
}
add_action('admin_head', 'post_formats_admin_style');

第三部分:前端展示处理

3.1 根据文章形式显示不同内容模板

在主题的模板文件中,我们需要根据文章形式显示不同的内容布局:

<?php
// 在主题的content.php或类似文件中添加以下代码

// 获取当前文章的形式
$format = get_post_format();
if (false === $format) {
    $format = 'standard';
}

// 根据文章形式加载不同的内容模板
switch($format) {
    case 'aside':
        // 日志形式
        echo '<article class="post-format-aside">';
        echo '<div class="aside-content">';
        the_content();
        echo '</div>';
        echo '<footer class="post-meta">';
        echo '<span class="post-date">' . get_the_date() . '</span>';
        echo '</footer>';
        echo '</article>';
        break;

    case 'gallery':
        // 相册形式
        echo '<article class="post-format-gallery">';
        echo '<h2 class="post-title">' . get_the_title() . '</h2>';

        // 获取相册短代码或图片
        $content = get_the_content();
        if (has_shortcode($content, 'gallery')) {
            echo '<div class="post-gallery">';
            echo do_shortcode($content);
            echo '</div>';
        } else {
            // 如果没有相册短代码,显示特色图片
            if (has_post_thumbnail()) {
                echo '<div class="post-thumbnail">';
                the_post_thumbnail('large');
                echo '</div>';
            }
            echo '<div class="post-content">';
            the_content();
            echo '</div>';
        }

        echo '</article>';
        break;

    case 'link':
        // 链接形式
        echo '<article class="post-format-link">';
        $content = get_the_content();

        // 提取链接
        preg_match('/<as[^>]*href="([^"]*)"[^>]*>(.*)</a>/i', $content, $matches);

        if (!empty($matches)) {
            echo '<div class="link-content">';
            echo '<a href="' . esc_url($matches[1]) . '" class="external-link" target="_blank">';
            echo '<span class="link-title">' . (!empty($matches[2]) ? $matches[2] : get_the_title()) . '</span>';
            echo '<span class="link-url">' . $matches[1] . '</span>';
            echo '</a>';
            echo '</div>';
        } else {
            // 如果没有找到链接,正常显示内容
            echo '<div class="post-content">';
            the_content();
            echo '</div>';
        }

        echo '</article>';
        break;

    case 'image':
        // 图像形式
        echo '<article class="post-format-image">';

        if (has_post_thumbnail()) {
            echo '<div class="featured-image">';
            the_post_thumbnail('full');
            echo '</div>';
        }

        echo '<div class="image-caption">';
        the_content();
        echo '</div>';

        echo '</article>';
        break;

    case 'quote':
        // 引用形式
        echo '<article class="post-format-quote">';
        echo '<blockquote>';
        the_content();
        echo '<cite>' . get_the_title() . '</cite>';
        echo '</blockquote>';
        echo '</article>';
        break;

    case 'video':
        // 视频形式
        echo '<article class="post-format-video">';
        echo '<h2 class="post-title">' . get_the_title() . '</h2>';

        $content = get_the_content();

        // 尝试提取视频
        if (has_shortcode($content, 'video') || has_shortcode($content, 'embed')) {
            echo '<div class="video-container">';
            echo apply_filters('the_content', $content);
            echo '</div>';
        } else {
            // 如果没有视频短代码,正常显示内容
            echo '<div class="post-content">';
            the_content();
            echo '</div>';
        }

        echo '</article>';
        break;

    case 'audio':
        // 音频形式
        echo '<article class="post-format-audio">';
        echo '<h2 class="post-title">' . get_the_title() . '</h2>';

        $content = get_the_content();

        // 尝试提取音频
        if (has_shortcode($content, 'audio')) {
            echo '<div class="audio-container">';
            echo apply_filters('the_content', $content);
            echo '</div>';
        } else {
            // 如果没有音频短代码,正常显示内容
            echo '<div class="post-content">';
            the_content();
            echo '</div>';
        }

        echo '</article>';
        break;

    default:
        // 标准文章形式
        echo '<article class="post-format-standard">';
        echo '<h2 class="post-title">' . get_the_title() . '</h2>';

        if (has_post_thumbnail()) {
            echo '<div class="post-thumbnail">';
            the_post_thumbnail('medium');
            echo '</div>';
        }

        echo '<div class="post-content">';
        the_content();
        echo '</div>';

        echo '</article>';
        break;
}
?>

第四部分:高级功能扩展

4.1 文章形式存档页面

为每种文章形式创建专门的存档页面:

<?php
// 创建文章形式存档查询
function post_format_archive_query($query) {
    if (!is_admin() && $query->is_main_query() && is_tax('post_format')) {
        $query->set('posts_per_page', 12);
    }
}
add_action('pre_get_posts', 'post_format_archive_query');

// 添加文章形式存档页面标题
function post_format_archive_title($title) {
    if (is_tax('post_format')) {
        $format = get_query_var('post_format');
        $format_strings = array(
            'post-format-aside' => '日志',
            'post-format-gallery' => '相册',
            'post-format-link' => '链接',
            'post-format-image' => '图像',
            'post-format-quote' => '引用',
            'post-format-status' => '状态',
            'post-format-video' => '视频',
            'post-format-audio' => '音频',
            'post-format-chat' => '聊天'
        );

        if (isset($format_strings[$format])) {
            $title = $format_strings[$format] . '存档';
        }
    }
    return $title;
}
add_filter('get_the_archive_title', 'post_format_archive_title');

4.2 文章形式小工具

创建一个显示特定文章形式的小工具:

<?php
// 文章形式小工具
class Post_Formats_Widget extends WP_Widget {

    public function __construct() {
        parent::__construct(
            'post_formats_widget',
            '文章形式小工具',
            array('description' => '显示特定文章形式的文章')
        );
    }

    public function widget($args, $instance) {
        echo $args['before_widget'];

        $title = !empty($instance['title']) ? $instance['title'] : '最新文章';
        $format = !empty($instance['format']) ? $instance['format'] : 'post-format-standard';
        $number = !empty($instance['number']) ? $instance['number'] : 5;

        echo $args['before_title'] . apply_filters('widget_title', $title) . $args['after_title'];

        // 查询文章
        $posts = new WP_Query(array(
            'posts_per_page' => $number,
            'tax_query' => array(
                array(
                    'taxonomy' => 'post_format',
                    'field' => 'slug',
                    'terms' => array($format)
                )
            )
        ));

        if ($posts->have_posts()) {
            echo '<ul>';
            while ($posts->have_posts()) {
                $posts->the_post();
                echo '<li>';
                echo '<a href="' . get_permalink() . '">' . get_the_title() . '</a>';
                echo '<span class="post-date">' . get_the_date() . '</span>';
                echo '</li>';
            }
            echo '</ul>';
            wp_reset_postdata();
        } else {
            echo '<p>暂无文章</p>';
        }

        echo $args['after_widget'];
    }

    public function form($instance) {
        $title = !empty($instance['title']) ? $instance['title'] : '';
        $format = !empty($instance['format']) ? $instance['format'] : 'post-format-standard';
        $number = !empty($instance['number']) ? $instance['number'] : 5;
        ?>
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>">标题:</label>
            <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" 
                   name="<?php echo $this->get_field_name('title'); ?>" type="text" 
                   value="<?php echo esc_attr($title); ?>">
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('format'); ?>">文章形式:</label>
            <select class="widefat" id="<?php echo $this->get_field_id('format'); ?>" 
                    name="<?php echo $this->get_field_name('format'); ?>">
                <option value="post-format-standard" <?php selected($format, 'post-format-standard'); ?>>标准</option>
                <option value="post-format-aside" <?php selected($format, 'post-format-aside'); ?>>日志</option>
                <option value="post-format-gallery" <?php selected($format, 'post-format-gallery'); ?>>相册</option>
                <option value="post-format-link" <?php selected($format, 'post-format-link'); ?>>链接</option>
                <option value="post-format-image" <?php selected($format, 'post-format-image'); ?>>图像</option>
                <option value="post-format-quote" <?php selected($format, 'post-format-quote'); ?>>引用</option>
                <option value="post-format-video" <?php selected($format, 'post-format-video'); ?>>视频</option>
                <option value="post-format-audio" <?php selected($format, 'post-format-audio'); ?>>音频</option>
            </select>
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('number'); ?>">显示数量:</label>
            <input class="tiny-text" id="<?php echo $this->get_field_id('number'); ?>" 
                   name="<?php echo $this->get_field_name('number'); ?>" type="number" 
                   value="<?php echo esc_attr($number); ?>" min="1" max="10">
        </p>
        <?php
    }

    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
        $instance['format'] = (!empty($new_instance['format'])) ? strip_tags($new_instance['format']) : '';
        $instance['number'] = (!empty($new_instance['number'])) ? intval($new_instance['number']) : 5;
        return $instance;
    }
}

// 注册小工具
function register_post_formats_widget() {
    register_widget('Post_Formats_Widget');
}
add_action('widgets_init', 'register_post_formats_widget');
?>

使用说明

  1. 将上述代码添加到当前主题的functions.php文件中
  2. 根据需要调整CSS样式以适应你的主题设计
  3. 在WordPress后台编辑文章时,可以在”文章形式”元框中选择不同的形式
  4. 前台将根据选择的文章形式显示不同的布局和样式

注意事项

  • 请确保你的主题支持文章形式功能
  • 在修改主题文件前,建议先备份
  • 不同主题可能需要调整CSS样式以达到最佳视觉效果

通过以上完整的配置和代码,你的WordPress网站将能够充分利用文章形式功能,为不同类型的内容提供更加合适的展示方式。