WordPress自动更新缓存功能的归档页面制作

之前使用的归档页面是秋叶博客分享的 → WordPress带缓存和特效的归档页面制作,使用的是php的缓存机制,每次发布/删除文章后,归档页面缓存不会自动清除和重建,想整一个包含缓存机制和手动刷新功能的归档页面,针对原来的归档页面优化了一下。

实现方案:将核心功能放在functions.php中,页面模板只负责显示。这种架构使缓存管理和内容生成逻辑集中化,而页面模板只负责显示内容,系统会在文章更新时自动刷新缓存,同时为管理员提供手动刷新选项,确保归档页面始终保持最新状态。更符合WordPress最佳实践,具有更好的性能和可维护性。

查看效果:https://chegva.com/archive/

功能设计

  1. functions.php部分

    • 缓存管理机制

    • 文章更新时自动清除缓存

    • 归档内容生成函数

    • 手动清除缓存的工具

  2. 页面模板部分

    • 只负责显示归档内容

    • 包含响应式布局和交互功能

缓存清除场景说明

场景旧状态新状态说明
  新文章发布非发布状态 (draftpending 等)publish归档需要添加新文章
定时发布futurepublish 归档需要添加新文章
  取消发布publish非发布状态 (draftprivate 等)归档需要移除该文章
  移至回收站任何状态trash归档需要移除该文章
  已发布文章更新publishpublish❌ 不触发缓存清除
  草稿更新draftdraft❌ 不触发缓存清除

工作流程图

Wordpress自动更新缓存功能的归档页面制作

Wordpress自动更新缓存功能的归档页面制作

定时发布文章的工作流程

Wordpress自动更新缓存功能的归档页面制作

实现代码

第一步:在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(); ?>

使用指南

  1. 安装步骤

    • 将functions.php代码添加到主题的functions.php文件

    • 创建page-archives.php模板文件

    • 在WordPress后台创建新页面并选择"归档页面"模板

  2. 缓存管理

    • 自动:发布新文章时自动刷新

    • 手动:管理员点击"清除归档缓存"链接

  3. 自定义选项

    • 修改缓存名称:'qiuye_archives'

    • 调整样式:编辑CSS代码段

    • 修改查询参数:调整WP_Query数组

调试步骤:

  1. 将完整代码复制到主题的 functions.php

  2. 发布一篇测试文章

  3. 查看归档页面源代码中的缓存时间标记

  4. 检查debug.log中的清除记录

  5. 使用管理栏按钮测试手动清除功能

1、检查缓存状态
在归档页面查看源代码,搜索 <!-- Cache generated: 查看缓存时间

Wordpress自动更新缓存功能的归档页面制作

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、手动清除测试
使用添加的管理栏按钮手动清除缓存

Wordpress自动更新缓存功能的归档页面制作

4、缓存插件排查
如果使用了缓存插件(W3TC、WP Super Cache等),尝试:

    • 排除归档页面缓存

    • 禁用插件测试

5、对象缓存检查
如果使用Redis/Memcached,确保 delete_option 能正确清除持久化存储


anzhihe 安志合个人博客,版权所有 丨 如未注明,均为原创 丨 转载请注明转自:https://chegva.com/6518.html | ☆★★每天进步一点点,加油!★★☆ | 

您可能还感兴趣的文章!

发表评论

电子邮件地址不会被公开。 必填项已用*标注