如何实现两个WordPress站点文章同步:一份简明指南

作为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地址访问此文件,这是最关键的安全加固措施。

    测试与排查

    1. 测试同步:​ 在主站发布一篇新的测试文章,观察镜像站点是否在几秒内自动出现相同文章。
    2. 检查状态:​ 如果同步失败,首先登录镜像站后台,检查文章是否被创建为“草稿”。
    3. 查看日志:​ 主站同步失败时,会记录错误日志。请检查主站的 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

    评论

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注