之前使用的归档页面是秋叶博客分享的 → WordPress带缓存和特效的归档页面制作,使用的是php的缓存机制,每次发布/删除文章后,归档页面缓存不会自动清除和重建,想整一个包含缓存机制和手动刷新功能的归档页面,针对原来的归档页面优化了一下。
实现方案:将核心功能放在functions.php中,页面模板只负责显示。这种架构使缓存管理和内容生成逻辑集中化,而页面模板只负责显示内容,系统会在文章更新时自动刷新缓存,同时为管理员提供手动刷新选项,确保归档页面始终保持最新状态。更符合WordPress最佳实践,具有更好的性能和可维护性。
查看效果:https://chegva.com/archive/
功能设计
functions.php部分:
缓存管理机制
文章更新时自动清除缓存
归档内容生成函数
手动清除缓存的工具
页面模板部分:
只负责显示归档内容
包含响应式布局和交互功能
缓存清除场景说明
场景 | 旧状态 | 新状态 | 说明 |
---|---|---|---|
新文章发布 | 非发布状态 (draft , pending 等) | publish | 归档需要添加新文章 |
定时发布 | future | publish | 归档需要添加新文章 |
取消发布 | publish | 非发布状态 (draft , private 等) | 归档需要移除该文章 |
移至回收站 | 任何状态 | trash | 归档需要移除该文章 |
已发布文章更新 | publish | publish | ❌ 不触发缓存清除 |
草稿更新 | draft | draft | ❌ 不触发缓存清除 |
工作流程图
定时发布文章的工作流程
实现代码
第一步:在functions.php中添加以下代码
/** * 添加归档页面 **/ // 注册归档缓存选项 add_action('init', function() { add_option('qiuye_archives', '', '', 'no'); }); // 核心缓存清除函数 function clear_archive_cache() { delete_option('qiuye_archives'); set_transient('qiuye_cache_cleared', time(), 60); // 设置60秒瞬态标记,避免在清除操作后立即重建 // 增强调试:记录清除操作 if (defined('WP_DEBUG') && WP_DEBUG) { error_log('清除归档缓存触发 - 文章ID: ' . $post_id); } } // 文章状态变更处理 - 只在状态变更时清除缓存 add_action('save_post', function($post_id, $post, $update) { // 跳过自动保存 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return; // 只处理文章类型 if ($post->post_type !== 'post') return; // 检查权限 if (!current_user_can('edit_post', $post_id)) return; // 获取旧状态 $old_status = get_post_meta($post_id, '_old_status', true); // 保存当前状态作为下次的旧状态 update_post_meta($post_id, '_old_status', $post->post_status); // 检查定时发布 $is_scheduled = ($post->post_status === 'future'); // 如果是定时发布的文章,设置定时任务 if ($is_scheduled) { $scheduled_time = strtotime($post->post_date); $current_time = current_time('timestamp'); // 只有在未来时间才设置定时任务 if ($scheduled_time > $current_time) { wp_schedule_single_event($scheduled_time, 'publish_future_post', array($post_id)); error_log("定时发布文章设置: $post_id, 发布时间: " . date('Y-m-d H:i:s', $scheduled_time)); } } // 状态变更检测 $status_changed = ($old_status && $old_status !== $post->post_status); // 需要清除缓存的场景 $clear_cache = false; if ($status_changed) { // 场景1: 从未发布变为发布状态 if ($old_status !== 'publish' && $post->post_status === 'publish') { $clear_cache = true; } // 场景2: 从发布状态变为非发布状态 elseif ($old_status === 'publish' && $post->post_status !== 'publish') { $clear_cache = true; } // 场景3: 从任何状态变为删除状态 elseif ($post->post_status === 'trash') { $clear_cache = true; } } // 场景4: 新文章直接发布 if (!$old_status && $post->post_status === 'publish') { $clear_cache = true; } if ($clear_cache) { clear_archive_cache(); error_log("文章状态变更触发缓存清除: " . ($old_status ?: 'new') . " => {$post->post_status} (ID: $post_id)"); } }, 10, 3); // 定时发布文章处理 add_action('publish_future_post', function($post_id) { $post = get_post($post_id); if ($post && $post->post_type === 'post') { clear_archive_cache(); error_log("定时发布文章触发缓存清除: $post_id"); // 发送通知(可选) if (defined('WP_DEBUG') && WP_DEBUG) { $admin_email = get_option('admin_email'); wp_mail($admin_email, '定时文章已发布', "文章 ID: $post_id 已按计划发布,归档缓存已更新。"); } } }); // 文章移至回收站处理 add_action('trashed_post', function($post_id) { $post = get_post($post_id); if ($post && $post->post_type === 'post') { clear_archive_cache(); error_log("文章移至回收站触发缓存清除: $post_id"); } }); // 文章从回收站恢复处理 add_action('untrashed_post', function($post_id) { $post = get_post($post_id); if ($post && $post->post_type === 'post') { // 如果恢复后是发布状态,清除缓存 if ($post->post_status === 'publish') { clear_archive_cache(); error_log("文章恢复发布触发缓存清除: $post_id"); } } }); // 文章永久删除处理 //add_action('deleted_post', function($post_id) { // // 删除状态跟踪的元数据 // delete_post_meta($post_id, '_old_status'); // // $post = get_post($post_id); // if ($post && $post->post_type === 'post') { // clear_archive_cache(); // error_log("文章永久删除触发缓存清除: $post_id"); // } //}); // 在文章编辑页添加状态跟踪 add_action('post_submitbox_start', function() { global $post; if ($post && $post->post_type === 'post') { // 保存当前状态作为旧状态 if (!get_post_meta($post->ID, '_old_status', true)) { update_post_meta($post->ID, '_old_status', $post->post_status); } echo '<input type="hidden" name="old_status" value="'.esc_attr($post->post_status).'">'; } }); // 在文章保存前捕获旧状态 add_action('pre_post_update', function($post_id) { $old_status = get_post_status($post_id); update_post_meta($post_id, '_old_status', $old_status); }); // 定时清理过期的状态跟踪元数据 add_action('wp_scheduled_delete', function() { global $wpdb; // 删除30天前的状态跟踪元数据 $thirty_days_ago = date('Y-m-d H:i:s', strtotime('-30 days')); $wpdb->query($wpdb->prepare(" DELETE FROM $wpdb->postmeta WHERE meta_key = '_old_status' AND post_id IN ( SELECT ID FROM $wpdb->posts WHERE post_modified < %s ) ", $thirty_days_ago)); error_log("清理过期的状态跟踪元数据完成"); }); // 归档内容生成函数 function generate_archive_html() { // 生成内容 $output = '<div class="archives"><div style="text-align:right;"><img src="https://cdn.chegva.com/static/sorting-answers.png" style="width: 16px;height: 14px;vertical-align:baseline;" ><a id="al_expand_collapse" href="#"> 全部展开/收缩</a> <span style="font-size:11px">(年份/月份也可点击哦!)</span></div>'; // 使用更可靠的查询方法 $args = array( 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => -1, 'ignore_sticky_posts' => 1, 'no_found_rows' => true, // 提高性能 'update_post_term_cache' => false, // 提高性能 'suppress_filters' => true // 确保无插件干扰 ); $the_query = new WP_Query($args); $year = 0; $mon = 0; while ( $the_query->have_posts() ) : $the_query->the_post(); $year_tmp = get_the_time('Y'); $mon_tmp = get_the_time('m'); if ($mon != $mon_tmp && $mon > 0) $output .= '</ul></li>'; if ($year != $year_tmp && $year > 0) $output .= '</ul>'; if ($year != $year_tmp) { $year = $year_tmp; $output .= '<h3 class="al_year">'. $year .'年<span style="padding-left:35px;">( '. get_num_posts_by_year($year) .' 篇文章 )</span></h3><ul class="al_mon_list">'; } if ($mon != $mon_tmp) { $mon = $mon_tmp; $output .= '<li><span class="al_mon">'. $mon .' 月</span><ul class="al_post_list">'; } $output .= '<li class="atitle fix"><span class="ttime">'. get_the_time('d日: ') .'</span><a class="tttile" href="'. get_permalink() .'">'. get_the_title() .'</a><span class="ttview">·'. the_views('0',' ') .'</span></li>'; endwhile; wp_reset_postdata(); $output .= '</ul></li></ul></div>'; // 添加缓存信息 - 使用本地时间 $output .= "<!-- Cache generated: ".get_local_time('Y-m-d H:i:s')." -->"; return $output; } // 扩展的获取本地时间函数(带时间戳参数) function get_local_time($format = 'Y-m-d H:i:s', $timestamp = null) { // 获取WordPress设置的时区 $timezone_string = get_option('timezone_string'); if ($timezone_string) { $timezone = new DateTimeZone($timezone_string); } else { $offset = get_option('gmt_offset'); $timezone = timezone_open(sprintf('%+d', $offset)); } // 使用当前时间或指定时间戳 $timestamp = $timestamp ?: time(); $datetime = new DateTime('@' . $timestamp); $datetime->setTimezone($timezone); return $datetime->format($format); } // 添加手动清除缓存的工具 add_action('admin_bar_menu', function($admin_bar) { if (current_user_can('manage_options')) { $admin_bar->add_menu([ 'id' => 'clear-archive-cache', 'title' => '清除归档缓存', 'href' => wp_nonce_url(add_query_arg('clear_archive_cache', '1'), 'clear_archive_cache') ]); } }, 100); // 处理手动清除请求 add_action('init', function($post_id) { if (isset($_GET['clear_archive_cache']) && check_admin_referer('clear_archive_cache')) { // delete_option('qiuye_archives'); clear_archive_cache(); wp_redirect(remove_query_arg(['clear_archive_cache', '_wpnonce'])); exit; } });
第二步:创建归档页面模板 (page-archives.php)
<div id="content"> <?php // 归档显示函数 function qiuye_display_archives() { // 检查瞬态是否存在 $cache_cleared_time = get_transient('qiuye_cache_cleared'); if ($cache_cleared_time) { // 如果缓存被清除过,重新生成 $output = generate_archive_html(); update_option('qiuye_archives', $output); // 添加缓存清除时间信息 $output .= "<!-- Cache cleared: ".get_local_time('Y-m-d H:i:s', $cache_cleared_time)." -->"; } else { // 尝试获取现有缓存 $output = get_option('qiuye_archives'); if (empty($output)) { $output = generate_archive_html(); update_option('qiuye_archives', $output); } } echo $output; } ?> <?php qiuye_display_archives(); ?>
使用指南
安装步骤:
将functions.php代码添加到主题的functions.php文件
创建page-archives.php模板文件
在WordPress后台创建新页面并选择"归档页面"模板
缓存管理:
自动:发布新文章时自动刷新
手动:管理员点击"清除归档缓存"链接
自定义选项:
修改缓存名称:
'qiuye_archives'
调整样式:编辑CSS代码段
修改查询参数:调整WP_Query数组
调试步骤:
将完整代码复制到主题的
functions.php
发布一篇测试文章
查看归档页面源代码中的缓存时间标记
检查debug.log中的清除记录
使用管理栏按钮测试手动清除功能
1、检查缓存状态:
在归档页面查看源代码,搜索 <!-- Cache generated:
查看缓存时间
2、检查错误日志:
在 wp-config.php
中添加:
define('WP_DEBUG', true); define('WP_DEBUG_LOG', true);
发布文章后检查 /wp-content/debug.log
$ grep "清除归档缓存" debug.log [25-Jun-2025 18:36:05 UTC] 清除归档缓存触发 - 文章ID: 6434 [25-Jun-2025 18:37:27 UTC] 清除归档缓存触发 - 文章ID: 6435 [25-Jun-2025 18:37:44 UTC] 清除归档缓存触发 - 文章ID: 6436 [25-Jun-2025 18:37:45 UTC] 清除归档缓存触发 - 文章ID: 6437 [25-Jun-2025 18:37:54 UTC] 清除归档缓存触发 - 文章ID: 6437 [25-Jun-2025 18:38:01 UTC] 清除归档缓存触发 - 文章ID: 6437 [25-Jun-2025 18:38:01 UTC] 清除归档缓存触发 - 文章ID: 6437 ...... [25-Jun-2025 19:07:18 UTC] 清除归档缓存触发 - 文章ID: 6442 [25-Jun-2025 19:07:19 UTC] 清除归档缓存触发 - 文章ID: 6442 [25-Jun-2025 19:07:27 UTC] 清除归档缓存触发 - 文章ID: 6443 [25-Jun-2025 19:07:28 UTC] 清除归档缓存触发 - 文章ID: 6444 [25-Jun-2025 19:08:34 UTC] 清除归档缓存触发 - 文章ID: 6445 [25-Jun-2025 19:08:51 UTC] 清除归档缓存触发 - 文章ID: 6442
3、手动清除测试:
使用添加的管理栏按钮手动清除缓存
4、缓存插件排查:
如果使用了缓存插件(W3TC、WP Super Cache等),尝试:
排除归档页面缓存
禁用插件测试
5、对象缓存检查:
如果使用Redis/Memcached,确保 delete_option
能正确清除持久化存储