Flutter中如何将Firestore自动生成文档ID替换为用户手机号并实现注册时手机号查重
解决方案:Firestore文档ID替换为手机号 + 注册时重复校验
针对你提出的两个需求,我来一步步帮你修改代码:
1. 将Firestore文档ID改为用户手机号
你当前代码里用的是Firebase Auth生成的user!.uid作为文档ID,要改成用户手机号很简单,只需要把doc(user!.uid)替换为用户输入的手机号即可。不过要注意统一手机号格式(比如去掉空格、区号等),避免同一个手机号因为格式不同被存成多个文档。
修改后的postDataToFirestore函数如下:
postDataToFirestore() async { FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance; // 统一手机号格式:去掉所有空格 String processedPhone = phoneController.text.replaceAll(RegExp(r'\s+'), ''); UserModel userModel = UserModel(); // 用处理后的手机号作为uid和phone字段 userModel.uid = processedPhone; userModel.name = nameController.text; userModel.email = emailController.text; userModel.phone = processedPhone; userModel.province = dropDownValue; userModel.dateOfBirth = dateController.text; userModel.challengeHistory = []; userModel.challengeMember = []; userModel.profileImage = 'https://firebasestorage.googleapis.com/v0/b/athaddak-bf02c.appspot.com/o/default_picture%2FBlank-Avatar.png?alt=media&token=47255868-37a0-4a55-8bc4-1d1ef5599ded'; userModel.challenges = 0; userModel.winnings = 0; userModel.events = 0; userModel.points = 20; // 用处理后的手机号作为文档ID await firebaseFirestore .collection("Users") .doc(processedPhone) .set(userModel.toMap()); Fluttertoast.showToast(msg: "Account Created Successfully .. :)"); Navigator.pushAndRemoveUntil( (context), MaterialPageRoute(builder: (context) => HomeScreen()), (route) => false); }
2. 注册时检查手机号是否重复
要避免重复注册,我们需要在创建Auth用户之前先检查手机号是否已存在,同时可以配合Firestore的唯一索引防止并发场景下的重复写入。
方式一:注册前主动查询Firestore
修改你的signUp函数,先校验表单,再查询手机号是否已存在,只有不存在时才创建用户:
void signUp(String email, String password) async { if (_formKey.currentState!.validate()) { // 先统一手机号格式 String processedPhone = phoneController.text.replaceAll(RegExp(r'\s+'), ''); // 查询该手机号对应的文档是否存在 var docSnapshot = await FirebaseFirestore.instance.collection("Users").doc(processedPhone).get(); if (docSnapshot.exists) { Fluttertoast.showToast(msg: "该手机号已注册,请更换其他手机号"); return; } // 手机号不存在,继续创建Auth用户 await _auth .createUserWithEmailAndPassword(email: email, password: password) .then((value) => {postDataToFirestore()}) .catchError((e) { Fluttertoast.showToast(msg: e!.message); }); } }
方式二:添加Firestore唯一索引(可选但推荐)
如果担心并发场景(比如两个用户同时用同一个手机号点击注册),可以在Firestore控制台给Users集合的phone字段设置唯一索引:
- 打开Firebase控制台 → Firestore数据库 → 索引
- 创建复合索引,集合选
Users,字段选phone(升序),勾选"唯一"选项 - 保存索引,等待生效
这样即使并发写入,Firestore会自动拒绝重复的手机号写入,你可以在catchError里捕获这个错误并提示用户:
.catchError((e) { if (e.toString().contains("unique")) { Fluttertoast.showToast(msg: "该手机号已注册,请更换其他手机号"); } else { Fluttertoast.showToast(msg: e!.message); } });
优化手机号输入框的校验
你还可以在手机号输入框的validator里添加格式校验,提前过滤无效输入:
final phoneField = TextFormField( controller: phoneController, keyboardType: TextInputType.phone, autofocus: false, autocorrect: false, textInputAction: TextInputAction.next, validator: (value) { if (value!.isEmpty) { return "Please Enter a Phone Number"; } // 校验手机号格式(示例为中国11位手机号,可根据你的需求调整正则) String cleanedPhone = value.replaceAll(RegExp(r'\s+'), ''); if (!RegExp(r'^1[3-9]\d{9}$').hasMatch(cleanedPhone)) { return "Please Enter a Valid Phone Number"; } return null; }, onSaved: (value) { phoneController.text = value!; }, textAlign: TextAlign.center, decoration: InputDecoration( prefixIcon: Icon(Icons.phone), contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15), hintText: AppLocalizations.of(context)!.phoneNumber, border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), ), );
这样就能完美实现你的两个需求啦!
内容的提问来源于stack exchange,提问作者editix
相关产品推荐
相关产品推荐

