WordPress插件自定义设置页多选字段保存异常求助
WordPress 插件多选设置字段无法保存多个值的解决方法
开发WordPress插件自定义设置页时遇到多选字段保存异常:该字段仅能保存单个选中值,选中多个选项时无法全部保存。尝试在字段名称后添加[]但无效,推测字段已处于数组中,但问题仍未解决。
相关代码
add_action( 'admin_init', 'settings_Init' ); function settings_Init() { register_setting( 'Plugin_Settings', // 设置组名称 'Plugin_Settings_Sanitize' // 要保存的选项名称 ); add_settings_section( 'Plugin_Settings_Section', // 区块ID __( 'Settings', 'textdomain' ), // 区块标题 'Settings_Section_Callback', // 区块回调函数 'Plugin_Settings' // 设置页面slug ); add_settings_field( 'Select_Field', __( 'Directory', 'textdomain' ), 'Render_Select', 'Plugin_Settings', 'Plugin_Settings_Section' ); } function Settings_Section_Callback() { echo __( 'This below options must be configured to ensure the plugin works as expected.', 'textdomain' ); } function Render_Select() { $options = get_option( 'Plugin_Settings_Sanitize' ); $products = wc_get_products(array( 'type' => 'course', 'status' => 'published', 'limit' => -1, ));?> <select class="" name='Plugin_Settings_Sanitize[Select_Field]' multiple> <?php foreach($products as $product){?> <option value='<?php echo $product->get_id();?>' <?php selected($options['Select_Field'], $product->get_id());?>> <?php echo $product->get_title();?> </option> <?php }?> </select> <?php } function options_page() { ?> <form action='options.php' method='post'> <h2>Platform</h2> <?php var_dump($_POST);?> <?php settings_errors(); ?> <?php settings_fields( 'Plugin_Settings' ); do_settings_sections( 'Plugin_Settings' ); submit_button();?> </form> <?php }
前端渲染的HTML
<select class="" name="Plugin_Settings_Sanitize[Select_Field]" multiple=""> <option value="17">This is a course test (Copy)</option> <option value="14" selected="selected">This is a course test</option> </select>
问题原因分析
- name属性缺失
[]:即使字段嵌套在数组中,多选select的name必须加上[],否则PHP只会接收最后一个选中的值,而非数组。 - 选中状态判断逻辑错误:当保存的值是数组时,
selected()函数的第二个参数是单个ID,无法直接匹配数组;同时未处理选项未设置时$options['Select_Field']为空的情况,会触发PHP警告。 - 未配置 sanitize 回调:
register_setting()未指定 sanitize 函数,WordPress默认过滤逻辑可能会丢弃数组类型的值,导致无法保存。
解决方案
1. 修改select的name属性
将name='Plugin_Settings_Sanitize[Select_Field]'改为name='Plugin_Settings_Sanitize[Select_Field][]',让PHP识别为数组格式。
2. 修复选中状态判断逻辑
在Render_Select()函数中,先检查保存的值是否为数组,再用in_array()判断当前选项是否被选中:
$selected = isset($options['Select_Field']) && is_array($options['Select_Field']) ? in_array($product->get_id(), $options['Select_Field']) : false; selected($selected, true);
3. 添加 sanitize 回调函数
在register_setting()中添加 sanitize 回调,确保数组能被安全保存:
register_setting( 'Plugin_Settings', 'Plugin_Settings_Sanitize', array( 'sanitize_callback' => 'sanitize_plugin_settings' ) );
同时定义 sanitize 函数,过滤非法值:
function sanitize_plugin_settings($input) { $sanitized_input = array(); if (isset($input['Select_Field']) && is_array($input['Select_Field'])) { $sanitized_input['Select_Field'] = array_map('absint', $input['Select_Field']); } else { $sanitized_input['Select_Field'] = array(); } return $sanitized_input; }
修改后的完整代码
add_action( 'admin_init', 'settings_Init' ); function settings_Init() { register_setting( 'Plugin_Settings', 'Plugin_Settings_Sanitize', array( 'sanitize_callback' => 'sanitize_plugin_settings' ) ); add_settings_section( 'Plugin_Settings_Section', __( 'Settings', 'textdomain' ), 'Settings_Section_Callback', 'Plugin_Settings' ); add_settings_field( 'Select_Field', __( 'Directory', 'textdomain' ), 'Render_Select', 'Plugin_Settings', 'Plugin_Settings_Section' ); } function Settings_Section_Callback() { echo __( 'This below options must be configured to ensure the plugin works as expected.', 'textdomain' ); } function sanitize_plugin_settings($input) { $sanitized_input = array(); if (isset($input['Select_Field']) && is_array($input['Select_Field'])) { $sanitized_input['Select_Field'] = array_map('absint', $input['Select_Field']); } else { $sanitized_input['Select_Field'] = array(); } return $sanitized_input; } function Render_Select() { $options = get_option( 'Plugin_Settings_Sanitize', array() ); $products = wc_get_products(array( 'type' => 'course', 'status' => 'published', 'limit' => -1, ));?> <select class="" name='Plugin_Settings_Sanitize[Select_Field][]' multiple> <?php foreach($products as $product){ $product_id = $product->get_id(); $selected = isset($options['Select_Field']) && is_array($options['Select_Field']) ? in_array($product_id, $options['Select_Field']) : false; ?> <option value='<?php echo $product_id;?>' <?php selected($selected, true);?>> <?php echo esc_html($product->get_title());?> </option> <?php }?> </select> <?php } function options_page() { ?> <form action='options.php' method='post'> <h2>Platform</h2> <?php settings_errors(); ?> <?php settings_fields( 'Plugin_Settings' ); do_settings_sections( 'Plugin_Settings' ); submit_button();?> </form> <?php }
内容的提问来源于stack exchange,提问作者Daniel Vickers
相关产品推荐
相关产品推荐

