You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress插件开发:多站点商品数据自动导入配置实现问询

Hey there! Let's break this down step by step—building repeatable field groups in a WordPress plugin settings page using classes is totally doable, and it'll keep your code clean and maintainable. Here's how I'd approach it:

1. Core Plugin Class Setup

First, create a main plugin class to encapsulate all settings logic. This will handle registering the admin menu, setting up the options page, and managing the repeatable fields.

class Product_Importer_Plugin {
    public function __construct() {
        // Hook into admin menu setup
        add_action('admin_menu', array($this, 'add_settings_page'));
        // Register settings
        add_action('admin_init', array($this, 'register_settings'));
        // Enqueue admin scripts for repeatable fields
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    }

    public function add_settings_page() {
        add_options_page(
            'Product Importer Settings',
            'Product Importer',
            'manage_options',
            'product-importer-settings',
            array($this, 'render_settings_page')
        );
    }

    public function register_settings() {
        register_setting(
            'product_importer_options_group', // Option group
            'product_importer_sites', // Option name (stores array of sites)
            array($this, 'sanitize_site_settings') // Sanitization callback
        );

        add_settings_section(
            'product_importer_main_section',
            'Site Configurations',
            array($this, 'render_section_description'),
            'product-importer-settings'
        );

        add_settings_field(
            'repeatable_sites',
            'Import Sources',
            array($this, 'render_repeatable_fields'),
            'product-importer-settings',
            'product_importer_main_section'
        );
    }

    // Sanitize the saved site data
    public function sanitize_site_settings($input) {
        $sanitized = array();
        
        if (isset($input['sites'])) {
            foreach ($input['sites'] as $site) {
                // Sanitize each field
                $sanitized_site = array(
                    'name' => sanitize_text_field($site['name']),
                    'curl_url' => esc_url_raw($site['curl_url']),
                    'product_ids' => sanitize_text_field($site['product_ids'])
                );
                
                // Only add if at least name and URL are present
                if (!empty($sanitized_site['name']) && !empty($sanitized_site['curl_url'])) {
                    $sanitized[] = $sanitized_site;
                }
            }
        }
        
        return $sanitized;
    }

    public function render_section_description() {
        echo '<p>Add and configure sites from which you want to import products.</p>';
    }

    public function render_settings_page() {
        if (!current_user_can('manage_options')) {
            wp_die(__('You do not have sufficient permissions to access this page.'));
        }
        ?>
        <div class="wrap">
            <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
            <form method="post" action="options.php">
                <?php
                settings_fields('product_importer_options_group');
                do_settings_sections('product-importer-settings');
                submit_button();
                ?>
            </form>
        </div>
        <?php
    }
}

// Initialize the plugin
new Product_Importer_Plugin();
2. Render Repeatable Field Groups

Add the method to render the repeatable fields—this will output existing saved sites and a button to add new groups.

public function render_repeatable_fields() {
    $sites = get_option('product_importer_sites', array());
    ?>
    <div id="repeatable-sites-container">
        <?php if (!empty($sites)): ?>
            <?php foreach ($sites as $index => $site): ?>
                <div class="site-field-group">
                    <h4>Site #<?php echo $index + 1; ?></h4>
                    <p>
                        <label for="site-name-<?php echo $index; ?>">Site Name:</label>
                        <input type="text" id="site-name-<?php echo $index; ?>" name="product_importer_sites[sites][<?php echo $index; ?>][name]" value="<?php echo esc_attr($site['name']); ?>" class="regular-text">
                    </p>
                    <p>
                        <label for="site-curl-url-<?php echo $index; ?>">cURL Link Format (use {product_id} as placeholder):</label>
                        <input type="text" id="site-curl-url-<?php echo $index; ?>" name="product_importer_sites[sites][<?php echo $index; ?>][curl_url]" value="<?php echo esc_attr($site['curl_url']); ?>" class="regular-text">
                        <small>Example: https://example.com/api/product/{product_id}</small>
                    </p>
                    <p>
                        <label for="site-product-ids-<?php echo $index; ?>">Product IDs (comma-separated):</label>
                        <input type="text" id="site-product-ids-<?php echo $index; ?>" name="product_importer_sites[sites][<?php echo $index; ?>][product_ids]" value="<?php echo esc_attr($site['product_ids']); ?>" class="regular-text">
                    </p>
                    <button type="button" class="remove-site-group button">Remove Site</button>
                    <hr>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </div>
    <button type="button" id="add-new-site-group" class="button button-primary">Add New Site</button>
    <?php
}
3. Add JavaScript for Dynamic Field Management

You'll need a small JS snippet to handle adding/removing field groups dynamically. First, enqueue the script in your class:

public function enqueue_admin_scripts($hook) {
    // Only load on our settings page
    if ($hook !== 'settings_page_product-importer-settings') {
        return;
    }

    wp_enqueue_script(
        'product-importer-admin-js',
        plugin_dir_url(__FILE__) . 'js/admin-scripts.js',
        array('jquery'),
        '1.0',
        true
    );
}

Then create js/admin-scripts.js with this code:

jQuery(document).ready(function($) {
    // Add new site group
    $('#add-new-site-group').on('click', function() {
        var container = $('#repeatable-sites-container');
        var index = container.children('.site-field-group').length;
        
        var newGroup = `
            <div class="site-field-group">
                <h4>Site #${index + 1}</h4>
                <p>
                    <label for="site-name-${index}">Site Name:</label>
                    <input type="text" id="site-name-${index}" name="product_importer_sites[sites][${index}][name]" class="regular-text">
                </p>
                <p>
                    <label for="site-curl-url-${index}">cURL Link Format (use {product_id} as placeholder):</label>
                    <input type="text" id="site-curl-url-${index}" name="product_importer_sites[sites][${index}][curl_url]" class="regular-text">
                    <small>Example: https://example.com/api/product/{product_id}</small>
                </p>
                <p>
                    <label for="site-product-ids-${index}">Product IDs (comma-separated):</label>
                    <input type="text" id="site-product-ids-${index}" name="product_importer_sites[sites][${index}][product_ids]" class="regular-text">
                </p>
                <button type="button" class="remove-site-group button">Remove Site</button>
                <hr>
            </div>
        `;
        
        container.append(newGroup);
    });

    // Remove site group
    $(document).on('click', '.remove-site-group', function() {
        $(this).closest('.site-field-group').remove();
        // Reindex groups after removal (optional but cleaner)
        $('.site-field-group').each(function(index) {
            $(this).find('h4').text(`Site #${index + 1}`);
            $(this).find('input').each(function() {
                var name = $(this).attr('name').replace(/\[sites\]\[\d+\]/, `[sites][${index}]`);
                var id = $(this).attr('id').replace(/-(\d+)-/, `-${index}-`);
                $(this).attr('name', name).attr('id', id);
            });
        });
    });
});
4. Next Steps for cURL/Scraping Logic

Once your settings are saved, you can extend the class to handle data fetching:

  • Add a method like fetch_product_data() that loops through the saved $sites array
  • For each site, split the comma-separated product IDs and replace {product_id} in the cURL URL with each ID
  • Use WordPress's wp_remote_get() (a safer, WP-compatible wrapper for cURL) to fetch data
  • Sanitize the response, then create/update WordPress products with wp_insert_post() (or WooCommerce functions if you're using WC)

Quick Tips:

  • Always add error handling for failed requests—check wp_remote_retrieve_response_code() to confirm a 200 OK status
  • Consider adding a cron job with wp_schedule_event() to automate imports on a schedule
  • Validate the cURL URL format to ensure the {product_id} placeholder is present before saving

内容的提问来源于stack exchange,提问作者Martijn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:40:22