前提
Vue.js, QuasarFrameworkなどで、Firebaseに作成しているアプリなどがある。
まだの方は、以下の記事など参照にしていただけますと幸いです。
https://qiita.com/yassyskywalker/items/d74ea3b0834145df5473
FirebaseUser新規作成時にセットされるプロパティの確認
Firebase のAuthenticationでセットするUserは、以下のプロパティを持っているようです。
更新時はこちら
Firebase Realtime DatabaseにUserのプロパティを追加する。
Firebase User オブジェクトに他のプロパティを直接追加することはできませんが、代わりに Firebase Realtime Database に追加プロパティを格納することができます。
とのことなので、サインアップのときに、一緒にRealtime Databaseに、Userテーブルを作成してみようと思います。
サインアップ時に、Realtime Database Userを作成する
参考:
https://firebase.google.com/docs/database/security/?hl=ja
目標とするデータベース構造は以下のようなものです。
{
"users": {
"<uid>(Authentication UserのID)": {
"name": "山田 太郎",
"username": "taro",
"homepage": "https://www.test",
"comment": "よろしく",
"tel": "123456",
"sex": "female",
"public": true
},
}
}
サインアップ時に、uidとusernameだけを設定した空のデータをFRDに作っておきます。
<template lang="html">
<div>
<div class="layout-padding row justify-center background-whitesmoke items-center">
<div class="col-xs-12 col-sm-7 col-lg-5">
<q-card class="q-card-background-white">
<q-card-main>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-center">
<img src="~assets/quasar-logo-full.svg" class="logo-sized">
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-left">
<h5>新規登録</h5>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-left">
<p style="font-size: 12px;">新規アカウントの登録をお願いします。</p>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input
v-model="username"
float-label="ユーザー名"
color="primary"
type="text"
pattern="^[0-9A-Za-z]+$"/>
</q-field>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input v-model="email" float-label="メールアドレス" color="primary" type="email"/>
</q-field>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input v-model="password" float-label="パスワード" color="primary" type="password"/>
</q-field>
</div>
</div>
<div class="row" style="padding-top: 20px;">
<div class="col-sm-10 offset-sm-1 text-right">
<q-btn color="primary" style="font-weight: bold;" @click="signUp">新規登録</q-btn>
</div>
</div>
<br>
<div class="row">
<p style="color:#027be3;font-size:12px;"><router-link :to="{ name: 'Login' }">すでに登録済みの方はサインインしてください</router-link></p>
</div>
</q-card-main>
</q-card>
</div>
</div>
</div>
</template>
<script>
import {
QBtn,
QCard,
QCardMain,
QField,
QInput
} from 'quasar'
import firebase from 'firebase'
export default {
name: 'signUp',
components: {
QBtn,
QCard,
QCardMain,
QField,
QInput
},
data () {
return {
username: '',
password: '',
email: '',
user_uid: '',
newUser: {
name: '',
username: '',
homepage: '',
comment: '',
tel: '',
sex: '',
public: true
}
}
},
methods: {
signUp () {
firebase.auth().createUserWithEmailAndPassword(this.email, this.password).then(
(user) => {
this.createNewUser(user)
// Emailの確認もつけておく
user.sendEmailVerification().then(
() => {
alert('アカウントの新規作成が完了しました!')
},
(err) => {
alert('EmailVerificationでerrが発生しました。', err)
}
)
this.$router.replace('/')
},
(err) => {
let errorCode = err.code
let errorMessage = err.message
alert(errorCode, errorMessage)
}
)
},
createNewUser (user) {
// UserのUIDをPKにして、users テーブルを作成する
const uid = user.uid
const username = this.username
this.newUser.username = username
firebase.database().ref('users/' + uid).set(this.newUser)
}
}
}
</script>
<style lang="stylus">
.q-card-background-white
background white
.background-whitesmoke
background whitesmoke
height 100vh
.logo-sized
width 150px
margin 20px
</style>
登録を実行して、Realtime Database にusers/ のテーブルができていれば成功です!
Realtime Database に, rulesを追加する。
ルールをカスタマイズしてセキュリティを高めます。公式サイトを参考にします。
https://firebase.google.com/docs/database/security/?hl=ja
https://firebase.google.com/docs/database/security/user-security?hl=ja
https://firebase.google.com/docs/database/web/read-and-write?authuser=1
Firebase Database ルールの構文は JavaScript ライクで、次に示す4つの種類があります。
.read ユーザーによるデータの読み取りを許可するときに記述します。
.write ユーザーによるデータの書き込みを許可するときに記述します。
.validate 値の適切なフォーマット方法、子属性を持つかどうか、およびデータ型を定義します。
.indexOn インデックスを作成する子に並べ替えとクエリをサポートするように指定します。
以下のようにコンソール画面のrulesで修正できます。
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
}
}
}
}
さらに、.validate
で、バリデーションも追加してみます。
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid",
"comment": {
".validate": "newData.isString() && newData.val().length > 0 && newData.val() < 200"
}
}
}
}
}
}
これで一旦サインアップのときに一緒にuser テーブルを作成する作業は完了です!
Realtime Databaseの、Userデータを読み取り&更新する
以下のような感じでRealtime Databasから、データの読み込みができます。
const db = firebase.database()
const dbProfileRef = db.ref('users/' + this.userUID)
dbProfileRef.on('value', snapshot => {
console.log('snapshot.val()', snapshot.val())
})
データをプロフィールフォームに読み込んでみます。ここでは、テストで、createdのタイミングで、データベースからユーザー情報を読み込んでみます。
また、update()メソッドで、ユーザ情報を更新することもできます。
<template lang="html">
<div class="row">
<div class="col-xs-12 col-sm-12">
<!-- プロフィールフォーム -->
<div class="row justify-center">
<div class="col-6">
<q-field
label="名前"
>
<q-input v-model="name" type="text"/>
</q-field>
</div>
</div>
<div class="row justify-center">
<div class="col-6">
<q-field
label="ユーザーネーム"
>
<q-input v-model="username" />
</q-field>
</div>
</div>
<div class="row justify-center">
<div class="col-6">
<q-field
label="ホームページ"
>
<q-input v-model="homepage" type="url"/>
</q-field>
</div>
</div>
<div class="row justify-center">
<div class="col-6">
<q-field
label="自己紹介"
type="textarea"
>
<q-input v-model="comment" type="textarea" :min-rows="5" />
</q-field>
</div>
</div>
<br>
<div class="row justify-center">
<div class="col-6 text-center bold-underline">
<span>非公開情報</span>
</div>
</div>
<div class="row justify-center">
<div class="col-6">
<q-field
label="電話番号"
>
<q-input v-model="tel" type="tel"/>
</q-field>
</div>
</div>
<div class="row justify-center">
<div class="col-6">
<q-field
label="性別"
>
<q-select
v-model="sex"
:options="sexOptions"
/>
</q-field>
</div>
</div>
<div class="row justify-center">
<div class="col-6">
<q-field
label="公開する"
>
<q-checkbox v-model="public" />
</q-field>
</div>
</div>
<div class="row justify-center">
<div class="col-6 text-center">
<q-btn color="primary" class="q-btn-margin" @click="updateUser">保存する</q-btn>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
QBtn,
QCheckbox,
QField,
QInput,
QSelect
} from 'quasar'
import MyPageHeader from './MyPageHeader.vue'
import firebase from 'firebase'
export default {
name: 'myPageProfile',
components: {
QBtn,
QCheckbox,
QField,
QInput,
QSelect
},
data () {
return {
url: '',
sexOptions: [
{
label: '男性',
value: 'male'
},
{
label: '女性',
value: 'female'
}
],
name: '',
username: '',
homepage: '',
comment: '',
public: false,
tel: '',
sex: ''
}
},
computed: {
userUID () {
return this.$store.getters.userUID
}
},
methods: {
updateUser () {
const userProfile = {
name: this.name,
username: this.username,
homepage: this.homepage,
comment: this.comment,
public: this.public,
tel: this.tel,
sex: this.sex
}
firebase.database().ref('users/' + this.userUID).update(userProfile)
}
},
created () {
const db = firebase.database()
const dbProfileRef = db.ref('users/' + this.userUID)
dbProfileRef.on('value', snapshot => {
snapshot.forEach((data) => {
let keyName = data.key
this.$data[keyName] = data.val()
})
})
}
}
</script>
<style lang="stylus">
.profile-img
width 100px
margin 20px
.bold-underline
font-weight bold
text-decoration underline
.tab-pane
margin 20px
.q-btn-margin
margin 20px
font-weight bold
.q-field-label-inner
color black
font-weight bold
</style>
以下の2点が実行されれば成功です!
- 読み込みのときに、データベースからデータが読み込まれる
- 更新して保存ボタンをクリックすると、データベースの値が更新される
まとめ
いままでSQLしか触ったことが無かったので、最初はかなりとまどったのですが、Firebaseのドキュメントが充実しているおかげで、スムーズにNoSQLへ移項できそうな気がします。
Firebaseの日本語ドキュメントと、動画講義の充実度合いは素晴らしいですね。
かなりファンになりました。特にSQL使ったことある人向けのRealtime Databaseの入門・解説動画はめっちゃわかりやすかったです。
https://www.youtube.com/watch?v=WacqhiI-g_o