如何在WordPress多站点的指定子站点中复制或关联文章?
嘿,这个需求在WordPress多站点场景里太常见了!我给你整理了两种实用方案,你可以根据自己的技术能力来选:
方案一:用现成插件快速搞定(适合非技术用户)
直接用成熟插件就能实现和分类小工具一样的直观操作,不用写代码:
- Multisite Post Duplicator:在文章编辑页侧边添加一个 metabox,你可以勾选要复制到的子站点,还能自定义复制时是否保留分类、标签、特色图片、自定义字段等元数据,完全符合你的需求。
- Post Switcher & Copier for Multisite:除了复制功能,还支持在子站点之间快速切换编辑关联的文章,适合需要跨站点同步更新内容的场景。
方案二:自定义开发实现(适合有技术能力的用户)
如果想要更高的定制化程度,比如和现有系统深度集成,可以自己写代码实现。下面是完整的示例:
步骤1:添加文章编辑页的子站点选择 metabox
这段代码会在文章编辑页侧边添加一个类似分类选择的复选框列表,展示所有子站点:
function add_multisite_post_copy_metabox() { add_meta_box( 'multisite_post_copy', '复制/关联到子站点', 'render_multisite_post_copy_metabox', 'post', 'side', 'default' ); } add_action('add_meta_boxes', 'add_multisite_post_copy_metabox'); function render_multisite_post_copy_metabox($post) { // 获取所有子站点 $sites = get_sites(); // 读取已选择的站点记录 $selected_sites = get_post_meta($post->ID, '_copied_to_sites', true); $selected_sites = is_array($selected_sites) ? $selected_sites : []; echo '<div style="max-height:200px; overflow-y:auto;">'; foreach ($sites as $site) { // 跳过当前编辑的站点 if ($site->blog_id == get_current_blog_id()) continue; switch_to_blog($site->blog_id); $site_name = get_bloginfo('name'); restore_current_blog(); ?> <label style="display:block; margin-bottom:8px;"> <input type="checkbox" name="copied_sites[]" value="<?php echo esc_attr($site->blog_id); ?>" <?php checked(in_array($site->blog_id, $selected_sites)); ?>> <?php echo esc_html($site_name); ?> </label> <?php } echo '</div>'; // 添加安全验证nonce wp_nonce_field('multisite_post_copy_action', 'multisite_post_copy_nonce'); }
步骤2:处理保存时的文章复制逻辑
当你点击发布/更新文章时,这段代码会自动把文章复制到你勾选的子站点,并保留关键内容:
function save_multisite_post_copy($post_id) { // 权限和安全验证 if (!current_user_can('edit_post', $post_id)) return; if (!isset($_POST['multisite_post_copy_nonce']) || !wp_verify_nonce($_POST['multisite_post_copy_nonce'], 'multisite_post_copy_action')) return; if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return; $original_post = get_post($post_id); if (!$original_post) return; $selected_sites = isset($_POST['copied_sites']) ? array_map('intval', $_POST['copied_sites']) : []; $existing_copies = get_post_meta($post_id, '_copied_to_sites', true); $existing_copies = is_array($existing_copies) ? $existing_copies : []; // 复制文章到新选中的子站点 foreach ($selected_sites as $blog_id) { if (!in_array($blog_id, $existing_copies)) { switch_to_blog($blog_id); // 组装新文章数据 $new_post_data = [ 'post_title' => $original_post->post_title, 'post_content' => $original_post->post_content, 'post_excerpt' => $original_post->post_excerpt, 'post_status' => $original_post->post_status, 'post_type' => $original_post->post_type, 'post_author' => get_current_user_id(), // 可根据需求改为子站点对应作者ID 'comment_status' => $original_post->comment_status, 'ping_status' => $original_post->ping_status, ]; $new_post_id = wp_insert_post($new_post_data); // 复制分类和标签 wp_set_post_categories($new_post_id, wp_get_post_categories($post_id)); wp_set_post_tags($new_post_id, wp_get_post_tags($post_id, ['fields' => 'names'])); // 复制特色图片 $featured_image = get_post_thumbnail_id($post_id); if ($featured_image) { set_post_thumbnail($new_post_id, $featured_image); } // 复制自定义字段(跳过自身的复制记录) $meta_fields = get_post_meta($post_id); foreach ($meta_fields as $key => $values) { if ($key == '_copied_to_sites') continue; foreach ($values as $value) { add_post_meta($new_post_id, $key, $value); } } restore_current_blog(); // 记录已复制的站点ID add_post_meta($post_id, '_copied_to_sites', $blog_id, false); } } // (可选)如果需要取消复制时删除子站点的文章,可以取消下面的注释 // foreach ($existing_copies as $blog_id) { // if (!in_array($blog_id, $selected_sites)) { // switch_to_blog($blog_id); // // 需要提前保存原文章和复制文章的对应关系,这里仅做示例 // $copied_post_id = get_post_meta($post_id, '_copied_post_' . $blog_id, true); // if ($copied_post_id) wp_delete_post($copied_post_id, true); // restore_current_blog(); // delete_post_meta($post_id, '_copied_to_sites', $blog_id); // } // } } add_action('save_post', 'save_multisite_post_copy');
代码使用说明
把上面的代码添加到当前主题的functions.php文件里,或者创建一个自定义插件来存放(更推荐,主题更新不会丢失)。注意:操作前记得备份网站,避免出现意外。
如果你的需求是关联而非复制(即子站点显示主站点的文章,不生成独立副本),可以修改逻辑为保存子站点ID和原文章ID的关联关系,然后在子站点通过switch_to_blog()调用原文章内容即可。
内容的提问来源于stack exchange,提问作者Web CGAir
相关产品推荐
相关产品推荐

