WooCommerce账户自定义DOB字段仅允许客户编辑一次求助
解决WooCommerce用户仅能编辑出生日期一次的问题
我帮你调整了代码,实现了前端客户只能设置一次出生日期,管理员后台可随意编辑的需求,同时修复了日期格式设置和生日折扣的逻辑漏洞(原代码不管用户是否生日都会给折扣)。
核心思路
- 前端账户详情页:检查用户是否已保存过生日日期,若已存在则将字段设为只读状态(用户能看到但无法修改);若未设置则显示可编辑字段。
- 后台管理员:保持原功能不受限制,可随时修改用户出生日期。
- 修正日期格式为
YYYY-MM-DD,并完善生日折扣判断逻辑(仅在用户生日当天发放折扣)。
完整修改后的代码
// 前端账户详情页显示出生日期字段(限制仅能编辑一次) add_action( 'woocommerce_edit_account_form', 'dob_on_myaccount_form' ); function dob_on_myaccount_form() { $user_id = get_current_user_id(); $existing_dob = get_user_meta( $user_id, 'birthday_field', true ); $field_args = array( 'type' => 'date', 'label' => __('出生日期', 'woocommerce' ), 'required' => false, 'input_attrs' => array( 'placeholder' => 'YYYY-MM-DD', 'pattern' => '\d{4}-\d{2}-\d{2}', // 强制日期格式为年-月-日 ) ); // 如果已存在生日数据,添加只读属性 if ( !empty($existing_dob) ) { $field_args['input_attrs']['readonly'] = 'readonly'; $field_args['input_attrs']['disabled'] = 'disabled'; // 增强禁用效果 } woocommerce_form_field( 'birthday_field', $field_args, $existing_dob ); } // 前端保存账户详情时的错误处理 add_action( 'woocommerce_save_account_details_errors', 'dob_on_myaccount_form_error', 10, 1 ); function dob_on_myaccount_form_error( $args ) { $user_id = get_current_user_id(); $existing_dob = get_user_meta( $user_id, 'birthday_field', true ); // 仅当用户未设置过生日时,才校验是否填写 if ( empty($existing_dob) && isset( $_POST['birthday_field'] ) && empty( $_POST['birthday_field'] ) ) { $args->add('error', __( '请填写出生日期', 'woocommerce' ) ); } } // 前端保存账户详情(仅允许首次设置) add_action( 'woocommerce_save_account_details', 'dob_on_myaccount_form_save', 10, 1 ); function dob_on_myaccount_form_save( $user_id ) { $existing_dob = get_user_meta( $user_id, 'birthday_field', true ); // 仅当用户未设置过生日时,才允许保存 if ( empty($existing_dob) && isset( $_POST['birthday_field'] ) && !empty( $_POST['birthday_field'] ) ) { update_user_meta( $user_id, 'birthday_field', sanitize_text_field( $_POST['birthday_field'] ) ); } } // 生日折扣逻辑(仅在用户生日当天发放10%折扣) add_action( 'woocommerce_cart_calculate_fees', 'give_birthday_discount', 10, 1 ); function give_birthday_discount( $cart ) { if ( is_admin() && !defined('DOING_AJAX') ) return; $user_id = get_current_user_id(); if ( !$user_id ) return; // 未登录用户不享受折扣 $user_dob = get_user_meta( $user_id, 'birthday_field', true ); if ( empty($user_dob) ) return; // 未设置生日的用户不享受 // 提取生日的月和日,与当前日期对比 $current_date = date('m-d'); $birthday_month_day = date('m-d', strtotime($user_dob)); if ( $current_date === $birthday_month_day ) { $discount_percentage = 10; $discount_amount = -( $cart->subtotal * $discount_percentage / 100 ); $cart->add_fee( __( '生日折扣', 'woocommerce' ), $discount_amount ); } } // 后台用户资料页显示出生日期字段 add_action( 'show_user_profile', 'dob_on_admin_profile', 10, 1 ); add_action( 'edit_user_profile', 'dob_on_admin_profile', 10, 1 ); function dob_on_admin_profile( $user ) { ?> <h3><?php _e('生日','woocommerce'); ?></h3> <table class="form-table"> <tr> <th><label for="birthday_field"><?php _e('出生日期', 'woocommerce'); ?></label></th> <td><input type="date" name="birthday_field" value="<?php echo esc_attr(get_the_author_meta('birthday_field', $user->ID)); ?>" class="regular-text" /></td> </tr> </table> <br /> <?php } // 后台保存用户出生日期(管理员无限制) add_action( 'personal_options_update', 'dob_on_admin_profile_save', 10, 1 ); add_action( 'edit_user_profile_update', 'dob_on_admin_profile_save', 10, 1 ); function dob_on_admin_profile_save( $user_id ) { if ( ! empty( $_POST['birthday_field'] ) ) { update_user_meta( $user_id, 'birthday_field', sanitize_text_field( $_POST['birthday_field'] ) ); } }
关键修改说明
- 前端字段限制:在
dob_on_myaccount_form中,通过检查用户是否已存在birthday_field元数据,为已设置的字段添加readonly和disabled属性,阻止用户修改。 - 保存逻辑限制:在
dob_on_myaccount_form_save中,仅当用户未设置过生日时才允许保存新的日期,彻底防止重复修改。 - 日期格式设置:通过
input_attrs添加pattern属性,强制用户输入YYYY-MM-DD格式的日期,同时设置占位符提示。 - 折扣逻辑修复:原代码会无条件给折扣,现在修改为仅当用户生日的月日与当前日期匹配时,才发放10%的折扣,并且排除了后台和未登录用户的情况。
内容的提问来源于stack exchange,提问作者user14906105
相关产品推荐
相关产品推荐

