Firebase(WebApp)アプリ開発の連載記事第三弾。第一弾の概要編、第二弾の環境構築編に引き続き、今回は実際にアプリを作成していこうと思いましたが、長くなってしまったので、開発編も分割します。もうしばらくお付き合いください。

1.Firebaseログイン

まず、開発環境にFirebaseのアカウントを紐付けます。これで、firebaseへのリリース作業をコマンドで実行できるようになります。
Google Cloud Shellのコンソール部分に以下のコマンドを入力して、実行してください。
※ 一定時間でCloud Shellからログアウトされます。ログアウトすると、現在のディレクトリ位置が変わるので、前回同様 firebase_sample ディレクトリに移動してください。

cd ~/firebase_sample
firebase login –no-localhost

Visit this URL on any device to log in以下のURLを選択してコピーし、ブラウザのアドレスバーに貼り付けてください。

※ クリックでリンク先に遷移するような表示になりますが、うまく表示されないので、必ずURLを選択してコピー&ペーストでアドレスバーに貼り付けて表示させてください。

リンクのアドレスを表示すると、アカウント選択の画面が表示されます。アカウントを選択し次へ進みます。

ログインが完了すると、コードが表示されます。

上記コードをGoogle Cloud ShellのPaste Authroization Code部分に貼り付けます。これで、firebaseへの接続が完了します。

2.RealtimeDatabase

データベースにデータを登録する処理をプログラムしていきます。

(1) データベースの準備

まずは、データベースを作成します。画面左側の「開発 > Realtime Database」で、データベースのページを表示します。
データベース作成のボタンをクリックして、データベースを作成します。

RealtimeDatabaseでは、他人にデータベースを自由に操作できないように「ロックモード」というモードが存在します。今回は期間限定でアクセス可能な「テストモード」で開始します。

データベースの登録が完了すると、以下のような画面になります。

まだ、何もデータが登録されていないので、nullが表示されています。これからプログラムを作成してRealtimeDatabaseにデータを登録します。

(2) プログラム作成

画面からデータを入力してデータベースに保存する処理をJavascriptで書きます。前回のindex.htmlを以下のように書き換えてください。

<html>
<!– The core Firebase JS SDK is always required and must be listed first –>
<script src=”<https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js>”> </script>
<script src=”<https://www.gstatic.com/firebasejs/7.17.1/firebase-database.js>”></script>
<!– TODO: Add SDKs for Firebase products that you want to use
<https://firebase.google.com/docs/web/setup#available-libraries> –>
    <script src=”<https://www.gstatic.com/firebasejs/7.17.1/firebase-analytics.js>”></script>
    <script>

        // Your web app’s Firebase configuration
        var firebaseConfig = {
            <自分の環境情報>
        };

        // Initialize Firebase
        firebase.initializeApp(firebaseConfig);
        firebase.analytics();

        // データベースの更新イベントを受け取る
        firebase.database().ref(‘data’).on(“value”, function(data) {
            if (data) {

                // リスト型のデータを受け取る
                var values = data.val()

                // 表示先のHTMLタグをクリアする
                var posts = document.getElementById(“posts”)
                posts.innerHTML = ”;

                // 表示するHTMLを作成する
                var ul =  document.createElement(“ul”)
                for(var key in values) {
                    var li = document.createElement(“li”)
                    li.appendChild(document.createTextNode(values[key] + ” “))

                    // ボタンの作成、キー値の埋め込み
                    var button = document.createElement(“button”)
                    button.dataset.key = key
                   button.appendChild(document.createTextNode(“削除”))
                    button.addEventListener(“click”, deleteData)
                    li.appendChild(button)
                    ul.appendChild(li)
                }

                // HTMLを更新
                posts.appendChild(ul)
            }
        })

        // データ登録処理
        function writeUserData() {

            // 入力値を取得
            var element = document.getElementById(“message”)
            var value = element.value;

            // 入力値が存在している場合にデータベースに登録
            if(value){
                firebase.database().ref(‘data’).push(value);
                alert(“登録しました”);
            }

            // 表示をクリア
            element.value = “”;
        }

        // データ削除処理
        function deleteData() {
            if(this.dataset.key){
                firebase.database().ref(‘data’).child(this.dataset.key).remove()
                alert(“削除しました。”)
            }
        }

    </script>
    <h1>Hello, Firebase.</h1>
    <input id=”message” type=”text”></input>
    <button onclick=”writeUserData()”>投稿</button>
    <div id=”posts”></div>
</html>

書き換えたらプレビューで表示確認しテキストボックスに、メッセージをなにか入力して、投稿してみてください。

投稿すると、直下にリストで入力したデータが表示されます。また、コンソール側でも入力データが登録されていることを確認できます。今回はdataという階層の下に入力した文字列が格納されていくようなデータ構造になっています。

(3) プログラムの説明
● UI部分

inputタグとbuttonタグを追加してテキストボックスとボタンを追加しています。

<h1>Hello, Firebase.</h1>

<input id=”message” type=”text”></input>
<button onclick=”writeUserData()”>投稿</button>
<div id=”posts”></div>

inputタグには、javascriptで参照しやすいようにid属性に「message」を付与しました。ボタンクリック時の処理はonclickイベントにwriteUserDataの関数を指定しています。id属性「posts」のdivタグは、データベースに登録されているデータを表示させる部分になります。

処理部分

追加したのは、データベースが更新されたときに実行されるイベント処理と、データ登録処理、データの削除処理です。

        // データベースの更新イベントを受け取る
        firebase.database().ref(‘data’).on(“value”, function(data) {
            if (data) {

                // リスト型のデータを受け取る
                var values = data.val()

                // 表示先のHTMLタグをクリアする
                var posts = document.getElementById(“posts”)
                posts.innerHTML = ”;

                // 表示するHTMLを作成する
                var ul =  document.createElement(“ul”)
                for(var key in values) {
                    var li = document.createElement(“li”)
                    li.appendChild(document.createTextNode(values[key] + ” “))

                    // ボタンの作成、キー値の埋め込み
                    var button = document.createElement(“button”)
                    button.dataset.key = key
                   button.appendChild(document.createTextNode(“削除”))
                    button.addEventListener(“click”, deleteData)
                    li.appendChild(button)
                    ul.appendChild(li)
                }

                // HTMLを更新
                posts.appendChild(ul)
            }
        })

        // データ登録処理
        function writeUserData() {

            // 入力値を取得
            var element = document.getElementById(“message”)
            var value = element.value;

            // 入力値が存在している場合にデータベースに登録
            if(value){
                firebase.database().ref(‘data’).push(value);
                alert(“登録しました”);
            }

            // 表示をクリア
            element.value = “”;
        }

        // データ削除処理
        function deleteData() {
            if(this.dataset.key){
                firebase.database().ref(‘data’).child(this.dataset.key).remove()
                alert(“削除しました。”)
            }
        }

動作としては、データベース更新イベントである ‘value’ は初期表示時にも発火するので、まずはこのイベント内の処理が実行されます。
データベース更新イベント処理では、データベースからデータを取得し、Javascript上でHTMLを作成し、id属性「posts」にデータを表示させる処理を記述しています。
もちろん、更新時にも発火するのでデータを登録した時に、追加されたように表示するためposts.innerHTML = ” のコードで一旦データをクリアしています。
登録処理では、id属性「message」に入力したデータをデータベースに登録しています。未入力状態でデータを追加させないために、条件式でデータの存在をチェックしています。
削除処理では、ボタンのタグに埋め込まれたキー値を使って、特定のデータだけ削除するようにしています。キー値は、データベース更新イベント処理でHTMLを作成するときに、埋め込んでいます。

(4) Firebase部分の解説

以下にFirebaseに関連する部分を解説します。
今回使っている、RealtimeDatabaseでは以下のようなコードがよく使われます。

firebase.database().ref(‘data’)

以下の3つで構成されています。

  1. firebase
     ほかのライブラリと競合しないようにするためにfirebaseの機能であることを明示するための名前空間です。firebaseの機能を使う場合に必ず指定をします。
  2. database()
    RealtimeDatabaseの機能を使う場合に指定します。このほかにも認証であればauth()など使う機能によって指定が変わる部分です。
  3. ref(<key>)
     データベース参照オブジェクトを取得します。データベースにはテーブルの概念がなく、キーバリュー型の構造になっています。引数に指定するのはキー値で、戻り値は参照オブジェクトです。
(5) データベース参照オブジェクト

データベース参照オブジェクトについてもう少し詳しく説明します。
refメソッドでデータベース参照オブジェクトが取得できますが、この参照オブジェクトに対しての操作がそのままデータベースへの書き込みや読み込みに対応します。
今回使用したプログラムを例に説明すると、

まず、データ登録部分では以下のコードを書いています。

firebase.database().ref(‘data’).push(value);

キー値「data」の参照オブジェクトに対して「push」メソッドでデータを追加しています。このコードを書くと、データベース上では「data」の階層の下に「push」の引数に指定したデータを登録することになります。

次はデータ取得部分です。コード(イベント登録部分抜粋)は以下になります。

firebase.database().ref(‘data’).on(“value”, function(data) {

})

キー値「data」の参照オブジェクトに対して、「on」メソッドの「value」というイベントの処理を登録しています。onメソッドの第2引数は、イベント処理部分になるので、無名関数を指定しています。
このコードを書くと、データベース上の「data」階層に対して操作が行われたときをトリガーにイベントが発火し、第2引数に指定した処理を実行することになります。
以上がRealtimeDatabaseのコードサンプルになります。

次回、AuthenticationとHostingを解説します。