当前位置:TMGM外汇官网-TMGM外汇交易平台 > 新闻资讯 > wordpress怎么把主网站的分类目录、导航菜单、页面、文章同步到子网站上面?

wordpress怎么把主网站的分类目录、导航菜单、页面、文章同步到子网站上面?

栏目:新闻资讯阅读:14发布时间:2026年11月5日
下面给你做一套完整的 WordPress Multisite 主站栏目 + 导航菜单自动同步系统。 按照你确认 […]

下面给你做一套完整的 WordPress Multisite 主站栏目 + 导航菜单自动同步系统。

按照你确认的要求,采用:

  • 网站环境:WordPress Multisite 多站点。

  • 服务器:宝塔面板 + Nginx。

  • 程序语言:PHP。

  • 部署方式:MU 插件(必须使用插件)。

  • 同步范围:文章分类目录 + 网站导航菜单。

  • 同步方向:主站 → 所有子站点。

  • 删除策略:主站删除栏目或菜单,子站点保留原有内容。

  • 第三方插件:不需要。

这套代码不需要修改 WordPress 核心文件,也不需要修改数据库结构。

一、最终实现效果

假设你的 WordPress 多站点有一个主站和三个子站点。

主站(统一管理)

数据源

文章分类目录

  • 外汇资讯

  • 外汇知识

  • 交易平台

  • 行业动态
    网站导航菜单

  • 首页

  • 关于我们

  • 新闻资讯

  • 联系我们

PHP 自动同步

子站点 A

已同步

分类目录

导航菜单

子站点 B

已同步

分类目录

导航菜单

子站点 C

已同步

分类目录

导航菜单

具体效果:

操作 子站点是否同步
主站新增分类 自动创建
主站修改分类名称 自动修改
主站修改分类别名 自动修改
主站新增子分类 自动创建并关联父分类
主站删除分类 子站点保留
主站新增导航菜单 自动创建
主站修改导航菜单 自动更新
主站新增菜单项目 自动添加
主站删除菜单 子站点保留

另外,还会提供一个手动同步按钮,方便第一次部署时将主站现有的所有分类和菜单同步到子站点。

需要特别说明: 导航菜单同步的是菜单结构和菜单项目,不会自动复制页面、文章或媒体文件。菜单链接指向的页面和分类需要在子站点存在,代码会根据页面路径、分类别名进行匹配。

二、第一步:进入宝塔面板,找到网站目录

首先登录宝塔面板。

  1. 点击左侧「网站」。

  2. 找到你的 WordPress 主站。

  3. 点击「根目录」。

  4. 找到 WordPress 程序目录。

正常情况下,目录结构如下:

/www/wwwroot/你的域名/
│
├── wp-admin/
├── wp-content/
│   ├── plugins/
│   ├── themes/
│   ├── uploads/
│   └── mu-plugins/
│
├── wp-includes/
├── wp-config.php
└── index.php

我们要使用的是:

wp-content/mu-plugins/

注意:mu-plugins 是 WordPress 的特殊插件目录,默认情况下可能不存在,需要自己创建。

1. 创建 mu-plugins 文件夹

进入:

/www/wwwroot/你的域名/wp-content/

点击宝塔文件管理器的「新建目录」。

目录名称填写:

mu-plugins

最终得到:

/www/wwwroot/你的域名/wp-content/mu-plugins/

2. 创建 PHP 文件

进入刚刚创建的 mu-plugins 文件夹。

新建文件:

multisite-category-menu-sync.php

完整路径:

/www/wwwroot/你的域名/wp-content/mu-plugins/multisite-category-menu-sync.php
重要

文件名称可以保持不变,后面所有代码都放在这个文件中。

三、第二步:配置 PHP 自动同步代码

下面是核心代码。

请将下面的代码完整复制到 multisite-category-menu-sync.php 文件中。不要遗漏开头和结尾。


<?php
/**
 * Plugin Name: Multisite Category & Menu Sync
 * Description: Synchronize main-site categories and navigation menus to all subsites.
 * Version: 1.0.0
 * Author: Custom
 */

if (!defined('ABSPATH')) {
    exit;
}

if (!is_multisite()) {
    return;
}

/**
 * 全局同步锁,防止子站点同步时再次触发同步。
 */
$GLOBALS['mscms_syncing'] = false;

/**
 * 获取主站 ID。
 */
function mscms_main_blog_id() {
    return (int) get_main_site_id();
}

/**
 * 判断当前是否为主站。
 */
function mscms_is_main_site() {
    return get_current_blog_id() === mscms_main_blog_id();
}

/**
 * 获取主站分类目录数据。
 */
function mscms_get_source_term($term_id) {
    $main_id = mscms_main_blog_id();

    switch_to_blog($main_id);

    $term = get_term($term_id, 'category');

    if (!$term || is_wp_error($term)) {
        restore_current_blog();
        return false;
    }

    $data = array(
        'term_id'     => (int) $term->term_id,
        'name'        => $term->name,
        'slug'        => $term->slug,
        'description' => $term->description,
        'parent'      => (int) $term->parent,
    );

    restore_current_blog();

    return $data;
}

/**
 * 将主站分类同步到当前目标子站点。
 * 支持多级分类及父子关系。
 */
function mscms_sync_category_recursive($term_id, $target_blog_id) {

    $source_blog_id = mscms_main_blog_id();

    $data = mscms_get_source_term($term_id);

    if (!$data) {
        return false;
    }

    // 先同步父分类,确保父子关系正确。
    $parent_id = 0;

    if (!empty($data['parent'])) {
        $parent_id = mscms_sync_category_recursive(
            $data['parent'],
            $target_blog_id
        );

        if (!$parent_id) {
            return false;
        }
    }

    $map_option = 'mscms_term_map_' . $source_blog_id;
    $mapping = get_option($map_option, array());

    $source_id = (int) $data['term_id'];

    $dest_id = isset($mapping[$source_id])
        ? (int) $mapping[$source_id]
        : 0;

    $dest_term = $dest_id
        ? get_term($dest_id, 'category')
        : false;

    $args = array(
        'slug'        => $data['slug'],
        'description' => $data['description'],
        'parent'      => $parent_id,
    );

    // 已有映射的分类:更新。
    if ($dest_term && !is_wp_error($dest_term)) {

        $result = wp_update_term(
            $dest_id,
            'category',
            array_merge($args, array(
                'name' => $data['name'],
            ))
        );

    } else {

        // 没有映射时,优先寻找同 slug 分类,避免重复创建。
        $existing = term_exists(
            $data['slug'],
            'category'
        );

        if ($existing) {

            $dest_id = is_array($existing)
                ? (int) $existing['term_id']
                : (int) $existing;

            $result = wp_update_term(
                $dest_id,
                'category',
                array_merge($args, array(
                    'name' => $data['name'],
                ))
            );

        } else {

            // 不存在时创建分类。
            $result = wp_insert_term(
                $data['name'],
                'category',
                $args
            );
        }
    }

    if (is_wp_error($result)) {
        error_log(
            '[Mscms] Category sync error: ' .
            $result->get_error_message()
        );

        return false;
    }

    $dest_id = is_array($result)
        ? (int) $result['term_id']
        : (int) $dest_id;

    // 保存主站分类 ID 与子站点分类 ID 的对应关系。
    $mapping[$source_id] = $dest_id;

    update_option($map_option, $mapping, false);

    return $dest_id;
}

/**
 * 同步单个分类到指定子站点。
 */
function mscms_sync_category($term_id, $target_blog_id) {

    if ($GLOBALS['mscms_syncing']) {
        return;
    }

    $GLOBALS['mscms_syncing'] = true;

    switch_to_blog($target_blog_id);

    try {
        mscms_sync_category_recursive(
            (int) $term_id,
            $target_blog_id
        );
    } finally {
        restore_current_blog();
        $GLOBALS['mscms_syncing'] = false;
    }
}

/**
 * 读取主站全部菜单及菜单项目。
 * 同时记录页面、分类的 slug,便于在子站点匹配。
 */
function mscms_get_source_menus() {

    $main_id = mscms_main_blog_id();

    switch_to_blog($main_id);

    $menus = wp_get_nav_menus();
    $locations = get_nav_menu_locations();

    $result = array();

    foreach ($menus as $menu) {

        $items = wp_get_nav_menu_items($menu->term_id);

        $menu_items = array();

        foreach ((array) $items as $item) {

            $object_slug = '';

            if ($item->type === 'post_type') {

                $post = get_post($item->object_id);

                if ($post) {
                    $object_slug = $post->post_name;
                }

            } elseif ($item->type === 'taxonomy') {

                $term = get_term(
                    $item->object_id,
                    $item->object
                );

                if ($term && !is_wp_error($term)) {
                    $object_slug = $term->slug;
                }
            }

            $menu_items[] = array(
                'id'          => (int) $item->ID,
                'title'       => $item->title,
                'type'        => $item->type,
                'object'      => $item->object,
                'object_id'   => (int) $item->object_id,
                'url'         => $item->url,
                'description' => $item->description,
                'attr_title'  => $item->attr_title,
                'target'      => $item->target,
                'classes'     => (array) $item->classes,
                'xfn'         => $item->xfn,
                'parent'      => (int) $item->menu_item_parent,
                'order'       => (int) $item->menu_order,
                'object_slug' => $object_slug,
            );
        }

        $result[] = array(
            'id'    => (int) $menu->term_id,
            'name'  => $menu->name,
            'slug'  => $menu->slug,
            'items' => $menu_items,
        );
    }

    restore_current_blog();

    return array(
        'menus'     => $result,
        'locations' => $locations,
    );
}

/**
 * 将主站菜单项目所指向的对象,
 * 转换成目标子站点中的对象 ID。
 */
function mscms_get_target_menu_object_id($item) {

    if ($item['type'] === 'custom') {
        return 0;
    }

    if ($item['type'] === 'post_type') {

        $post = get_page_by_path(
            $item['object_slug'],
            OBJECT,
            $item['object']
        );

        return $post ? (int) $post->ID : false;
    }

    if ($item['type'] === 'taxonomy') {

        $term = get_term_by(
            'slug',
            $item['object_slug'],
            $item['object']
        );

        return $term ? (int) $term->term_id : false;
    }

    return false;
}

/**
 * 将主站所有导航菜单同步到指定子站点。
 */
function mscms_sync_menus_to_blog($target_blog_id) {

    $source_data = mscms_get_source_menus();

    $menus = $source_data['menus'];
    $source_locations = $source_data['locations'];

    $GLOBALS['mscms_syncing'] = true;

    switch_to_blog($target_blog_id);

    try {

        $menu_mapping = get_option(
            'mscms_menu_map_' . mscms_main_blog_id(),
            array()
        );

        $item_mapping = get_option(
            'mscms_menu_item_map_' . mscms_main_blog_id(),
            array()
        );

        $dest_menu_ids = array();

        foreach ($menus as $menu) {

            $source_menu_id = $menu['id'];

            // 根据 slug 找到目标菜单。
            $dest_menu = wp_get_nav_menu_object(
                $menu['slug']
            );

            if (!$dest_menu) {

                // 不存在时创建菜单。
                $new_menu_id = wp_update_nav_menu_object(
                    0,
                    array(
                        'menu-name' => $menu['name'],
                    )
                );

                if (is_wp_error($new_menu_id)) {
                    continue;
                }

                $dest_menu_id = (int) $new_menu_id;

            } else {

                $dest_menu_id = (int) $dest_menu->term_id;

                // 更新菜单名称。
                wp_update_nav_menu_object(
                    $dest_menu_id,
                    array(
                        'menu-name' => $menu['name'],
                    )
                );
            }

            $menu_mapping[$source_menu_id] = $dest_menu_id;

            $dest_menu_ids[$menu['slug']] = $dest_menu_id;

            // 按菜单顺序排列,尽量确保父项目先创建。
            usort($menu['items'], function($a, $b) {
                return $a['order'] <=> $b['order'];
            });

            foreach ($menu['items'] as $item) {

                $source_item_id = $item['id'];

                $dest_item_id = isset(
                    $item_mapping[$source_item_id]
                )
                    ? (int) $item_mapping[$source_item_id]
                    : 0;

                // 转换菜单项目对应的页面或分类 ID。
                $object_id = mscms_get_target_menu_object_id(
                    $item
                );

                // 目标站点没有对应页面或分类时跳过。
                if ($object_id === false) {
                    continue;
                }

                // 处理父菜单项目关系。
                $parent_id = 0;

                if (!empty($item['parent'])) {

                    $parent_id = isset(
                        $item_mapping[$item['parent']]
                    )
                        ? (int) $item_mapping[$item['parent']]
                        : 0;
                }

                $args = array(
                    'menu-item-title'       => $item['title'],
                    'menu-item-type'        => $item['type'],
                    'menu-item-object'      => $item['object'],
                    'menu-item-object-id'   => $object_id,
                    'menu-item-url'         => $item['url'],
                    'menu-item-description' => $item['description'],
                    'menu-item-attr-title'  => $item['attr_title'],
                    'menu-item-target'      => $item['target'],
                    'menu-item-classes'     => $item['classes'],
                    'menu-item-xfn'         => $item['xfn'],
                    'menu-item-parent-id'   => $parent_id,
                    'menu-item-position'    => $item['order'],
                    'menu-item-status'      => 'publish',
                );

                // 已有项目更新,没有则创建。
                $result = wp_update_nav_menu_item(
                    $dest_menu_id,
                    $dest_item_id,
                    $args
                );

                if (!is_wp_error($result) && $result) {

                    $item_mapping[$source_item_id] =
                        (int) $result;
                }
            }
        }

        update_option(
            'mscms_menu_map_' . mscms_main_blog_id(),
            $menu_mapping,
            false
        );

        update_option(
            'mscms_menu_item_map_' . mscms_main_blog_id(),
            $item_mapping,
            false
        );

        // 同步主题导航菜单位置。
        $current_locations = get_nav_menu_locations();
        $registered_locations = get_registered_nav_menus();

        foreach ($source_locations as $location => $source_menu_id) {

            if (!isset($registered_locations[$location])) {
                continue;
            }

            $source_menu = wp_get_nav_menu_object(
                $source_menu_id
            );

            if (!$source_menu) {
                continue;
            }

            if (isset($dest_menu_ids[$source_menu->slug])) {

                $current_locations[$location] =
                    $dest_menu_ids[$source_menu->slug];
            }
        }

        set_theme_mod(
            'nav_menu_locations',
            $current_locations
        );

    } finally {

        restore_current_blog();

        $GLOBALS['mscms_syncing'] = false;
    }
}

/**
 * 同步主站全部分类和菜单到所有子站点。
 */
function mscms_sync_all_sites() {

    if (!is_multisite()) {
        return;
    }

    $main_id = mscms_main_blog_id();

    // 获取主站全部分类。
    switch_to_blog($main_id);

    $categories = get_terms(array(
        'taxonomy'   => 'category',
        'hide_empty' => false,
    ));

    restore_current_blog();

    // 获取网络内所有站点。
    $sites = get_sites(array(
        'number' => 0,
        'deleted' => 0,
        'archived' => 0,
        'spam' => 0,
    ));

    $count = 0;

    foreach ($sites as $site) {

        $target_blog_id = (int) $site->blog_id;

        // 跳过主站。
        if ($target_blog_id === $main_id) {
            continue;
        }

        // 逐个同步分类。
        if (!is_wp_error($categories)) {

            foreach ($categories as $category) {

                mscms_sync_category(
                    $category->term_id,
                    $target_blog_id
                );
            }
        }

        // 同步导航菜单。
        mscms_sync_menus_to_blog(
            $target_blog_id
        );

        $count++;
    }

    update_site_option(
        'mscms_last_sync',
        current_time('mysql')
    );

    update_site_option(
        'mscms_last_sync_count',
        $count
    );

    return $count;
}

/**
 * 主站新增分类时自动同步。
 */
function mscms_category_created($term_id) {

    if (
        $GLOBALS['mscms_syncing'] ||
        !mscms_is_main_site()
    ) {
        return;
    }

    $sites = get_sites(array(
        'number' => 0,
        'deleted' => 0,
        'archived' => 0,
        'spam' => 0,
    ));

    foreach ($sites as $site) {

        if ((int) $site->blog_id === mscms_main_blog_id()) {
            continue;
        }

        mscms_sync_category(
            $term_id,
            (int) $site->blog_id
        );
    }
}

add_action(
    'created_category',
    'mscms_category_created',
    20,
    1
);

/**
 * 主站修改分类时自动同步。
 */
add_action(
    'edited_category',
    'mscms_category_created',
    20,
    1
);

/**
 * 主站更新菜单时同步。
 */
function mscms_menu_changed($menu_id = 0) {

    if (
        $GLOBALS['mscms_syncing'] ||
        !mscms_is_main_site()
    ) {
        return;
    }

    $sites = get_sites(array(
        'number' => 0,
        'deleted' => 0,
        'archived' => 0,
        'spam' => 0,
    ));

    foreach ($sites as $site) {

        if ((int) $site->blog_id === mscms_main_blog_id()) {
            continue;
        }

        mscms_sync_menus_to_blog(
            (int) $site->blog_id
        );
    }
}

add_action(
    'wp_update_nav_menu',
    'mscms_menu_changed',
    20,
    1
);

add_action(
    'wp_update_nav_menu_item',
    'mscms_menu_changed',
    20,
    3
);

/**
 * 新建子站点后,自动执行同步。
 */
function mscms_new_site_created($new_site) {

    if (
        $GLOBALS['mscms_syncing'] ||
        !is_object($new_site)
    ) {
        return;
    }

    $blog_id = (int) $new_site->blog_id;

    if ($blog_id === mscms_main_blog_id()) {
        return;
    }

    $GLOBALS['mscms_syncing'] = true;

    try {

        switch_to_blog($blog_id);

        restore_current_blog();

        // 这里延后到站点初始化完成后执行。
        // 由后续的同步任务或手动同步完成首次同步。

    } finally {

        $GLOBALS['mscms_syncing'] = false;
    }
}

add_action(
    'wp_initialize_site',
    'mscms_new_site_created',
    100,
    1
);

/**
 * 网络管理后台添加同步管理页面。
 */
function mscms_add_network_admin_page() {

    add_submenu_page(
        'settings.php',
        '多站点栏目菜单同步',
        '栏目菜单同步',
        'manage_network',
        'mscms-sync',
        'mscms_admin_page'
    );
}

add_action(
    'network_admin_menu',
    'mscms_add_network_admin_page'
);

/**
 * 管理页面。
 */
function mscms_admin_page() {

    if (!current_user_can('manage_network')) {
        wp_die('没有权限访问此页面。');
    }

    $last_sync = get_site_option(
        'mscms_last_sync',
        '尚未同步'
    );

    $last_count = get_site_option(
        'mscms_last_sync_count',
        0
    );

    ?>
    <div class="wrap">

        <h1>WordPress 多站点栏目菜单同步</h1>

        <p>
            此功能将主站文章分类目录和导航菜单同步到所有子站点。
        </p>

        <table class="widefat striped" style="max-width:700px">

            <tr>
                <td><strong>同步方向</strong></td>
                <td>主站 → 所有子站点</td>
            </tr>

            <tr>
                <td><strong>同步内容</strong></td>
                <td>文章分类目录 + 导航菜单</td>
            </tr>

            <tr>
                <td><strong>删除策略</strong></td>
                <td>保留子站点已有分类和菜单项目</td>
            </tr>

            <tr>
                <td><strong>上次同步时间</strong></td>
                <td><?php echo esc_html($last_sync); ?></td>
            </tr>

            <tr>
                <td><strong>上次同步子站点数量</strong></td>
                <td><?php echo esc_html($last_count); ?></td>
            </tr>

        </table>

        <h2>手动执行全站同步</h2>

        <p>
            点击下面的按钮,将主站现有的分类和导航菜单同步到所有子站点。
        </p>

        <form method="post"
              action="<?php echo esc_url(admin_url('admin-post.php')); ?>">

            <input type="hidden"
                   name="action"
                   value="mscms_manual_sync">

            <?php wp_nonce_field('mscms_manual_sync'); ?>

            <?php submit_button('立即同步所有子站点'); ?>

        </form>

        <?php if (isset($_GET['mscms_done'])) : ?>

            <div class="notice notice-success is-dismissible">
                <p>同步任务已执行,请检查子站点分类和导航菜单。</p>
            </div>

        <?php endif; ?>

    </div>
    <?php
}

/**
 * 手动同步处理。
 */
function mscms_manual_sync_handler() {

    if (!current_user_can('manage_network')) {
        wp_die('没有权限执行此操作。');
    }

    check_admin_referer('mscms_manual_sync');

    mscms_sync_all_sites();

    wp_safe_redirect(
        add_query_arg(
            'mscms_done',
            '1',
            network_admin_url('settings.php?page=mscms-sync')
        )
    );

    exit;
}

add_action(
    'admin_post_mscms_manual_sync',
    'mscms_manual_sync_handler'
);

四、第三步:补充新建子站点自动同步功能

上面代码还需要补充一个小地方:新建子站点时,不应该只等待你手动同步,而应该自动执行首次同步。

请在 PHP 文件中找到下面这段:

function mscms_new_site_created($new_site) {

从这个函数开始,一直到它后面的:

add_action(
    'wp_initialize_site',
    'mscms_new_site_created',
    100,
    1
);

将这一整段替换为下面的代码:


/**
 * 新建子站点后,自动同步主站分类和菜单。
 */
function mscms_new_site_created($new_site) {

    if (
        empty($new_site->blog_id) ||
        !is_multisite()
    ) {
        return;
    }

    $target_blog_id = (int) $new_site->blog_id;

    if ($target_blog_id === mscms_main_blog_id()) {
        return;
    }

    // 获取主站全部分类。
    $main_id = mscms_main_blog_id();

    switch_to_blog($main_id);

    $categories = get_terms(array(
        'taxonomy'   => 'category',
        'hide_empty' => false,
    ));

    restore_current_blog();

    // 同步分类。
    if (!is_wp_error($categories)) {

        foreach ($categories as $category) {

            mscms_sync_category(
                $category->term_id,
                $target_blog_id
            );
        }
    }

    // 同步导航菜单。
    mscms_sync_menus_to_blog($target_blog_id);
}

add_action(
    'wp_initialize_site',
    'mscms_new_site_created',
    100,
    1
);

这样,新建子站点并完成 WordPress 初始化后,就会自动同步主站已有的分类目录和导航菜单。

五、第四步:保存代码并检查部署

现在进行保存。

  1. 回到宝塔文件管理器。

  2. 打开 multisite-category-menu-sync.php。

  3. 检查代码是否完整。

  4. 点击保存。

文件位置:

/www/wwwroot/你的域名/wp-content/mu-plugins/multisite-category-menu-sync.php

检查 PHP 版本

建议使用:

  • PHP 7.4

  • PHP 8.0

  • PHP 8.1

  • PHP 8.2

建议优先使用 PHP 8.1 或 8.2,并确保 WordPress 本身兼容。

本代码使用 PHP 7 及以上语法。

检查插件是否加载

登录 WordPress 主站后台:

进入:

「插件 → 已安装插件 → 必须使用的插件」

正常情况下应该看到:

Multisite Category & Menu Sync

已加载

必须使用的插件(MU Plugins)

PHP 文件已成功加载

多站点环境检测通过

注意:MU 插件不需要点击启用,它只要放在正确的目录中就会自动加载。

六、第五步:第一次手动同步

这是非常重要的一步。

代码部署完成后,第一次需要手动执行全站同步。

操作路径:

WordPress 主站后台
    ↓
我的站点(My Sites)
    ↓
网络管理(Network Admin)
    ↓
设置(Settings)
    ↓
栏目菜单同步

也可以尝试直接访问:

https://你的主站域名/wp-admin/network/settings.php?page=mscms-sync

进入后,你会看到:

WordPress 多站点栏目菜单同步

同步方向

主站 → 所有子站点

同步内容

分类目录 + 导航菜单

删除策略

保留子站点原有数据

手动执行全站同步

第一次部署时,点击按钮将主站现有栏目和菜单同步到所有子站点。

立即同步所有子站点

这是后台操作界面的示意图

点击「立即同步所有子站点」。

系统会依次执行:

  1. 读取主站所有文章分类。

  2. 检查每个子站点是否存在对应分类。

  3. 存在则更新,不存在则创建。

  4. 按照父子关系同步多级分类。

  5. 读取主站全部导航菜单。

  6. 在子站点创建或更新菜单。

  7. 匹配菜单项目对应的页面和分类。

  8. 尝试同步主题导航位置。

完成后,后台会显示上次同步时间和执行过的子站点数量。

注意: 当前代码是逐个站点同步,适合一般规模的多站点网络。如果子站点非常多(例如上百个),建议后续增加分批任务和失败重试机制。

七、第六步:测试自动同步是否正常

建议不要直接在正式网站上大规模操作,先拿一个子站点进行测试。

假设:

主站:https://www.example.com

子站点1:https://site1.example.com

子站点2:https://site2.example.com

以上域名只是测试示例。

测试一:主站新增分类

登录主站后台:

「文章 → 分类目录」

新建以下分类:

名称 别名(Slug)
外汇资讯 forex-news
外汇知识 forex-knowledge
交易平台 trading-platform
行业动态 industry-news

点击添加分类。

然后分别登录子站点后台:

「文章 → 分类目录」

检查是否出现上述四个分类。

预期结果

所有子站点都自动出现相同的分类。

测试二:测试多级分类

在主站建立:

外汇资讯
├── 行业新闻
├── 市场分析
└── 平台动态

其中:

  • 外汇资讯:父分类。

  • 行业新闻:子分类。

  • 市场分析:子分类。

  • 平台动态:子分类。

保存后,登录子站点检查。

预期结果:

外汇资讯
├── 行业新闻
├── 市场分析
└── 平台动态

父子级关系应该保持一致。

测试三:测试修改分类

在主站将:

外汇资讯

修改成:

外汇市场资讯

同时修改 Slug:

forex-news

修改后检查子站点。

预期结果:

  • 分类名称自动修改。

  • Slug 自动修改。

  • 原有子分类仍然保留。

  • 不会重复创建一个新的分类。

测试四:测试删除分类

在主站删除:

行业动态

然后登录子站点。

预期结果:

子站点仍然保留:

行业动态

这是按照你要求的删除策略设计的。

测试五:测试导航菜单

登录主站后台:

「外观 → 菜单」

创建一个菜单:

主导航

添加以下菜单项目:

首页
关于我们
新闻资讯
联系我们

保存菜单。

然后检查子站点:

「外观 → 菜单」

预期结果:

  • 自动创建主导航菜单。

  • 自动添加菜单项目。

  • 尽可能匹配对应页面。

  • 保持菜单项目顺序。

  • 保持父子级菜单关系。

  • 尝试匹配相同名称的主题菜单位置。

注意:子站点必须存在对应的页面,否则代码会跳过无法匹配的页面菜单项,不会自动创建页面。

八、第七步:两个建议修改的小地方

为了让系统更稳定,我建议再做两个调整。

1. 修正网络后台提交地址

在代码中找到:

action="<?php echo esc_url(admin_url('admin-post.php')); ?>"

改成:

action="<?php echo esc_url(network_admin_url('admin-post.php')); ?>"

这样在网络管理后台执行同步时,会使用网络管理的正确地址。

2. 优先使用菜单 ID 映射,防止菜单重复创建

在 mscms_sync_menus_to_blog() 中,找到:

// 根据 slug 找到目标菜单。
$dest_menu = wp_get_nav_menu_object(
    $menu['slug']
);

替换成:

// 优先根据保存的映射查找菜单。
$mapped_menu_id = isset(
    $menu_mapping[$source_menu_id]
)
    ? (int) $menu_mapping[$source_menu_id]
    : 0;

$dest_menu = $mapped_menu_id
    ? wp_get_nav_menu_object($mapped_menu_id)
    : false;

// 如果映射不存在,再通过 slug 查找。
if (!$dest_menu) {
    $dest_menu = wp_get_nav_menu_object(
        $menu['slug']
    );
}

这样可以减少菜单名称或别名发生变化时重复创建菜单的情况。

九、常见问题及解决办法

问题 可能原因 解决办法
MU 插件没有显示 文件路径错误 检查 mu-plugins 目录
主站新增分类不自动同步 PHP 报错或 Hook 未执行 查看 PHP 错误日志
子站点没有分类 子站点被排除或同步失败 手动全站同步
分类重复创建 旧分类映射缺失 检查分类 slug 和映射
导航菜单没有出现 菜单创建失败 检查菜单同步日志
菜单项目缺失 子站点不存在对应页面 先创建对应页面
菜单位置没有变化 子站点主题位置不同 检查主题注册的菜单位置

宝塔查看 PHP 错误日志

进入:

宝塔面板
  ↓
网站
  ↓
你的 WordPress 网站
  ↓
日志

也可以查看 PHP 错误日志。

代码中已经加入了分类同步错误记录:

error_log(
    '[Mscms] Category sync error: ' .
    $result->get_error_message()
);

如果遇到分类同步失败,可以通过日志定位问题。

十、上线前特别注意的事项

这套代码已经覆盖基本的分类和菜单同步流程,但正式投入 SEO 网站使用之前,有几个细节需要了解:

  1. 不会同步文章内容:只同步分类目录和导航菜单。

  2. 不会同步页面内容:菜单引用的页面需要在子站点提前创建。

  3. 不会删除子站点原有菜单项目:主站删除菜单项目后,子站点保留。

  4. 不会自动同步其他自定义分类法:目前只处理 WordPress 默认的 category。

  5. 导航菜单位置需要主题兼容:主站和子站点最好使用相同主题,并注册相同的菜单位置。

  6. 大规模站点需要分批处理:如果子站点达到几十至上百个,建议增加 WP-Cron 或队列处理,避免 PHP 执行超时。

另外,建议先备份数据库和 wp-content,再部署到正式网站。

十一、我建议你下一步完善的功能

目前这套属于第一版基础同步系统。如果你准备长期运营多个 SEO 子站点,我建议后续升级到 V2 版本:

功能 V1 基础版 V2 增强版
分类自动同步
支持
支持
菜单自动同步
支持
支持
多级分类
支持
支持
同步日志记录 基础 PHP 日志 独立日志后台
同步失败重试 不支持 支持
指定子站点同步 不支持 支持
定时自动校验 不支持 支持
菜单删除同步 保留子站点 可配置
分类与菜单映射管理 数据库存储 后台可视化管理

我的建议: 如果你的主要目的是运营多个 SEO 网站,最好升级成 V2,尤其是增加同步日志、失败重试、指定子站点和后台管理功能。

这样以后你只需要登录主站后台,就能统一管理所有子站点的栏目和导航,不需要每个网站单独操作。

部署完成后,我也可以继续帮你检查 PHP 错误日志和同步结果,确保这套系统真正运行正常。

版权说明

本文标题:wordpress怎么把主网站的分类目录、导航菜单、页面、文章同步到子网站上面?,收录于EC Markets外汇官网平台:【新闻资讯】栏目,本文禁止任何商业性转载、分享,如需转载需联系小编并注明来源;部分内容整理自网络,如有侵权请联系删除。

相关文章