✨专业 WordPress 开发,定制建站,高效上线,合作即享优化服务!🚀

批量将文章转换为 WooCommerce 商品插件

功能说明

功能一:将所有文章分类同步为 WooCommerce 商品分类(保留层级结构)

  • 使用文章分类的名称和 slug 创建 product_cat

  • 保留父子层级

  • 自动跳过已存在分类

  • 可从后台点击按钮一键执行

功能二:批量将文章转换为 WooCommerce 商品

  • 多选文章分类进行批量转换

  • 绑定已同步的商品分类(按 slug 匹配)

  • 支持分页处理防止超时

  • 跳过已转换文章(使用 _converted_from_post 标记)


🧾 文件:batch-convert-posts-to-products.php

你可以将这份文件内容保存为插件:

<?php
/**
 * Plugin Name: 批量将文章转换为商品
 * Description: 将 WordPress 文章批量转换为 WooCommerce 商品,保持分类结构。
 * Version: 1.0
 * Author: 半岛
 */

// 添加后台工具菜单
add_action('admin_menu', function() {
    add_management_page(
        '文章转商品工具',
        '文章转商品工具',
        'manage_options',
        'batch-convert-posts-to-products',
        'render_batch_convert_page'
    );
});

// 渲染后台页面
function render_batch_convert_page() {
    $categories = get_categories(['hide_empty' => false]);
    ?>
    <div class="wrap">
        <h1>批量将文章转换为商品</h1>
        <h2>步骤 1:同步文章分类为商品分类(保留层级)</h2>
        <button id="sync-categories" class="button">同步文章分类到商品分类</button>
        <div id="sync-result" style="margin-top:10px;"></div>

        <h2 style="margin-top:40px;">步骤 2:选择分类批量转换文章为商品</h2>
        <form id="convert-form">
            <div style="max-height:300px; overflow:auto; border:1px solid #ccc; padding:10px;">
                <?= render_category_checkboxes($categories); ?>
            </div>
            <br>
            <button type="button" id="start-convert" class="button button-primary">开始转换</button>
        </form>
        <div id="convert-status" style="margin-top:20px; font-weight:bold;"></div>
    </div>

    <script>
    (function(){
        let offset = 0;
        let convertedTotal = 0;
        let selectedCats = [];

        // 同步分类按钮事件
        document.getElementById('sync-categories').addEventListener('click', function(){
            const btn = this;
            btn.disabled = true;
            btn.textContent = '同步中...';
            fetch(ajaxurl + '?action=sync_post_categories_to_product_cat')
                .then(res => res.json())
                .then(data => {
                    if (data.success) {
                        document.getElementById('sync-result').innerHTML = '✅ 同步完成,共同步分类:' + data.count;
                    } else {
                        document.getElementById('sync-result').innerHTML = '❌ 同步失败:' + data.message;
                    }
                    btn.disabled = false;
                    btn.textContent = '同步文章分类到商品分类';
                });
        });

        function updateStatus(msg) {
            document.getElementById('convert-status').innerHTML = msg;
        }

        function convertBatch() {
            if (!selectedCats.length) {
                updateStatus('请先选择分类');
                document.getElementById('start-convert').disabled = false;
                return;
            }

            const data = new URLSearchParams();
            data.append('action', 'ajax_batch_convert_posts_to_products');
            data.append('offset', offset);
            selectedCats.forEach(cat => data.append('cats[]', cat));

            fetch(ajaxurl, {
                method: 'POST',
                body: data,
                credentials: 'same-origin',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            }).then(res => res.json())
              .then(data => {
                  if (data.success) {
                      convertedTotal += data.converted;
                      offset += data.converted;
                      updateStatus(`已转换文章:${convertedTotal}`);
                      if (data.has_more) {
                          convertBatch();
                      } else {
                          updateStatus(`✅ 转换完成,总共转换文章:${convertedTotal}`);
                          document.getElementById('start-convert').disabled = false;
                      }
                  } else {
                      updateStatus('转换失败: ' + data.message);
                      document.getElementById('start-convert').disabled = false;
                  }
              }).catch(err => {
                  updateStatus('请求失败: ' + err.message);
                  document.getElementById('start-convert').disabled = false;
              });
        }

        document.getElementById('start-convert').addEventListener('click', function(){
            const checkedBoxes = document.querySelectorAll('input[name="post_cats[]"]:checked');
            selectedCats = Array.from(checkedBoxes).map(cb => cb.value);
            offset = 0;
            convertedTotal = 0;
            this.disabled = true;
            updateStatus('开始转换中...');
            convertBatch();
        });
    })();
    </script>
    <?php
}

// 显示分类多选框(带层级)
function render_category_checkboxes($categories, $parent = 0, $level = 0) {
    $html = '';
    foreach ($categories as $cat) {
        if ($cat->parent == $parent) {
            $indent = str_repeat('&nbsp;&nbsp;&nbsp;', $level);
            $html .= '<label style="display:block; margin-left:' . ($level * 20) . 'px;">';
            $html .= '<input type="checkbox" name="post_cats[]" value="' . esc_attr($cat->term_id) . '"> ';
            $html .= $indent . esc_html($cat->name);
            $html .= '</label>';
            $html .= render_category_checkboxes($categories, $cat->term_id, $level + 1);
        }
    }
    return $html;
}

// AJAX: 同步分类
add_action('wp_ajax_sync_post_categories_to_product_cat', function() {
    $post_categories = get_categories(['hide_empty' => false, 'orderby' => 'term_id']);
    $synced = 0;
    $cat_map = [];

    usort($post_categories, fn($a, $b) => $a->parent - $b->parent);

    foreach ($post_categories as $cat) {
        if (!$cat || is_wp_error($cat)) continue;

        $parent_product_cat_id = 0;
        if ($cat->parent && isset($cat_map[$cat->parent])) {
            $parent_product_cat_id = $cat_map[$cat->parent];
        }

        $term = get_term_by('slug', $cat->slug, 'product_cat');
        if (!$term) {
            $term = wp_insert_term($cat->name, 'product_cat', [
                'slug'   => $cat->slug,
                'parent' => $parent_product_cat_id,
            ]);
            if (is_wp_error($term)) continue;
            $term_id = $term['term_id'];
        } else {
            $term_id = $term->term_id;
            if ($term->parent != $parent_product_cat_id) {
                wp_update_term($term_id, 'product_cat', ['parent' => $parent_product_cat_id]);
            }
        }

        $cat_map[$cat->term_id] = $term_id;
        $synced++;
    }

    wp_send_json_success(['count' => $synced]);
});

// AJAX: 文章转商品
add_action('wp_ajax_ajax_batch_convert_posts_to_products', function() {
    $cats = isset($_POST['cats']) ? array_map('intval', $_POST['cats']) : [];
    $offset = isset($_POST['offset']) ? intval($_POST['offset']) : 0;
    $limit = 10;

    if (empty($cats)) {
        wp_send_json_error(['message' => '未选择分类']);
    }

    $posts = get_posts([
        'post_type'      => 'post',
        'posts_per_page' => $limit,
        'offset'         => $offset,
        'post_status'    => 'publish',
        'category__in'   => $cats,
        'orderby'        => 'ID',
        'order'          => 'ASC',
    ]);

    $converted = 0;

    foreach ($posts as $post) {
        $existing = get_posts([
            'post_type'  => 'product',
            'meta_key'   => '_converted_from_post',
            'meta_value' => $post->ID,
            'fields'     => 'ids',
            'posts_per_page' => 1,
        ]);
        if (!empty($existing)) continue;

        $product_id = wp_insert_post([
            'post_title'   => $post->post_title,
            'post_content' => $post->post_content,
            'post_excerpt' => $post->post_excerpt,
            'post_status'  => 'publish',
            'post_type'    => 'product',
        ]);
        if (is_wp_error($product_id)) continue;

        update_post_meta($product_id, '_converted_from_post', $post->ID);
        wp_set_object_terms($product_id, 'simple', 'product_type');

        $category_ids = wp_get_post_categories($post->ID);
        $product_cats = [];
        foreach ($category_ids as $catid) {
            $cat = get_category($catid);
            if ($cat && !is_wp_error($cat)) {
                $term = get_term_by('slug', $cat->slug, 'product_cat');
                if ($term) {
                    $product_cats[] = $term->term_id;
                }
            }
        }
        if (!empty($product_cats)) {
            wp_set_object_terms($product_id, $product_cats, 'product_cat');
        }

        $thumb_id = get_post_thumbnail_id($post->ID);
        if ($thumb_id) {
            set_post_thumbnail($product_id, $thumb_id);
        }

        $converted++;
    }

    $has_more = count($posts) === $limit;
    wp_send_json_success(['converted' => $converted, 'has_more' => $has_more]);
});

 

附加:一键删除指定文章分类下所有文章的完整 PHP 代码,可以放到主题的 functions.php 或自定义插件里,后台会添加一个菜单页面,输入文章分类 slug 或 ID,点击按钮即可删除该分类下所有文章。

// 删除指定文章分类下所有文章的函数
function delete_all_posts_in_category($category_slug_or_id) {
    $args = [
        'post_type'      => 'post',
        'posts_per_page' => -1,
        'post_status'    => 'any',
        'category__in'   => is_numeric($category_slug_or_id) ? [$category_slug_or_id] : [],
    ];

    // 如果传入的是 slug,则先查出对应分类 ID
    if (!is_numeric($category_slug_or_id)) {
        $cat = get_category_by_slug($category_slug_or_id);
        if ($cat && !is_wp_error($cat)) {
            $args['category__in'] = [$cat->term_id];
        } else {
            return new WP_Error('invalid_category', '分类不存在');
        }
    }

    $posts = get_posts($args);
    $deleted = 0;

    foreach ($posts as $post) {
        wp_delete_post($post->ID, true); // 强制永久删除
        $deleted++;
    }

    return $deleted;
}

// 后台菜单
add_action('admin_menu', function() {
    add_submenu_page(
        'edit.php',
        '清空文章分类',
        '清空文章分类',
        'manage_options',
        'delete-posts-by-category',
        'render_delete_posts_page'
    );
});

// 后台页面内容
function render_delete_posts_page() {
    $deleted_count = null;
    $error_message = '';

    if (isset($_POST['post_cat_slug'])) {
        $cat_slug_or_id = sanitize_text_field($_POST['post_cat_slug']);
        $result = delete_all_posts_in_category($cat_slug_or_id);
        if (is_wp_error($result)) {
            $error_message = $result->get_error_message();
        } else {
            $deleted_count = $result;
        }
    }
    ?>
    <div class="wrap">
        <h1>清空文章分类下所有文章</h1>
        <form method="post">
            <p>
                <label for="post_cat_slug">输入文章分类 Slug 或 ID:</label><br>
                <input type="text" name="post_cat_slug" id="post_cat_slug" style="width:300px;" required>
            </p>
            <p>
                <button class="button button-primary" type="submit">立即删除该分类下所有文章</button>
            </p>
        </form>
        <?php if ($deleted_count !== null): ?>
            <div style="margin-top:20px;">
                ✅ 共删除了 <strong><?php echo intval($deleted_count); ?></strong> 篇文章。
            </div>
        <?php elseif ($error_message): ?>
            <div style="margin-top:20px; color:red;">
                ❌ 错误:<?php echo esc_html($error_message); ?>
            </div>
        <?php endif; ?>
    </div>
    <?php
}

 

WordPress 技术支持团队
WordPress 技术支持团队

💻 一位真诚且细致入微的年轻开发者🎓,专注于外贸网站定制开发领域。
🌟 专业承接 WordPress 建站设计定制与全方位开发服务。我们的独特优势在于,不仅精通网站开发技术,更将国际化主流美术设计元素🎨巧妙融合,同时制定精准有效的品牌营销策略📈。
💡 服务涵盖:
🔍WordPress 主题开发,打造独一无二的网站视觉风格与用户体验。
💻WordPress 网站定制,根据您的外贸业务需求,量身定制专属网站。
无论是网站架构搭建,还是界面美学设计,亦或是品牌推广策略,我们都能为您提供一站式的优质解决方案,助力您的外贸事业在互联网上脱颖而出,迈向全球市场🚀。

文章: 45

發表回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

提交您的请求

报价收集表

💥网站建设 | 实力说话,不搞虚的!

宝子们,咱就说,好多甲方都不乐意自己的网站被同行抄作业,这就跟你开个店,肯定不想让别人知道你的进货渠道是一个道理,对不?所以呢,为了给客户满满的安全感,咱网站上就没放任何客户案例作品的链接哈,这可是咱对客户隐私的保护。

📌但要是有真心想做网站的老板,或者宝子你只是想看看我们的案例,那就赶紧加我们网站的联系方式,咱麻溜地给你发几个瞅瞅,主打一个真诚!

要是你还没拿定主意要做啥风格的网站,也简单,你就找几个同行的网站发给我们,照着做就完事儿。咱选仿站可不代表没本事哈,只是咱实在受不了那种瞎扯犊子的无效沟通和繁琐到让人抓狂的流程。有些甲方做个企业展示型网站,非得找几十家供应商来卷,说实话,没真技术的公司才会在那跪舔甲方。咱不一样,咱就想踏踏实实地给客户做出性价比超高、让客户满意得直拍大腿的网站。那些跪舔的活儿,就让那些只会耍嘴皮子、没啥技术的公司去干吧,咱不伺候! #网站建设

#甲方乙方 #拒绝内卷

联系WordPress技术团队

我们期待您的来信。

提交您的请求

报价收集表