Flutter中实现Firebase Auth注册用户UID与Cloud Firestore关联的方案
如何在Firebase Auth注册时将UID同步为Firestore文档ID
我刚好解决了和你一模一样的需求!当用户通过邮箱密码完成Firebase Auth注册后,把自动生成的UID作为Cloud Firestore中users集合的文档ID创建空文档,后续让用户在主应用内补充完善其他数据。下面是我亲测可行的实现方案:
实现步骤
1. 封装Firestore操作类
先创建一个adduser.dart文件,专门用来处理Firestore的用户数据操作。这里定义DatabaseService类,通过构造函数传入用户UID,这样就能精准定位到对应用户的文档:
import 'package:cloud_firestore/cloud_firestore.dart'; FirebaseFirestore firestore = FirebaseFirestore.instance; class DatabaseService { final String uid; DatabaseService({ required this.uid }); // 引用users集合 final CollectionReference userCollection = FirebaseFirestore.instance.collection('users'); // 初始化用户数据(传空值是为了先创建文档,后续再补充内容) Future updateUserData(String ouderName, String kindName, String school,) async { return await userCollection.doc(uid).set({ 'ouderName' : ouderName, 'kindName' : kindName, 'school' : school, }); } }
2. 在注册流程中触发文档创建
找到你的Firebase Auth注册逻辑所在的fire_auth.dart文件,在注册成功返回用户对象之前,调用上面的updateUserData方法,传入空字符串就能创建以UID为ID的文档:
// 在return user;之前添加这行代码 await DatabaseService(uid: user!.uid).updateUserData('', '', '');
完成这一步后,用户注册成功的同时,Firestore的users集合里就会生成一个以该用户UID为文档ID的空结构文档,后续用户进入主应用后,你可以通过同样的DatabaseService类来更新这个文档的内容。
附:完整的注册页面代码
这里是我使用的注册页面实现,供你参考:
import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:planplay/login/profile_page.dart'; import 'package:planplay/login/fire_auth.dart'; import 'package:planplay/login/validator.dart'; class RegisterPage extends StatefulWidget { @override _RegisterPageState createState() => _RegisterPageState(); } class _RegisterPageState extends State<RegisterPage> { final _registerFormKey = GlobalKey<FormState>(); final _nameTextController = TextEditingController(); final _emailTextController = TextEditingController(); final _passwordTextController = TextEditingController(); final _focusName = FocusNode(); final _focusEmail = FocusNode(); final _focusPassword = FocusNode(); bool _isProcessing = false; @override Widget build(BuildContext context) { return GestureDetector( onTap: () { _focusName.unfocus(); _focusEmail.unfocus(); _focusPassword.unfocus(); }, child: Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Color.fromRGBO(132, 76, 130, 1)), title: Text('Registreren', style: TextStyle(color: Color.fromRGBO(132, 76, 130, 1))), centerTitle: true, backgroundColor: Color.fromRGBO(250, 202, 48, 1), ), body: Center( child: SingleChildScrollView( reverse: true, padding: EdgeInsets.all(32), child: Padding( padding: const EdgeInsets.all(24.0), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( height: 120.0, width: 120.0, decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/images/logo.jpg'), fit: BoxFit.fill, ), ), ), SizedBox(height: 24.0), Form( key: _registerFormKey, child: Column( children: <Widget>[ TextFormField( controller: _nameTextController, focusNode: _focusName, validator: (value) => Validator.validateName( name: value, ), decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color:Color.fromRGBO(132, 76, 130, 1))), hintText: "Naam ouder", hintStyle: TextStyle(color: Color.fromRGBO(132, 76, 130, 1)), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Color.fromRGBO(250, 202, 48, 1))), errorBorder: UnderlineInputBorder( borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide( color: Colors.red, ), ), ), ), SizedBox(height: 16.0), TextFormField( controller: _emailTextController, focusNode: _focusEmail, validator: (value) => Validator.validateEmail( email: value, ), decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color:Color.fromRGBO(132, 76, 130, 1))), hintText: "Email adres", hintStyle: TextStyle(color: Color.fromRGBO(132, 76, 130, 1)), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Color.fromRGBO(250, 202, 48, 1))), errorBorder: UnderlineInputBorder( borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide( color: Colors.red, ), ), ), ), SizedBox(height: 16.0), TextFormField( controller: _passwordTextController, focusNode: _focusPassword, obscureText: true, validator: (value) => Validator.validatePassword( password: value, ), decoration: InputDecoration( enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color:Color.fromRGBO(132, 76, 130, 1))), hintText: "Wachtwoord", hintStyle: TextStyle(color: Color.fromRGBO(132, 76, 130, 1)), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Color.fromRGBO(250, 202, 48, 1))), errorBorder: UnderlineInputBorder( borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide( color: Colors.red, ), ), ), ), SizedBox(height: 32.0), _isProcessing ? CircularProgressIndicator( valueColor: AlwaysStoppedAnimation<Color>(Color.fromRGBO(250, 202, 48, 1)), ) : Row( children: [ Expanded( child: ElevatedButton( onPressed: () async { setState(() { _isProcessing = true; }); if (_registerFormKey.currentState! .validate()) { User? user = await FireAuth .registerUsingEmailPassword( name: _nameTextController.text, email: _emailTextController.text, password: _passwordTextController.text, ); setState(() { _isProcessing = false; }); if (user != null) { Navigator.of(context) .pushAndRemoveUntil( MaterialPageRoute( builder: (context) => ProfilePage(user: user), ), ModalRoute.withName('/'), ); } } else { final snackBar = SnackBar(content: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon(Icons.error_outline, size: 32, color:Color.fromRGBO(132, 76, 130, 1)), const SizedBox(width: 16), Expanded(child: Text('Gegevens onjuist, vul de juiste gegevens in', style: TextStyle(color:Color.fromRGBO(132, 76, 130, 1))), ), ], ), backgroundColor: Colors.red, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); setState(() { _isProcessing = false; }); } }, child: Text( 'Registreren', style: TextStyle(color: Color.fromRGBO(132, 76, 130, 1)), ), style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Color.fromRGBO(250, 202, 48, 1)), ), ), ), ], ) ], ), ) ], ), ), ), ), ), ), ); } }
内容的提问来源于stack exchange,提问作者Hagi Pro
相关产品推荐
相关产品推荐

