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

WordPress后台自定义菜单MetaBox数据无法保存求助

WordPress自定义价格列表页面数据无法保存的修复方案

核心问题分析

你当前的代码混淆了WordPress设置页面和文章元数据保存两种逻辑:

  • 自定义菜单页面不是文章编辑页,save_post钩子不会触发
  • 表单提交到options.php但又试图保存到post_meta,逻辑冲突
  • get_post_meta参数错误,直接用布尔值代替了post ID

修复后的完整代码

<?php
function register_pricepage_subpage() {
    add_menu_page( 
        '自定义价格列表', 
        '动态价格列表', 
        'manage_options', 
        'dynamic-price-list', 
        'price_page_display_callback' 
    );
    add_action( 'admin_init', 'register_pricepage_settings' );
}
add_action( 'admin_menu', 'register_pricepage_subpage' );

// 注册设置,将数据存在wp_options表
function register_pricepage_settings() {
    register_setting( 
        'pricepage-settings-group', 
        'price_page_fields',
        array(
            'sanitize_callback' => 'price_page_sanitize_fields',
            'default' => array()
        )
    );
}

// 数据清洗回调,确保输入安全
function price_page_sanitize_fields($input) {
    $cleaned = array();
    if(!empty($input['name'])) {
        $count = count($input['name']);
        for($i=0; $i<$count; $i++) {
            $name = trim($input['name'][$i]);
            if(!empty($name)) {
                $cleaned[] = array(
                    'name' => sanitize_text_field($name),
                    'price' => sanitize_text_field(trim($input['price'][$i]))
                );
            }
        }
    }
    return $cleaned;
}

// 页面渲染回调
function price_page_display_callback() {
    // 获取保存的设置数据
    $price_page_fields = get_option('price_page_fields', array());
    ?>
    <div class="wrap">
        <h1>动态价格列表</h1>
        <form method="post" action="options.php">
            <?php
                settings_fields('pricepage-settings-group');
                do_settings_sections('pricepage-settings-group');
            ?>
            <p><a id="add-row" class="button" href="#">添加行</a></p>
            <table id="price_page-fieldset-one" width="50%" style="padding: 1rem 2rem;">
                <thead>
                    <tr>
                        <th width="75%" style="border: solid 1px #000;padding: 3px 5px;">名称</th>
                        <th width="20%" style="border: solid 1px #000;padding: 3px 5px;">价格</th>
                        <th width="5%" style="border: solid 1px #000;padding: 3px 5px;">操作</th>
                    </tr>
                </thead>
                <tbody>
                    <?php if(!empty($price_page_fields)): ?>
                        <?php foreach($price_page_fields as $field): ?>
                        <tr>
                            <td><input type="text" class="widefat" name="price_page_fields[name][]" value="<?php echo esc_attr($field['name']); ?>" /></td>
                            <td><input type="text" class="widefat" name="price_page_fields[price][]" value="<?php echo esc_attr($field['price']); ?>" /></td>
                            <td><a class="button remove-row" href="#" style="padding: 0rem 1.5rem;">-</a></td>
                        </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                    <tr>
                        <td><input type="text" class="widefat" name="price_page_fields[name][]" /></td>
                        <td><input type="text" class="widefat" name="price_page_fields[price][]" /></td>
                        <td><a class="button remove-row" href="#" style="padding: 0rem 1.5rem;">-</a></td>
                    </tr>
                    <?php endif; ?>
                    <!-- 隐藏的模板行 -->
                    <tr class="empty-row screen-reader-text">
                        <td><input type="text" class="widefat" name="price_page_fields[name][]" /></td>
                        <td><input type="text" class="widefat" name="price_page_fields[price][]" /></td>
                        <td><a class="button remove-row" href="#" style="padding: 0rem 1.5rem;">-</a></td>
                    </tr>
                </tbody>
            </table>
            <?php submit_button('保存设置'); ?>
        </form>
    </div>
    <script type="text/javascript">
        jQuery(document).ready(function($) {
            $('#add-row').on('click', function(e) {
                e.preventDefault();
                var row = $('.empty-row.screen-reader-text').clone(true);
                row.removeClass('empty-row screen-reader-text');
                row.insertBefore('#price_page-fieldset-one tbody>tr:last');
            });
            $('.remove-row').on('click', function(e) {
                e.preventDefault();
                $(this).parents('tr').remove();
            });
        });
    </script>
    <?php
}
?>

关键修改说明

  1. 统一数据存储逻辑:放弃post_meta,改用WordPress设置系统(存在wp_options表),符合自定义菜单页面的特性
  2. 修复表单字段命名:将分散的name[]/price[]改为结构化的price_page_fields[name][]/price_page_fields[price][],便于统一处理
  3. 添加数据清洗回调:通过sanitize_callback确保输入数据安全,避免XSS风险
  4. 修正页面渲染逻辑:用get_option代替错误的get_post_meta,正确获取设置数据
  5. 优化JavaScript事件:添加e.preventDefault()避免默认跳转行为,修复克隆行的逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:07:02