WooCommerce 注册表单中实现自定义字段的数据库级验证码校验

2次阅读

WooCommerce 注册表单中实现自定义字段的数据库级验证码校验

本文详解如何在 WooCommerce 用户注册表单中,为自定义文本字段(如邀请码/密钥)添加严格校验逻辑:仅当输入值精确匹配数据库 secret_codes 表中的某条 code 记录时才允许注册成功,否则中断提交并显示友好错误提示。

本文详解如何在 woocommerce 用户注册表单中,为自定义文本字段(如邀请码/密钥)添加严格校验逻辑:仅当输入值精确匹配数据库 `secret_codes` 表中的某条 `code` 记录时才允许注册成功,否则中断提交并显示友好错误提示。

在 WooCommerce 中扩展注册流程时,常需对用户输入的自定义字段(例如“激活码”“推荐码”或“内部密钥”)进行强一致性验证——不能仅检查非空或格式,而必须确保该值真实存在于 wordpress 数据库的指定表中(如 wp_secret_codes)。这属于典型的业务约束型校验,需在用户提交瞬间完成数据库查询与比对,并阻止非法注册。

✅ 正确实现步骤

1. 在注册表单中添加自定义字段(前端)

首先确保你的自定义字段已正确输出在注册页(通常通过 woocommerce_register_form 钩子):

// functions.php 或插件文件中 add_action('woocommerce_register_form', 'add_registration_code_field'); function add_registration_code_field() {     woocommerce_form_field('registration_code', array(         'type'          => 'text',         'required'      => true,         'label_class'   => array('woocommerce-form__label'),         'input_class'   => array('woocommerce-Input woocommerce-Input--text input-text'),         'label'         => __('邀请码(必填)', 'woocommerce'),         'placeholder'   => __('请输入有效的邀请码', 'woocommerce')     )); }

2. 执行服务端校验(关键:woocommerce_register_post)

使用 woocommerce_register_post 钩子拦截提交,在创建用户前完成数据库校验。注意:必须使用 $wpdb->get_var() 或 $wpdb->get_row() 获取实际数据,而非 $wpdb->query()(它返回影响行数,无法判断是否存在匹配记录)

add_action('woocommerce_register_post', 'validate_registration_code', 10, 3); function validate_registration_code($username, $email, $validation_errors) {     global $wpdb;      $input_code = isset($_POST['registration_code']) ? sanitize_text_field(wp_unslash($_POST['registration_code'])) : '';      if (empty($input_code)) {         $validation_errors->add('registration_code_error', __('<strong>错误</strong>:邀请码不能为空。', 'woocommerce'));         return;     }      // 假设表名为 wp_secret_codes,字段为 code(请按实际表结构调整)     $table_name = $wpdb->prefix . 'secret_codes';     $valid_code = $wpdb->get_var($wpdb->prepare(         "SELECT code FROM {$table_name} WHERE code = %s LIMIT 1",         $input_code     ));      if (!$valid_code) {         $validation_errors->add(             'registration_code_error',             __('<strong>错误</strong>:您输入的邀请码无效,请确认后重试。', 'woocommerce')         );     } }

⚠️ 重要注意事项

  • 使用 $wpdb->prepare() 防止 sql 注入,绝不可拼接用户输入到 SQL 字符串
  • sanitize_text_field() 用于清理输入,但校验逻辑必须依赖数据库查询结果;
  • LIMIT 1 提升性能,因只需判断存在性;
  • 表名建议使用 $wpdb->prefix . ‘secret_codes’ 以兼容多站点与自定义前缀。

3. (可选)注册成功后消耗/标记该码

若邀请码为一次性使用,可在用户创建后更新数据库(例如添加 used_at 时间戳或删除记录),通过 woocommerce_created_customer 钩子实现:

add_action('woocommerce_created_customer', 'mark_code_as_used'); function mark_code_as_used($customer_id) {     global $wpdb;     $input_code = isset($_POST['registration_code']) ? sanitize_text_field(wp_unslash($_POST['registration_code'])) : '';     if (empty($input_code)) return;      $table_name = $wpdb->prefix . 'secret_codes';     $wpdb->update(         $table_name,         ['used_at' => current_time('mysql')],         ['code' => $input_code],         ['%s'],         ['%s']     ); }

✅ 总结

  • 校验必须在 woocommerce_register_post 阶段完成,早于用户写入数据库;
  • 使用 $wpdb->get_var() 判断值是否存在,语义清晰且高效;
  • 前端字段名(如 ‘registration_code’)需与 $_POST 键名完全一致;
  • 始终对用户输入执行 sanitize_text_field() + $wpdb->prepare() 双重防护;
  • 错误信息应明确、友好,避免暴露数据库结构等敏感信息。

通过以上方式,你将构建出一个安全、可靠且符合业务规则的注册码校验机制,真正实现“仅白名单可注册”的管控目标。

text=ZqhQzanResources