提示 展开 / 收起

本人在建站过程中,看到其他博客中各种各样好看的栏目页面,想要借鉴到自己的博客里,却拼尽全力无法使用Wordpress默认编辑器实现,也没有找到相关教程。不论是添加csss还是嵌入html都无法实现与主题一致的效果,十分违和。尝试过使用Elementor,但升级版需要付费,且操作界面过于繁杂不方便入门,学习成本高,于是从源码出发,尝试修改主题文件达到目的。在阅读主题文件夹下的源码后,发现 “archive.php”"index.php" 中包含了有关展示文章和说说的代码。

源码学习

其中 "index.php" 主页,包含封面大图、Display和Article部分的代码。该文件通过引用 "tpl/content-thumb.php" 获取数据库中存储的静态页面、非静态文章和说说并按时间倒序排序,再通过引用 "tpl/content-thumbcard.php" 来将每篇文章以预设的样式展示。

“archive.php” 中包含相似的结构,获取某一特定分类下的所有文章和说说,并引用 "tpl/content-thumbcard.php" 来实现指定样式展示。如:二次元~ 标签。

综上所述,如果想要实现与主题一致的展示效果,必须在获取文章数据后通过引用模板 "tpl/content-thumbcard.php" 实现。

代码实现

首先在主题路径下创建一个存储自定义模板文件的php文件,我选择放在 "Sakurairo/" 文件夹中并命名为 "page-column-ai-cover.php" ,内容如下(其中包含其他可选参数及其使用方式):

提示信息块 展开 / 收起
<?php
/**
 * Template Name: 条件检索页面模板
 */
/**
 * The template for displaying archive pages.
 * @link https://codex.wordpress.org/Template_Hierarchy     
 * @package Sakurairo
 */

get_header(); ?>

<div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
        <?php
        // 显示页面本身的内容,即 WordPress 页面编辑器中的内容
        if (have_posts()) :
            while (have_posts()) : the_post(); ?>
                <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
       <!-- 以下注释部分会在使用了模板的页面中出现重复的标题,若有需求可以保留 -->
              <!--  <header class="entry-header">
                        <?php the_title('<h1 class="entry-title">', '</h1>'); ?>
                    </header>  -->
                    
                    <div class="entry-content">
                        <?php the_content(); ?>
                    </div>
                </article>
            <?php endwhile;
        endif;
        
        // 显示特定分类的文章列表
        $args = array(
            'post_type' => array('post', 'shuoshuo'),
            'cat' => 11,
            'posts_per_page' => -1  // -1表示获取所有匹配的文章
        );
        $ai_query = new WP_Query($args);
        
        if ($ai_query->have_posts()) :
            while ($ai_query->have_posts()) : $ai_query->the_post();
                get_template_part('tpl/content', 'thumbcard');
            endwhile;
            // 重置查询
            wp_reset_postdata();
        else :
            get_template_part('tpl/content', 'none');
        endif;
        ?>

    </main><!-- #main -->
</div><!-- #primary -->

<?php
get_footer();
待更新折叠块 展开 / 收起

此时,在添加页面界面中,可以选择模板:“条件检索页面模板”,即可在页面的内容后显示所有的分类ID为11的文章,且使用主题的默认样式。

但是该方案具有明显的局限性,即每有一个条件检索的需求,则需要额外复制一个相同的模板,且仅仅修改其中的查询条件。因此为提高代码复用性,可以利用 WordPress 的短代码功能优化其表现。

短代码优化

由于添加短代码需要修改主题文件 function.php ,更新主题时可能带来不便,而且 function.php 文件中函数太多不方便管理,因此选择插件Code Snippets” 、 “Simple Custom CSS and JS作为替代方案。Code Snippets 支持添加 function.php HTML ,虽然其原生支持 CSS 和 JS,但需要付费,用 Simple Custom CSS and JS替补。

首先修改上述模板 "page-column-ai-cover.php"

<?php
/**
 * Template Name: 条件检索页面模板
 */
/**
 * 通用AI内容页面模板,可通过短代码[ai_songs]控制显示内容
 * @link https://codex.wordpress.org/Template_Hierarchy
 * @package Sakurairo
 */

get_header(); ?>

<div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
        <?php
        // 显示页面本身的内容
        if (have_posts()) :
            while (have_posts()) : the_post(); ?>
                <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                    
                    <div class="entry-content">
                        <?php the_content(); ?>
                    </div>
                </article>
            <?php endwhile;
        endif;
        ?>

    </main><!-- #main -->
</div><!-- #primary -->
<?php
get_footer();

简化模板内容,使其显示页面自身的内容即可,剩余操作交给短代码处理。

Code Snippets 插件中创建一个名为 “条件检索列表短代码” 的php文件(建议命名简单易懂,方便后续修改),其中添加以下代码:

/**
 * 条件检索列表短代码
 * 支持多种查询条件:分类ID、分类名、标签ID、标签名、文章ID等
 * 
 * @param array $atts 短代码参数
 * @return string 输出的HTML内容
 */
function content_shortcode($atts) {
    // 默认参数
    $defaults = array(
        'post_types' => 'post,shuoshuo', // 文章类型,逗号分隔
        'posts_per_page' => '-1',        // 每页文章数,-1表示全部
        'orderby' => 'date',             // 排序字段
        'order' => 'DESC',               // 排序方式
        'template' => 'thumbcard',       // 使用的模板部分
        
        // 分类查询参数
        'category_id' => '',             // 分类ID
        'category_name' => '',           // 分类别名
        'category__in' => '',            // 多个分类ID,逗号分隔
        'category__not_in' => '',        // 排除的分类ID,逗号分隔
        
        // 标签查询参数
        'tag_id' => '',                  // 标签ID
        'tag_name' => '',                // 标签别名
        'tag__in' => '',                 // 多个标签ID,逗号分隔
        'tag__not_in' => '',             // 排除的标签ID,逗号分隔
        
        // 文章ID查询
        'post_ids' => '',                // 特定文章ID,逗号分隔
        'post__not_in' => '',            // 排除的文章ID,逗号分隔
        
        // 自定义分类法查询
        'taxonomy' => '',                // 自定义分类法名称
        'term' => '',                    // 自定义分类法的term(别名)
        'term_id' => '',                 // 自定义分类法的term ID
        'taxonomy_relation' => 'AND',    // 分类法查询关系:AND 或 OR
    );
    
    // 合并用户参数和默认参数
    $atts = shortcode_atts($defaults, $atts);
    
    // 验证taxonomy_relation参数
    $atts['taxonomy_relation'] = strtoupper($atts['taxonomy_relation']);
    if ($atts['taxonomy_relation'] !== 'AND' && $atts['taxonomy_relation'] !== 'OR') {
        $atts['taxonomy_relation'] = 'AND';
    }
    
    // 构建查询参数
    $args = array(
        'posts_per_page' => $atts['posts_per_page'],
        'orderby' => $atts['orderby'],
        'order' => $atts['order']
    );
    
    // 处理post_types参数
    if (!empty($atts['post_types'])) {
        $post_types = explode(',', $atts['post_types']);
        $post_types = array_map('trim', $post_types);
        // 验证post types是否存在
        $valid_post_types = array();
        foreach ($post_types as $post_type) {
            if (post_type_exists($post_type)) {
                $valid_post_types[] = $post_type;
            }
        }
        if (!empty($valid_post_types)) {
            $args['post_type'] = $valid_post_types;
        }
    }
    
    // 初始化tax_query
    $tax_query = array();
    
    // 处理分类查询
    if (!empty($atts['category_id']) || !empty($atts['category_name']) || 
        !empty($atts['category__in'])) {
        
        $category_query = array(
            'taxonomy' => 'category',
            'operator' => 'IN'
        );
        
        if (!empty($atts['category_id'])) {
            $category_query['terms'] = array($atts['category_id']);
            $category_query['field'] = 'term_id';
        } else if (!empty($atts['category_name'])) {
            $category_query['terms'] = array($atts['category_name']);
            $category_query['field'] = 'slug';
        } else if (!empty($atts['category__in'])) {
            $category__in = explode(',', $atts['category__in']);
            $category__in = array_map('trim', $category__in);
            $category__in = array_map('intval', $category__in);
            $category_query['terms'] = $category__in;
            $category_query['field'] = 'term_id';
        }
        
        $tax_query[] = $category_query;
    }
    
    // 处理分类排除
    if (!empty($atts['category__not_in'])) {
        $category__not_in = explode(',', $atts['category__not_in']);
        $category__not_in = array_map('trim', $category__not_in);
        $category__not_in = array_map('intval', $category__not_in);
        
        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'term_id',
            'terms' => $category__not_in,
            'operator' => 'NOT IN'
        );
    }
    
    // 处理标签查询
    if (!empty($atts['tag_id']) || !empty($atts['tag_name']) || 
        !empty($atts['tag__in'])) {
        
        $tag_query = array(
            'taxonomy' => 'post_tag',
            'operator' => 'IN'
        );
        
        if (!empty($atts['tag_id'])) {
            $tag_query['terms'] = array($atts['tag_id']);
            $tag_query['field'] = 'term_id';
        } else if (!empty($atts['tag_name'])) {
            $tag_query['terms'] = array($atts['tag_name']);
            $tag_query['field'] = 'slug';
        } else if (!empty($atts['tag__in'])) {
            $tag__in = explode(',', $atts['tag__in']);
            $tag__in = array_map('trim', $tag__in);
            $tag__in = array_map('intval', $tag__in);
            $tag_query['terms'] = $tag__in;
            $tag_query['field'] = 'term_id';
        }
        
        $tax_query[] = $tag_query;
    }
    
    // 处理标签排除
    if (!empty($atts['tag__not_in'])) {
        $tag__not_in = explode(',', $atts['tag__not_in']);
        $tag__not_in = array_map('trim', $tag__not_in);
        $tag__not_in = array_map('intval', $tag__not_in);
        
        $tax_query[] = array(
            'taxonomy' => 'post_tag',
            'field' => 'term_id',
            'terms' => $tag__not_in,
            'operator' => 'NOT IN'
        );
    }
    
    // 处理自定义分类法查询
    if (!empty($atts['taxonomy']) && (!empty($atts['term']) || !empty($atts['term_id']))) {
        // 验证自定义分类法是否存在
        if (taxonomy_exists($atts['taxonomy'])) {
            $custom_taxonomy_query = array(
                'taxonomy' => $atts['taxonomy'],
                'operator' => 'IN'
            );
            
            if (!empty($atts['term'])) {
                $custom_taxonomy_query['terms'] = array($atts['term']);
                $custom_taxonomy_query['field'] = 'slug';
            } else if (!empty($atts['term_id'])) {
                $custom_taxonomy_query['terms'] = array($atts['term_id']);
                $custom_taxonomy_query['field'] = 'term_id';
            }
            
            $tax_query[] = $custom_taxonomy_query;
        }
    }
    
    // 如果有多个tax_query条件,设置关系
    if (count($tax_query) > 1) {
        $tax_query['relation'] = $atts['taxonomy_relation'];
    }
    
    // 将tax_query添加到主查询参数
    if (!empty($tax_query)) {
        $args['tax_query'] = $tax_query;
    }
    
    // 处理文章ID查询
    if (!empty($atts['post_ids'])) {
        $post_ids = explode(',', $atts['post_ids']);
        $post_ids = array_map('trim', $post_ids);
        $post_ids = array_map('intval', $post_ids);
        
        // 过滤有效的文章ID
        $valid_post_ids = array();
        foreach ($post_ids as $post_id) {
            if (get_post_status($post_id)) {
                $valid_post_ids[] = $post_id;
            }
        }
        
        if (!empty($valid_post_ids)) {
            $args['post__in'] = $valid_post_ids;
            // 当指定多个文章ID时,按指定顺序排序
            if (count($valid_post_ids) > 1) {
                $args['orderby'] = 'post__in';
            }
        }
    }
    
    // 处理排除的文章ID
    if (!empty($atts['post__not_in'])) {
        $post__not_in = explode(',', $atts['post__not_in']);
        $post__not_in = array_map('trim', $post__not_in);
        $post__not_in = array_map('intval', $post__not_in);
        
        // 过滤有效的文章ID
        $valid_post__not_in = array();
        foreach ($post__not_in as $post_id) {
            if (get_post_status($post_id)) {
                $valid_post__not_in[] = $post_id;
            }
        }
        
        if (!empty($valid_post__not_in)) {
            $args['post__not_in'] = $valid_post__not_in;
        }
    }

    // 添加分页支持
    $paged = (get_query_var('paged')) ? get_query_var('paged') : ((get_query_var('page')) ? get_query_var('page') : 1);
    $args['paged'] = $paged;
    
    // 执行查询
    $ai_query = new WP_Query($args);
    $output = '';
    
    if ($ai_query->have_posts()) {
        ob_start(); // 开始输出缓冲
        
        while ($ai_query->have_posts()) : $ai_query->the_post();
            // 动态获取模板部分,支持传入的template参数
            get_template_part('tpl/content', $atts['template']);
        endwhile;
		
		        // 添加分页导航 - 与原始归档模板保持一致
        if (iro_opt('pagenav_style') == 'ajax') { ?>
            <div id="pagination" class="pagination-archive">
                <?php echo next_posts_link(__(' Previous', 'sakurairo'), $ai_query->max_num_pages); ?>
            </div>
            <div id="add_post"><span id="add_post_time" style="visibility: hidden;" title="<?php echo iro_opt('page_auto_load', ''); ?>"></span></div>
        <?php } else { ?>
            <nav class="navigator">
                <?php previous_posts_link('<i class="fa-solid fa-angle-left"></i>', $ai_query->max_num_pages); ?>
                <?php next_posts_link('<i class="fa-solid fa-angle-right"></i>', $ai_query->max_num_pages); ?>
            </nav>
        <?php }
        
        // 重置查询
        wp_reset_postdata();
        
        $output = ob_get_clean(); // 获取缓冲内容
    } else {
        ob_start();
        get_template_part('tpl/content', 'none');
        $output = ob_get_clean();
    }
    
    return $output;
}
add_shortcode('content', 'content_shortcode');

现在,页面编辑的任何地方添加简码,即可根据简码内容显示指定的文章和说说。所有短代码可选标签均在文件开头,按需填写即可。

使用示例

# 选择所有分类id为11的文章和说说
[content category_id="11"]

# 选择所有标签id为12的文章和说说
[content tag_id="12"]

可以看到页面设置的标题、内容、特色图片均正常显示。

自定义选项快速定制分类

在使用 qwen.ai 的过程中,它给我提了一个很有趣的建议。虽然直接使用短代码可以平替,仍写在这里。

新建一个php页面模板:

<?php
/**
 * Template Name: 自定义混合归档页面
 * Description: 显示分类下所有文章和说说的混合归档页面
 */
get_header(); ?>

<div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
        
        <!-- 显示页面编辑器内容 -->
        <?php while (have_posts()) : the_post(); ?>
            <div class="page-content">
                <?php the_content(); ?>
            </div>
        <?php endwhile; ?>
        
        <!-- 获取当前页面关联的分类 -->
        <?php
        $category_slug = get_post_meta(get_the_ID(), '_custom_archive_category', true);
        
        if ($category_slug) :
            // 获取当前分类对象
            $category = get_category_by_slug($category_slug);
            if ($category) :
                // 显示分类标题和描述
                if (!iro_opt('patternimg') || !z_taxonomy_image_url()) { ?>
                    <header class="page-header">
                        <h1 class="cat-title"><?php echo $category->name; ?></h1>
                        <span class="cat-des"><?php echo $category->description; ?></span>
                    </header>
                <?php } ?>
                
                <!-- 使用短代码显示混合内容 -->
                <?php echo do_shortcode('[ai_content post_types="post,shuoshuo" category_name="' . $category_slug . '"]'); ?>
                
            <?php endif; ?>
        <?php else : ?>
            <p class="no-category-selected">请在页面设置中选择一个分类。</p>
        <?php endif; ?>
    </main>
</div>

<?php get_footer();

新建function

将以下代码添加到在 Code Snippets 中新建的php中,或直接添加到主题的function.php:

// 添加自定义混合归档页面选项
function add_custom_mixed_archive_meta_box() {
    add_meta_box(
        'custom_mixed_archive_settings',
        '混合归档设置',
        'custom_mixed_archive_meta_box_callback',
        'page',
        'side',
        'default'
    );
}
add_action('add_meta_boxes', 'add_custom_mixed_archive_meta_box');

function custom_mixed_archive_meta_box_callback($post) {
    // 添加安全验证字段
    wp_nonce_field('custom_mixed_archive_meta_box', 'custom_mixed_archive_meta_box_nonce');
    
    // 获取当前设置
    $category_slug = get_post_meta($post->ID, '_custom_archive_category', true);
    
    // 获取所有分类
    $categories = get_categories();
    ?>
    <p>
        <label for="custom_archive_category"><strong>选择要显示的分类:</strong></label>
        <select name="custom_archive_category" id="custom_archive_category">
            <option value="">无</option>
            <?php foreach ($categories as $category) : ?>
                <option value="<?php echo esc_attr($category->slug); ?>" <?php selected($category_slug, $category->slug); ?>>
                    <?php echo esc_html($category->name); ?>
                </option>
            <?php endforeach; ?>
        </select>
    </p>
    <p style="font-size: 0.9em; color: #666;">
        此页面将显示所选分类下的所有文章和说说。
    </p>
    <?php
}

// 保存设置
function save_custom_mixed_archive_meta_box($post_id) {
    // 验证nonce
    if (!isset($_POST['custom_mixed_archive_meta_box_nonce'])) {
        return;
    }
    
    // 验证nonce值
    if (!wp_verify_nonce($_POST['custom_mixed_archive_meta_box_nonce'], 'custom_mixed_archive_meta_box')) {
        return;
    }
    
    // 检查自动保存
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
    
    // 检查权限
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }
    
    // 保存数据
    if (isset($_POST['custom_archive_category'])) {
        update_post_meta($post_id, '_custom_archive_category', sanitize_text_field($_POST['custom_archive_category']));
    }
}
add_action('save_post', 'save_custom_mixed_archive_meta_box');

保存后,在”添加页面“的右侧设置栏中会新增一个选项,选择分类并使用“自定义混合归档页面”模板后发布页面,该页面中即可显示指定分类的全部文章和说说。

原理:上述新增代码实际上是实现了为“自定义混合归档页面”模板创建的页面自动添加一行代码:

echo do_shortcode('[ai_content post_types="post,shuoshuo" category_name="' . $category_slug . '"]');

利用实现的自定义条件检索短代码完成类型检索,只是在页面编辑过程中不用编写短代码而已,因此这个模板同样支持设置标题、正文和特色图片等,归档的文章会在页面内容之后展示。

虽然感觉用处不大就是了


封面图:#原创 热度似乎过了,那就来点win11娘 - karvཁར་ཨུ་的插画 - pixiv

我想活得聪明,通透,快乐,满足。 我想我的世界窗明几净。 一片雾蓝色。
最后更新于 2025-09-21