Dokan插件产品编辑器自定义字段保存异常修复需求
解决Dokan产品编辑器中CMB2组字段二次序列化问题
问题根源
Dokan在保存产品元数据时,会自动对POST传递的数组进行序列化处理;而CMB2的组字段默认也会对数组进行序列化操作,两者叠加就导致了二次序列化,最终存储的是序列化后的字符串而非预期的多维数组。
修正方案
通过调整CMB2字段的保存逻辑,禁用其自动序列化,并改用Dokan的产品保存钩子手动处理字段存储,确保数据仅被序列化一次。
步骤1:修改CMB2组字段注册代码
在functions.php中找到你注册features组字段的代码,调整如下:
add_action( 'cmb2_admin_init', 'register_product_features_metabox' ); function register_product_features_metabox() { $cmb = new_cmb2_box( array( 'id' => 'product_features_metabox', 'title' => __( 'Product Features', 'emperor' ), 'object_types' => array( 'product' ), 'context' => 'normal', 'priority' => 'high', 'save_fields' => false, // 禁用CMB2自动保存逻辑 ) ); // 注册features组字段 $group_field_id = $cmb->add_field( array( 'id' => 'product_features', 'type' => 'group', 'description' => __( 'Add product features', 'emperor' ), 'options' => array( 'group_title' => __( 'Feature {#}', 'emperor' ), 'add_button' => __( 'Add Another Feature', 'emperor' ), 'remove_button' => __( 'Remove Feature', 'emperor' ), 'sortable' => true, ), // 自定义 sanitization 回调,返回原始数组 'sanitization_cb' => 'cmb2_sanitize_features_group', ) ); // 添加组内子字段(根据你的实际字段调整) $cmb->add_group_field( $group_field_id, array( 'name' => __( 'Feature Name', 'emperor' ), 'id' => 'feature_name', 'type' => 'text', ) ); $cmb->add_group_field( $group_field_id, array( 'name' => __( 'Feature Value', 'emperor' ), 'id' => 'feature_value', 'type' => 'text', ) ); } // 自定义组字段 sanitization,直接返回原始数组 function cmb2_sanitize_features_group( $value, $field_args, $field ) { return is_array( $value ) ? $value : array(); }
步骤2:通过Dokan钩子手动保存字段
添加Dokan产品创建/更新的钩子,手动处理features字段的存储,确保数据仅被序列化一次:
// 处理Dokan产品保存时的features字段 add_action( 'dokan_new_product_added', 'dokan_save_product_features', 10, 2 ); add_action( 'dokan_product_updated', 'dokan_save_product_features', 10, 2 ); function dokan_save_product_features( $product_id, $post_data ) { // 检查是否存在features字段数据 if ( isset( $_POST['product_features'] ) && is_array( $_POST['product_features'] ) ) { $features_data = $_POST['product_features']; // 直接更新元数据,WordPress会自动对数组进行一次序列化 update_post_meta( $product_id, '_product_features', $features_data ); } else { // 清空字段(可选) delete_post_meta( $product_id, '_product_features' ); } }
步骤3:验证读取逻辑
确保你读取字段数据时,使用get_post_meta()并设置第三个参数为false(默认就是false,会自动反序列化):
$features = get_post_meta( get_the_ID(), '_product_features', false ); // 此时$features就是正确的多维数组
关键说明
- 禁用CMB2的
save_fields避免其自动序列化数组 - 自定义sanitization回调确保返回原始数组格式
- 借助Dokan的产品保存钩子完成最终存储,让WordPress默认的元数据处理逻辑负责一次序列化
内容的提问来源于stack exchange,提问作者Iman Hasani
相关产品推荐
相关产品推荐

