田無rb#10 ~Nuxt.js firebase連携⑥~

ログイン時のみDBの参照、書き込みができるアプリの作成をやっていきます

firebaseの設定

firebaseのコンソールにアクセス => Databaseをクリック => ルールをクリック

DBのルール設定が表示されるので、以下のように修正する(.readと.writeの行)

これでログインしている場合のみ、readとwriteが使えるようになる

{
  "rules": {
    ...,
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

コード修正

ログイン、ログアウト処理

ログインは前回と同様、providerを作成してsignInWithPopupを実行する

ログアウトはsignOutで行う

// ログイン
let provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result) {
  ...
})

// ログアウト
firebase.auth().signOut()

ログインしている時、currentUserにユーザ情報のオブジェクトが保持される

これはsignInWithPopupで返されるオブジェクトと同じなので、displayNameなどの値を取り出せる

ログアウト時はnullとなるので、ログインしているかどうかの判定にも使える

firebase.auth().currentUser

DB連携

firebase.database()でDBオブジェクトを取得する。refメソッドで参照先を指定する

let db = firebase.database()
let ref = db.ref("board")

並び替え、絞り込み

orderByKey()はキーの昇順でのソート。limitToLast()は最後のデータから引数(数値)分のデータに絞り込んで取得する

ref.orderByKey().limitToLast(10)

他にも以下のようなソート、絞り込み方法が存在する

ソート

  • orderByValue ... 値による並び替え
  • orderByChild ... 引数に指定した子ノードの値によって並び替え

絞り込み

  • equalTo ... 引数の値と等しいもの
  • limitToFirst ... 先頭のデータから引数で指定した件数分
  • startAt ... 先頭の値を引数で指定した値とする
  • endAt ... 最後の値を引数で指定した値とする

イベント監視

on()メソッドでvalueイベントを監視する

value イベントを使用して、データの追加などが行われる度に、その時点での参照先のデータを読み取ることができる

以下の例だとsnapshot.val()で参照先の値を取り出せる

ref.orderByKey().limitToLast(10).on("value", function(snapshot) {
  snapshot.val() // 参照先の値
})

firebase.google.com

データ追加

dataに保存するデータをオブジェクトで用意しておき、参照先(ref(`board/${id}`))に対してsetメソッドで保存できる

(ここでは現在時刻をミリ秒に変換したものをidとしている。今回は勉強目的なので問題無さそうだが、完全に重複しないとは言い切れないので実際のシステム開発時は別の方法を検討するのが良いかも)

let data = {
  foo: this.foo,
  bar: this.bar,
  baz: this.baz,
}
let id = (new Date).getTime()
firebase.database().ref(`board/${id}`).set(data)

これにて、「Vue.js & Nuxt.js超入門」の写経はひとまず終了

次は、付録が残っているのでそれをやるか、また別のことをやるかどうしようか、、といったところです

田無rb#9 ~Nuxt.js firebase連携⑤~

firebaseによるgoogle認証の続きから

firebaseによるgoogle認証の解説

前回は実装中にエラーが起こったところでタイムアップでしたが、修正して動くようになったので(前回記事にて追記コメントしています)解説から

firebaseで発行されたapiKeyなどを渡して、firebaseの初期化を行います

firebase上に利用例が載っていたんですが、初期化の部分にはfirebase.initializeApp(config)のみ書いてあり、実行するとエラーになったのでhttps://github.com/zeit/next.js/issues/1999#issuecomment-326805233を参考に修正しています

// 設定用意
var config = {
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "..."
};

// firebase初期化
!firebase.apps.length ? firebase.initializeApp(config) : firebase.app();

続いて、認証を行う機能を提供するGoogleAuthProviderオブジェクトを作成します

signInWithPopupメソッドで作成したオブジェクトを利用してポップアップでgoogle認証を実施します

ログインに成功した場合、以下のようにresult.userでログインユーザ情報を取得できます

var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider)
  .then(function(result) {
    console.log(result.user.providerID)  // OAuthProviderのID
    console.log(result.user.uid)         // ユーザに割り当てられたID
    console.log(result.user.displayName) // 表示名
    console.log(result.user.email)       // メールアドレス
    console.log(result.user.phoneNumber) // 電話番号
    ...
  }).catch(function(error) {
    ...
  });

次回はログイン時のみ参照、投稿が可能な伝言板アプリの作成を行う

田無rb#8 ~Nuxt.js firebase連携④~

今回も「Vue.js&Nuxt.js超入門」Chapter6の続きをやっていきます

Firebaseへのデータの追加

https://[プロジェクトID].firebaseio.com/person/[キー].json というURLに対して axios の put メソッドを使ってアクセスを行う

axios.put([url], [object]);

これで指定のキーに対して object が値として保存される

※キーが存在する場合上書きされるので注意とのこと

Firebaseのデータ削除

追加で使っていた put メソッドを delete に変更すれば良いだけ

axios.put([url]);

まとめ

Firebaseを使う際は、どのURLにどのメソッドを使ってアクセスするかが重要

personの中でキーが 1 の値を取得する場合は以下のURL
https://[プロジェクトID].firebaseio.com/person/1.json

その中でnameを取得したい場合は以下のURL
https://[プロジェクトID].firebaseio.com/person/1/name.json

全ての person のデータを取得したい場合のURL
https://[プロジェクトID].firebaseio.com/person.json

また行う操作に対して以下のメソッドを使い分ける

- データの取得 ... get
- データの保存 ... put
- データの削除 ... delete

Firebaseのソーシャルログイン機能の利用

FirebaseはDBだけでなくソーシャルログイン機能も提供されているのでそれを使ってみる

Firebase側の設定

Firebaseのコンソールにアクセスしてサイドバーの [ Authentication ] をクリック => [ ログイン方法 ] リンクをクリック

ログイン方法がリスト化されている。今回は google ログインを使うので、有効にしてサポートメールアドレスを追加しておく

そしてアプリで利用する firebase の設定情報を取得しておく

歯車クリック => [ プロジェクトの設定 ] クリック => [ マイアプリ ] で設定を行うと以下のように apiKey などが発行されるのでそれらを使う

<script>
  // Your web app's Firebase configuration
  var firebaseConfig = {
    apiKey: "...",
    authDomain: "...",
    databaseURL: "...",
    projectId: "...",
    storageBucket: "...",
    messagingSenderId: "...",
    appId: "..."
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
</script>

アプリ側の設定

続いて、nuxt.js アプリからログインするために firebase パッケージをインストールする

$ npm install firebase --save

(余談:saveオプション必要だっけと思って調べてみたところ、npm5.0.0以降はデフォルトでsaveしてくれるので不要らしい)

実装したところ以下のエラーが発生

Error: This operation is not supported in the environment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled.

いろいろ調べたりしましたが今日は解決法が分からなかったのでまた次回〜

(2019/07/07追記)

エラーが発生してサーバが止まる状態になっていたため、以下のように例外補足を行うようにしたところ、処理は続くようになった(例外補足の処理が実行されるので根本解決にはなっていませんが...)

// before
firebase.auth().signInWithPopup(provider)
  .then(function(result) {
    ...
  });

// after
firebase.auth().signInWithPopup(provider)
  .then(function(result) {
    ...
  }).catch(function(error) {
    ...
  });

それとは別件で Firebase App named '[DEFAULT]' already exists (app/duplicate-app) という例外も発生したので、以下のコメントを参考に修正しました

github.com

(2019/07/13追記)

then 側の処理で typo をしていたため修正したら直りました

ただ、例外処理を実行していたのは typo のせいでは無さそうなので、その他にも色々いじっている間にどこか変わってしまったのかも

田無rb#7 ~Nuxt.js firebase連携③~

今回も「Vue.js&Nuxt.js超入門」Chapter6の続きをやっていきます

前回は全てのJSONデータを表示できるようになったので、今回は特定の値を取り出してみる

https://[プロジェクトID].firebaseio.com/person/[キー].json というURLにアクセスすれば該当キーのデータを取得できる


キー指定での検索はできるようになったが、それだけでは不便なので Firebase 側にインデックスを設定して様々な検索を行えるようにする

firebase.google.com

上記リンクに記載されている .indexOn の設定を行う。この設定を行うことで、値の並び替えと検索ができるようになるらしい

設定を行い、ソースコードJSONデータを取得する部分のURLを以下のように修正する

https://[プロジェクトID].firebaseio.com/person.json?orderBy="$key"&equalTo="検索テキスト"

各クエリについて

  • orderBy="$key" ... どの項目でデータを並び替えるかを指定する。検索を行う際に必ず指定しなければならず、指定した値が検索項目となる(ここではキーを検索項目とする。キーは$をつけて $key と表す)
  • equalTo="検索テキスト" ... orderByで指定した項目の値(ここではキー)と検索テキストが一致したものを取り出す

ここではキーを指定しているので、記事冒頭の検索と違いがないように見えるが、得られるデータに差異がある

{ "s.takahashi@example.com": {"age": 25, "name": "高橋周平"}} というデータを持っているとき、

  • .../person/[キー].json で検索した場合、値の部分({"age": 25, "name": "高橋周平"})のみ取得する
  • .../person.json?orderBy="$key"&equalTo="検索テキスト" で検索した場合、キーを含めたものを取得する

equalTo以外での検索の例として、年齢で範囲指定したい場合、 .../person.json?orderBy="age"&startAt=開始数&endAt=終了数 といったようなクエリで検索できる

田無rb#6 ~Nuxt.js firebase連携②~

「Vue.js&Nuxt.js超入門」Chapter6の続きをやっていきます

FirebaseでJSONデータを作成して、そこにブラウザからアクセスできることまでを前回やったので、続いてはNuxt.jsアプリからのアクセスを試してみる

変数urlに作成したJSONデータを渡すようにして、asyncDataを使ってコンポーネント生成時に呼び出すようにしている

<script>
const axios = require('axios')

let url = "https://[プロジェクトID].firebaseio.com/person.json"

export default {
  ...
  asyncData: async function() {
    let result = await axios.get(url);
    return { json_data: result.data };
  }
}
</script>

テンプレートから、json_dataの値をリスト形式で表示する

🤔json_dataはオブジェクトだからキーと値があるけど、v-forで回すときは(data, key)のようにkeyが後ろに来るらしい

<template>
  ...
  <ul v-for="(data, key) in json_data">
    <li>{{data.name}} [{{key}}]</li>
  </ul>
  ...
</template>

田無rb#5 ~Nuxt.js firebase連携①~

「Vue.js&Nuxt.js超入門」Chapter6の続き

前回axiosを使っての外部データとの連携を行った 続いてはDB連携

Google が提供するクラウドのデータベースサービス、Firebaseを利用する

  • Firebaseのプロジェクトを作成する
    • 書籍にはプロジェクト名の重複不可と有るが、ランダムのsuffix付きIDが振られるようになったので、アプリ名の重複は大丈夫そう
  • Realtime Databaseを作成(画面上部の Cloud Firestore のデータベースの作成ではないので注意)
    • セキュリティルールはテストモードとする
    • サンプルデータを作成して、 https://プロジェクトID.firebaseio.com/person.json でサンプルデータがJSON形式で表示されていることを確認

田無rb#4

「Vue.js&Nuxt.js超入門」写経続き

Chapter6外部サービスを利用しようの続きから 前回は axios を使って自前で用意しているデータを読み込んだので外部データの読み込みを行う JSONのダミーデータを公開しているJSONPlaceholderと言うサービスを使う

  • axiosではgetで受け取ったデータがJSON形式だった場合、自動的にオブジェクトに変換してくれる
  • asyncDataはコンポーネント生成時、自動的に実行される
    • 自動的ではなく、自分で非同期通信をしたいときは自前実装の必要あり(以下のような形で書く)
      • ボタンクリックで実行など。非同期処理なので、値を使ってなにか行いたいときは注意
axios.get(アドレス).then((res) => { ...アクセス後の処理... })
  • エラー対策
    • アドレスが間違えていたり、サーバが停止したりなど様々な原因
    • thenの後にメソッドチェーンを使ってcatchを記述(引数は関数となる。その関数の引数にエラー情報をまとめたオブジェクトが渡される)
axios.get(アドレス).then(...).catch((error) => { ...エラー処理... });