BAE 3.0 上的 WordPress(五):巧用 BCS 缓存,让速度飞

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 收费时,用处就来了。

Twenty Twelve 主题添加 WordPress PageNavi 教程

Twenty Twelve 作为 WordPress 官方主题,小清新。但是,有一点我不喜欢,没有 Page Navi,而是采用传统方式。这也许是为了保证响应式设计不错位。但是,其实可以微调一下,我拿我有限的设备测试了一下,貌似不错位。

1)修改主题 Style.CSS,加入:

.page-numbers {
	padding: 0 5px 5px;
}

2)修改主题的 Functions.PHP,加入:

<?php
function nikbobo_pagenavi(){
	global $wp_query;   

	$big = 999999999; // need an unlikely integer

	$pagination = array(
		'base' => str_replace( $big, '%#%', get_pagenum_link( $big ) ),
		'format' => '',
		'total' => $wp_query->max_num_pages,
		'current' => max( 1, get_query_var('paged') ),
		'prev_text' => '<span class="meta-nav">←</span>',
		'next_text' => '<span class="meta-nav">→</span>',
		'show_all'     => False,
		'end_size'     => 1,
		'mid_size'     => 1
	);

	echo paginate_links($pagination); 
}
?>

3)在主题的 Functions.php,查找:

function twentytwelve_content_nav( $html_id ) {
	global $wp_query;

	$html_id = esc_attr( $html_id );

	if ( $wp_query->max_num_pages > 1 ) : ?>
		<nav id="<?php echo $html_id; ?>" class="navigation" role="navigation">
			<h3 class="assistive-text"><?php _e( 'Post navigation', 'twentytwelve' ); ?></h3>
			<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">←</span> Older posts', 'twentytwelve' ) ); ?></div>
			<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">→</span>', 'twentytwelve' ) ); ?></div>
		</nav><!-- #<?php echo $html_id; ?> .navigation -->
	<?php endif;
}

替换为:

function twentytwelve_content_nav( $html_id ) {
	global $wp_query;

	$html_id = esc_attr( $html_id );

	if ( $wp_query->max_num_pages > 1 ) : ?>
		<nav id="<?php echo $html_id; ?>" class="navigation" role="navigation">
			<h3 class="assistive-text"><?php _e( 'Post navigation', 'twentytwelve' ); ?></h3>
			<?php nikbobo_pagenavi(); ?>
		</nav><!-- #<?php echo $html_id; ?> .navigation -->
	<?php endif;
}

大功告成!

有没有发现?这其实和我的 ProwerV6 主题添加 WordPress PageNavi 教程是差不多的,唯一的区别就是 CSS。

话说,Twenty Thirteen 的 CSS,我也弄出来了,有时间再发吧!