WordPress 缺省模板重载
我们知道 WordPress 有一套自己的内容显示流程以及相关显示模板的加载方式,但在有些应用场景可能需要对缺省的流程和显示方式做客户化定制,比如从其它 URL 获取的内容,显示在文章的某个区域,本篇文章就介绍具体的实现方法。
这里主要通过 WordPress 的三个钩链来实现,包括 template_include、wp_head、the_content。
首先就是重载缺省的显示模板,也就是在加载预定义模板(主题)之前加载自定义内容及显示方式,这是通过钩链 template_include 来处理的。
...
//下面的代码可以放到插件的主程序中
add_filter(
'template_include',
function( $template ) {
//当前显示的内容是页面 “site_map” 时用自定义模板
if (is_page('site_map'))
return plugin_dir_path( __FILE__ ) . '/template.php';
return $template;
},
20
);
...
上面的代码中使用了过滤条件 is_page(),就是当前访问页面 “site_map” 时使用自定义模板,否则使用缺省模板。另外,过滤条件可以组合使用,比如 is_front_page()、is_single() 等。这里列出了各种条件函数的说明,可以参考一下。
在自定义模板中,使用 wp_remote_get 从其它 URL 地址处获取网页内容,并保持原来的显示样式,这需要分离获取页面 <head> 标签部分,与现有主题 <head> 中的内容合并,然后通过钩链 wp_head 来完成。
template.php
...
$url = 'http://localhost:8080';
$args = array(
'httpversion' => '1.1',
'headers' => array(
'referer' => home_url()
)
);
$response = wp_remote_get( $url, $args );
if ( is_wp_error( $response ) ) {
status_header( 500 );
require_once plugin_dir_path( __FILE__ ) . 'error.php';
} else {
$isStatic = preg_match(
'/\.(js|png|jpe?g|gif|svg|woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/i',
$_SERVER['REQUEST_URI']
);
header( 'content-type: ' . $response['headers']['content-type'] );
status_header( $response['response']['code'] );
//非静态资源处理
if (!$isStatic) {
//分离标签<head>和<body>中的内容
list($head, $rest) = preg_split('/(?=<\/head>)/', wp_remote_retrieve_body( $response ) );
list($body, $end) = preg_split('/(?=<\/body>)/', $rest);
//这里如果使用获取页面的<head>,就用echo $head,下面的代码做<head>内容合并
$head_data = preg_replace('/<\s+head\s+>/', '', $head, 1);
$body_data = preg_replace('/<\s+body\s+>/', '', $body, 1);
//使用钩链wp_head,当主题header.php中调用wp_head()时合并获取页面<head>内容
add_action('wp_head', function () {
global $head_data;
echo $head_data;
});
get_header(); //调用主题header.php,合并其<head>中的定义,同时渲染其内容
//这里如果直接显示获取页面<body>中的内容就调用 echo $body,使用the_content钩链是为了把内容显示在文章的显示区域
add_filter( 'the_content', function() {
global $body_data;
return $body_data;
}, -1 );
the_content();
//调用主题footer.php
get_footer();
//如果不做原主题相关内容的合并处理就调用 echo $end
} else {
//静态资源不做处理,原样输出
echo wp_remote_retrieve_body( $response );
}
}
...
通过上面的代码,可以把获取网页的内容显示在当前主题定义的文章显示区域,同时显示主题 header.php 和 footer.php 中的内容(显示侧边栏就调用 get_sidebar),如果仅需要显示获取网页的内容,就按照上面代码中的提示,不做合并处理即可。