作为WordPress站长,你是否曾担心主站因服务器故障或维护导致访客无法访问?建立一个内容同步的镜像站点是提升网站可用性的有效方案。本文将详细介绍一种通过代码实现两个WordPress站点文章自动同步的稳定方法,确保你的内容在主站出现问题时,依然可以通过备用站点正常访问。
一、同步方案概述本方案的核心原理是利用WordPress的发布钩子。当主站发布或更新文章时,系统会自动触发一个函数,该函数会收集文章的所有数据(如标题、内容、分类等),并通过HTTP POST请求将数据安全地发送到预先配置好的镜像站点。镜像站点接收到并验证数据后,会调用WordPress函数自动创建一篇相同的文章。重要提示与局限性:
- 适用对象: 此方法适用于有一定技术基础、喜欢动手的用户。
- 核心限制: 本方案仅同步文章文本内容(标题、正文、分类、标签)。文章中的图片、附件等媒体文件仍然链接到主站。如果主站无法访问,镜像站的文章图片也会失效。
- 操作前提: 操作前请务必备份两个站点的文件和数据库。
二、具体实现步骤第一步:配置镜像站点(接收端)在镜像站点的WordPress根目录下(与 wp-config.php文件同级),创建一个名为 post-receiver.php的文件(建议使用更不易被猜到的文件名)。然后填入以下代码:
<?php
/**
* WordPress文章同步接收端
* 文件:post-receiver.php
* 功能:接收主站推送的文章数据并创建文章
*/
// 绕过主题加载,直接初始化WordPress核心功能
define('WP_USE_THEMES', false);
require_once('wp-load.php');
// 安全配置
$secret_key = 'Your_Very_Long_Secret_Key_123!@#'; // !!!重要:请修改为一个长且复杂的密钥!!!
// 验证请求是否包含正确的密钥
if (!isset($_POST['key']) || $_POST['key'] !== $secret_key) {
status_header(403); // 返回403禁止访问状态码
echo 'Error: Authentication failed.';
exit; // 密钥错误,立即终止脚本
}
// 验证必要的数据是否存在
if (empty($_POST['title']) || empty($_POST['content'])) {
status_header(400); // 返回400错误请求状态码
echo 'Error: Missing title or content.';
exit;
}
// 处理文章分类
$category_names = explode(',', $_POST['category']);
$category_ids = array();
foreach ($category_names as $cat_name) {
$cat_name = trim($cat_name);
if (!empty($cat_name)) {
$cat_id = get_cat_ID($cat_name);
// 如果分类不存在,可以在这里选择自动创建
// if (!$cat_id) { $cat_id = wp_create_category($cat_name); }
if ($cat_id) {
$category_ids[] = $cat_id;
}
}
}
// 准备文章数据
$post_data = array(
'post_title' => wp_strip_all_tags($_POST['title']), // 清理标题
'post_content' => $_POST['content'],
'post_status' => 'publish', // 直接设置为“发布”
'post_author' => 1, // 发布文章的作者ID(1通常为管理员)
'post_date' => $_POST['date'],
'post_type' => $_POST['type'],
'tags_input' => $_POST['tags'],
'post_category' => $category_ids
);
// 插入文章到数据库
$post_id = wp_insert_post($post_data, true); // 返回WP_Error对象以便调试
// 检查文章是否成功创建
if (is_wp_error($post_id)) {
status_header(500);
echo 'Error: Failed to create post. ' . $post_id->get_error_message();
} else {
echo 'Success: Post synced successfully. ID: ' . $post_id;
}
?>
第二步:配置主站点(发送端)- 推荐插件方式为避免主题更新导致代码丢失,强烈建议将发送功能创建为一个独立插件。
1.在主站的 /wp-content/plugins/目录下,创建一个新文件夹,例如 post-sync-sender。
2.在该文件夹内创建一个PHP文件,命名为 post-sync-sender.php。
3.将以下代码复制到该文件中:
<?php
/**
* Plugin Name: 文章同步发送端
* Description: 实现主站文章发布后自动同步到镜像站点
* Version: 1.1
* Author: Leepoet.cn
*/
// 禁止直接访问
if (!defined('ABSPATH')) {
exit;
}
/**
* 主同步函数
* 使用 transition_post_status 钩子可靠地检测新文章的发布
*/
add_action('transition_post_status', 'post_sync_sender_on_publish', 10, 3);
function post_sync_sender_on_publish($new_status, $old_status, $post) {
// 只有当文章从非"发布"状态变为"发布"状态时才触发同步
if ($new_status === 'publish' && $old_status !== 'publish') {
// 确保只同步"文章"类型,排除页面、附件等
if ($post->post_type === 'post') {
post_sync_send_post($post->ID);
}
}
}
/**
* 执行同步任务
*/
function post_sync_send_post($post_ID) {
// 配置项 - 请根据实际情况修改
$secret_key = 'Your_Very_Long_Secret_Key_123!@#'; // 必须与镜像站设置的密钥一致
$receiver_url = 'https://your-mirror-site.com/post-receiver.php'; // 替换为你的镜像站点地址
$post = get_post($post_ID);
// 获取文章数据
$title = get_the_title($post_ID);
$content = get_post_field('post_content', $post_ID);
$date = $post->post_date;
// 处理分类
$post_categories = wp_get_post_categories($post_ID, array('fields' => 'names'));
$category_string = implode(',', $post_categories);
// 处理标签
$post_tags = wp_get_post_tags($post_ID, array('fields' => 'names'));
$tags_string = implode(',', $post_tags);
// 构建发送数据
$data = array(
'key' => $secret_key,
'title' => $title,
'content' => $content,
'date' => $date,
'category' => $category_string,
'type' => $post->post_type,
'tags' => $tags_string
);
// 使用cURL发送POST请求
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $receiver_url,
CURLOPT_RETURNTRANSFER => true, // 返回响应内容
CURLOPT_POST => true, // 启用POST
CURLOPT_POSTFIELDS => http_build_query($data), // 安全编码数据
CURLOPT_TIMEOUT => 15, // 设置15秒超时,避免主站卡顿
CURLOPT_SSL_VERIFYPEER => false, // 如果镜像站HTTPS证书有问题可设为false。生产环境建议解决证书问题。
CURLOPT_USERAGENT => 'WordPress/Post-Sync-Plugin', // 标识请求来源
));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
curl_close($ch);
// 记录日志,便于排查问题(可选,但强烈推荐)
if ($http_code != 200) {
error_log("[Post Sync Failed] Post ID: $post_ID. HTTP Code: $http_code. cURL Error: $curl_error. Response: $response");
} else {
error_log("[Post Sync Success] Post ID: $post_ID synced successfully.");
}
}
?>
4.保存文件后,进入WordPress后台的“插件”页面,找到并激活“文章同步发送端”的插件。
三、安全加固(重要)镜像站的 post-receiver.php文件是一个API端点,需要保护。
除了使用复杂密钥外,建议在镜像站的 .htaccess文件中(如果使用Apache服务器)添加IP限制,只允许你的主站服务器IP访问此文件。在 .htaccess的 # BEGIN WordPress规则之前添加:
# 保护文章同步接口
<Files "post-receiver.php">
Order Deny,Allow
Deny from all
Allow from 123.123.123.123 # 请替换为你的主站服务器IP地址
</Files>
安全性:确保 post.php 文件和同步插件中使用的密钥足够复杂(建议使用长字符串混合大小写字母、数字和符号),并定期更换。镜像站的 post.php 文件是一个API端点,存在被恶意利用的风险。
强烈建议通过配置网站服务器的 .htaccess (Apache/Nginx) 文件,限制仅允许您的主站服务器IP地址访问此文件,这是最关键的安全加固措施。
测试与排查
- 测试同步: 在主站发布一篇新的测试文章,观察镜像站点是否在几秒内自动出现相同文章。
- 检查状态: 如果同步失败,首先登录镜像站后台,检查文章是否被创建为“草稿”。
- 查看日志: 主站同步失败时,会记录错误日志。请检查主站的
wp-content/debug.log文件(如果已开启WP_DEBUG_LOG)或服务器的PHP错误日志,根据日志信息定位问题。
四、注意事项与局限性
•安全性: 确保 post.php文件和同步插件中使用的密钥足够复杂,并定期更换。镜像站的 post.php文件应被视为一个API端点,存在被恶意利用的风险,建议通过 .htaccess文件限制访问IP(如只允许主站服务器IP访问)。
•媒体文件不同步: 此方案仅同步文章文本内容(标题、正文、分类、标签)。文章中的图片、附件等媒体文件仍然存储在原始URL。如果主站无法访问,镜像站的文章图片也会失效。要实现媒体文件同步,需要更复杂的方案(如使用插件或将媒体文件托管在第三方CDN)。
•短代码兼容性: 如果文章使用了主站主题或插件特有的短代码,在镜像站可能无法正常解析。
•双向同步: 此方案是单向的(主站 -> 镜像站)。在镜像站对文章进行的修改不会同步回主站。
参考文献:https://www.zhihu.com/question/20087367/answer/767804443































































































































