Nginx-helper纯代码版,文章评论发布自动清理Fastcgi缓存

时间:2022-05-05
本文章向大家介绍Nginx-helper纯代码版,文章评论发布自动清理Fastcgi缓存,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

摘 要

张戈博客之前分享过Nginx开启fastcgi静态缓存加速的教程,文中也提到了WordPress对应的最佳配套插件:Nginx-Helper。本文分享一个博客自用、原创的Nginx-Helper纯代码版本,帮你的网站再消灭一个插件。

Nginx-Helper 这款插件主要用于 Nginx 的 Fastcgi 缓存或 Redis 缓存清理,用起来确实不错,堪称绝配!感兴趣可以翻看博客之前的分享:

Nginx 开启 fastcgi_cache 缓存加速,支持 html 伪静态页面 解决 Nginx Helper 插件一键清理缓存功能导致网站打不开问题

最近,发现文章发布缓存清理不生效了,开启日志看了下,发现插件清理文章缓存的时候在文章地址后多加了一个斜杠,比如 https://zhangge.net/5111.html/ ,那这样肯定不行了,因为 fastcgi 缓存是和 url 密切相关的,多一个斜杠,自然就南辕北辙了。

想想可能是和我博客加了 “分类地址后面自动加斜杠” 的机制导致的吧!懒得研究如何解决,想起之前给有偿用户写过一个纯代码版本,解决 PHP 版本过低无法兼容 Nginx-Helper 插件的问题。这次正好拿来完善一下,而且还能消灭一个插件。

经过代码编写、测试验证,一个简单的 Nginx-Helper 纯代码原创版本就新鲜出炉了。

Ps:2016 年 12 月 11 日更新:修复了文章更新发布无法清理首页缓存问题,请重新拷贝如下代码。

/**
* WordPress Nginx FastCGI缓存清理代码(Nginx-Helper纯代码版) By 张戈博客
* 文章地址:https://zhangge.net/5112.html
* 转载请保留原文出处,谢谢合作!
*/

//初始化配置
$logSwitch  = 0;                  //配置日志开关,1为开启,0为关闭
$logFile    = '/tmp/purge.log';   //配置日志路径
$cache_path = '/tmp/wpcache';     //配置缓存路径

//清理所有缓存(仅管理员) 范例:http://www.domain.com/?purge=all
if ($_GET['purge'] == 'all' && is_user_logged_in()) {
    if( current_user_can( 'manage_options' )) 
    {
        delDirAndFile($cache_path, 0);
    }
}

//缓存清理选项
add_action('publish_post', 'Clean_By_Publish', 99);                   //文章发布、更新清理缓存
add_action('comment_post', 'Clean_By_Comments',99);                   //评论提交清理缓存(不需要可注释)
add_action('comment_unapproved_to_approved', 'Clean_By_Approved',99); //评论审核清理缓存(不需要可注释)

//文章发布清理缓存函数
function Clean_By_Publish($post_ID){
    $url = get_permalink($post_ID);

    cleanFastCGIcache($url);        //清理当前文章缓存
    cleanFastCGIcache(home_url().'/');  //清理首页缓存(不需要可注释此行)
        
    //清理文章所在分类缓存(不需要可注释以下5行)
    if ( $categories = wp_get_post_categories( $post_ID ) ) {
        foreach ( $categories as $category_id ) {
            cleanFastCGIcache(get_category_link( $category_id ));
        }
    }

    //清理文章相关标签页面缓存(不需要可注释以下5行)
    if ( $tags = get_the_tags( $post_ID ) ) {
        foreach ( $tags as $tag ) {
	    cleanFastCGIcache( get_tag_link( $tag->term_id ));
        }
    }
}

// 评论发布清理文章缓存
function Clean_By_Comments($comment_id){
    $comment  = get_comment($comment_id);
    $url      = get_permalink($comment->comment_post_ID);
    cleanFastCGIcache($url);
}

// 评论审核通过清理文章缓存
function Clean_By_Approved($comment)
{
    $url      = get_permalink($comment->comment_post_ID); 
    cleanFastCGIcache($url);
}

//日志记录
function purgeLog($msg)
{
    global $logFile, $logSwitch;
    if ($logSwitch == 0 ) return;
    date_default_timezone_set('Asia/Shanghai');
    file_put_contents($logFile, date('[Y-m-d H:i:s]: ') . $msg . PHP_EOL, FILE_APPEND);
    return $msg;
}

// 缓存文件删除函数
function cleanFastCGIcache($url) {
    $url_data  = parse_url($url);
    global $cache_path;
    if(!$url_data) {
        return purgeLog($url.' is a bad url!' );
    }

    $hash        = md5($url_data['scheme'].'GET'.$url_data['host'].$url_data['path']);
    $cache_path  = (substr($cache_path, -1) == '/') ? $cache_path : $cache_path.'/';
    $cached_file = $cache_path . substr($hash, -1) . '/' . substr($hash,-3,2) . '/' . $hash;
    
    if (!file_exists($cached_file)) {
        return purgeLog($url . " is currently not cached (checked for file: $cached_file)" );
    } else if (unlink($cached_file)) {
        return purgeLog( $url." *** CLeanUP *** (cache file: $cached_file)");
    } else {
        return purgeLog("- - An error occurred deleting the cache file. Check the server logs for a PHP warning." );
    }
}

/**
 * 删除目录及目录下所有文件或删除指定文件
 * 代码出自ThinkPHP:http://www.thinkphp.cn/code/1470.html
 * @param str $path   待删除目录路径
 * @param int $delDir 是否删除目录,1或true删除目录,0或false则只删除文件保留目录(包含子目录)
 * @return bool 返回删除状态
 */
function delDirAndFile($path, $delDir = FALSE) {
    $handle = opendir($path);
    if ($handle) {
        while (false !== ( $item = readdir($handle) )) {
            if ($item != "." && $item != "..")
                is_dir("$path/$item") ? delDirAndFile("$path/$item", $delDir) : unlink("$path/$item");
        }
        closedir($handle);
        if ($delDir)
            return rmdir($path);
    }else {
        if (file_exists($path)) {
            return unlink($path);
        } else {
            return FALSE;
        }
    }
}

根据实际情况,修改代码中的缓存路径配置:

$cache_path = '/tmp/wpcache';     //配置缓存路径

Ps:这个路径其实就是 Nginx Fastcgi 缓存配置中的 fastcgi_cache_path 参数,详见前文分享

然后,将整段粘贴到 WordPress 主题函数模板文件 functions.php 当中即可。其他功能细项,在代码中都有详细的注释了,自行参考修改。

现在发布/更新文章、评论提交/审核,就会自动删除当前文章缓存了,发布/更新文章还会清理首页、分类以及相关标签页缓存(不需要可根据代码中的注释进行屏蔽)。

另外,如果想清理全部缓存,可在管理员登陆状态下访问首页+?purge=all 参数,比如:http://zhangge.net/?purge=all ,其他用户或访客访问这个地址则没有任何作用,如果还不放心也可以自行更改代码中的参数判断字符串。

?purge=all

经过测试,这种带参数的路径同样会被 Nginx 缓存,也就说?purge=all 只能用一次,第二次刷新就没效果了,因为被 Nginx 缓存了,要解决也很简单,在 fastcgi 缓存配置中排除这个路径即可:

#后台等特定页面不缓存(其他需求请自行添加即可)
if ($request_uri ~* "purge=all|/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
     set $skip_cache 1;
}

当然,如果是按照 Nginx-Helper 插件,那还能添加更多功能,比如清理订阅页面缓存什么的。但是我觉得并不需要,有以上基础功能已经足够了。有模仿能力、动手能力的站长朋友,完全可以在以上代码的基础上添加自己想要的功能,相信也是小菜一碟。