在 BAE 3.0 上的 WordPress(四):新的缓存设想 中,我提到了使用 BCS 缓存,目前我就已经实现了!
但是,问题还是有的,就是:有时候,文章发布、评论发表要自己手动更新缓存,无法自动更新。
很简单,在根目录创建一个 index-with-bcs.php,写入:
<?php
// 模式设置
$debug = 1; //开关 DeBug 模式(0:Off;1:On)
$display_cached_by_bcs = 1; //显示 Cache By BCS(0:Off;1:On)
$start = microtime(); // 计算页面加载时间
// BAE 获取真实 IP
$RealIP = str_replace(", ", "", str_replace(getenv('REMOTE_ADDR'), "", getenv('HTTP_X_FORWARDED_FOR')));
if (false === getenv('HTTP_X_FORWARDED_FOR')) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
} else {
$_SERVER['REMOTE_ADDR'] = $RealIP;
}
define('WP_USE_THEMES', true); // 不这样,主题就没了。
require_once ('bcs.class.php'); // 载入 BCS SDK
$cache_bucket = 'bucket'; // 缓存所用的 Bucket,建议使用“私有”模式和单独 Bucket,不要混用
$cache_ak = 'AK'; // API Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_AK')
$cache_sk = 'SK'; // Scret Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_SK')
$baidu_bcs = new BaiduBCS($cache_ak, $cache_sk);
$refresh_key = 'r'; // 单页缓存刷新 Key,默认 r,刷新方式就是访问你要刷新的页面 + ?r=y,强烈建议更改此选项
$clean_key = 'c'; // 缓存清空 Key,默认 c,刷新方式就是访问站点任意页面 + ?c=y,强烈建议更改此选项
$url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$url = str_replace('?' . $refresh_key . '=y', '', $url);
$url = str_replace('?' . $clean_key . '=y', '', $url);
$key = md5($url);
$object = '/' . md5($url);
// 检查 WordPress 是否处于登录状态下
$cookie = var_export($_COOKIE, true);
$loggedin = preg_match("/wordpress_logged_in/", $cookie);
// 如果已经缓存,且为游客访问(非登陆状态下),就直接加载缓存内容
if ($baidu_bcs->is_object_exist($cache_bucket, $object) && !$loggedin && !strpos($url, '/feed/') && !isset($_GET[$refresh_key]) && !isset($_GET[$clean_key])) {
echo $baidu_bcs->get_object($cache_bucket, $object)->body;
$cached = 1;
$msg = '<!-- Page cached -->';
// 如果检测到刷新指令,就清空该页缓存
} elseif ($_GET[$refresh_key] == 'y') {
require('./wp-blog-header.php');
$baidu_bcs->delete_object($cache_bucket, $object);
$msg = '<!-- Page cache deleted -->';
// 如果检测到清空指令,就清空所有缓存
} elseif ($_GET[$clean_key] == 'y') {
require('./wp-blog-header.php');
$list_opt = array('start' => 0);
$list_cache = json_decode($baidu_bcs->list_object($cache_bucket, $list_opt)->body, true);
$i = 0;
while($i < 1000){
$object= $list_cache["object_list"][$i]["object"];
$baidu_bcs->delete_object($cache_bucket, $object);
$i++;
}
$msg = '<!-- Cache flushed -->';
// 如果登录的情况下,就不缓存
} elseif ($loggedin) {
require('./wp-blog-header.php');
$msg = '<!-- Page not cached -->';
// 否则,缓存该页面
} else {
ob_start();
require('./wp-blog-header.php');
$html = ob_get_contents();
ob_end_clean();
echo $html;
// 如果是 404 页面 或 搜索结果 页面就不缓存
if (!is_404() && !is_search()) {
// 缓存 7 天,但不知过期是否会自动处理
$cache_opt = array('header' => array(
'Expires' => 'modify plus 7 days',
'Content-Type' => 'text/plain'
)
);
$baidu_bcs->create_object_by_content($cache_bucket, $object, $html, $cache_opt);
$msg = '<!-- Page is cached -->';
}
}
$end = microtime(); // 得到加载完成时间
if ($cached && $display_cached_by_bcs) {
echo "\n" . '<!-- Dynamic page generated in ' . t_exec($start, $end) . ' seconds -->' . "\n";
echo '<!-- Cached page generated by Nikbobo BCS Cache -->' . "\n";
echo '<!-- BCS Cache: ' . $key . ' -->' . "\n";
}
// 如果 DeBug 模式开启,就显示 DeBug 信息
if ($debug) {
echo "\n" . $msg . "\n";
}
// 时间比对
function t_exec($start, $end) {
$t = (getmicrotime($end) - getmicrotime($start));
return round($t,5);
}
// 获取页面加载时间
function getmicrotime($t) {
list($usec, $sec) = explode(" ",$t);
return ((float)$usec + (float)$sec);
}
?>
就可以了。
但是,记住 BAE 3.0 服务的 SDK 需要开发者自己安装到环境中,所以自己下载 BCS SDK 扔到根目录。
我们还要做的是修改 App.Conf 将伪静态修改到 index-with-bcs.php,具体步骤是:
编辑 App.Conf,将:
- url : /
script : index.php
- url : (.*)
script : /index.php
替换为:
- url : /
script : index-with-bcs.php
- url : (.*)
script : /index-with-bcs.php
然后,为了尽可能避免发布文章不自动更新、发表评论不自动更新,我们需要在主题的 Functions.php 中添加如下代码:
/*
* BCS 缓存清空 (当发布文章、评论时)
*/
function bcs_cache_refresh() {
global $batcache;
$post = get_post($post_id);
if ( $post->post_type == 'revision' || get_post_status($post_id) != 'publish' )
return;
bcs_cache_refresh_url( get_option('home') );
bcs_cache_refresh_url( trailingslashit( get_option('home') ) );
bcs_cache_refresh_url( get_permalink($post_id) );
}
add_action( 'wp_trash_post', 'bcs_cache_refresh', 0 );
add_action( 'publish_post', 'bcs_cache_refresh', 0 );
add_action( 'edit_post', 'bcs_cache_refresh', 0 ); // leaving a comment called edit_post
add_action( 'delete_post', 'bcs_cache_refresh', 0 );
add_action( 'publish_phone', 'bcs_cache_refresh', 0 );
add_action( 'clean_post_cache', 'bcs_cache_refresh' );
function bcs_cache_refresh_url($url) {
if ( empty( $url ) )
return false;
require_once ('bcs.class.php');
$cache_bucket = 'Bucket'; // 缓存所用的 Bucket,建议使用“私有”模式和单独 Bucket,不要混用
$cache_ak = 'AK'; // API Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_AK')
$cache_sk = 'SK'; // Scret Key,BAE 3.0 环境需要手动填写,2.0 可用 getenv('HTTP_BAE_ENV_SK')
$baidu_bcs = new BaiduBCS($cache_ak, $cache_sk);
$cache_object = '/' . md5( $url );
$baidu_bcs->delete_object($cache_bucket, $cache_object);
return true;
}
话说,SiteMap.XML 改一改,也可以缓存一下。敬请期待。
有人问这个有什么用,不是有 Cache 么?但是我想说,等到 Cache 收费时,用处就来了。