FirebaseのFunctionsで取り敢えずAPIを作ろう1


FirebaseのFunctionsでAPIを作ろう その1

GoogleのFirebaseってめちゃ便利ですよね,PHP派の私もいい加減あれこれ触ってます.
最近はNuxt使ってSSRアプリをHosting+Functionsにデプロイしたりしてますが
いい加減実用的なものを作るべき段になりました.
備忘録もかねて作業内容をつらつらします.

*今回はAPIまで行きません
*随所に偏見が入ってますが見逃してください.

~エミュレータの設定編

取り敢えずエミュレータの設定まで記事にします.
API的に動くところが一応見えます.

目的

APIの定義は非常に広いと思いますが,ここでは取り敢えずDBに接続してデータを入れたり貰ったりするサーバ側のなんかと定義します.
で,いい加減PHP以外でサーバレスで何とかしたいということで,FirebaseのFunctions使っていきます.
DBはGCPのCloud SQLのMySQL8系です.
今回はあんまり関係ないです.
そこまで進んだら続編出すなり続き書くなりします.

環境

OS:Windows10
エディタ(IDE):PHP Storm
因みにnpm派です.現代は一周回ってnpmです(偏見).yarnは捨てます.

前提

基本的に以下に沿って行きます.
https://firebase.google.com/docs/functions/get-started?hl=ja

Firebaseの設定

Firebaseのプロジェクトの作成とかです.
この辺は割愛します.
サイトからでもプロジェクトからでもいいです.
手順に沿って行くとFirestoreも使用するのでFunctionsとFirestoreも設定しておいてください.

ディレクトリ構成

取り敢えずプロジェクトのディレクトリを作ります.
できたら中に入って

npm install -g firebase-tools

特にpackage.jsonとか無いので見た目変化ないですがいいです.
で,

firebase login

この辺も経験ある人はいつも通り.
ログイン済みの人はいりません.

firebase init firestore

firebase init functions

因みに言語は「JavaScript」を選択.
申し訳ないけど「TypeScript」はめんどくさいだけです(偏見2).
複数人で開発するなら考えます.

デプロイファイル

デプロイする,つまり実際にアップロード?して使用するファイルは「functions」ディレクトリの下になります.
基本的には「functions/index.js」です.
こいつを手順に沿って書いていきます.
以下のようになります.

functions/index.js

const functions = require("firebase-functions");

// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
admin.initializeApp();

// このHTTPエンドポイントに渡されたテキストパラメーターを取得し、パス/ messages /:documentId / originalの下のCloudFirestoreに挿入します
exports.addMessage = functions.https.onRequest(async (req, res) => {
    // テキストパラメータを取得します。
    const original = req.query.text;
    // Firebase Admin SDKを使用して、新しいメッセージをCloudFirestoreにプッシュします。
    const writeResult = await admin.firestore().collection('messages').add({original: original});
    // メッセージの書き込みに成功したというメッセージを送り返します
    res.json({result: `Message with ID: ${writeResult.id} added.`});
});


// / messages /:documentId / originalに追加された新しいメッセージをリッスンし、メッセージの大文字バージョンを/ messages /:documentId / uppercaseに作成します
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
    .onCreate((snap, context) => {
        // CloudFirestoreに書き込まれた内容の現在の値を取得します。
        const original = snap.data().original;

        // `context.params`を使用してパラメータ` {documentId} `にアクセスします
        functions.logger.log('Uppercasing', context.params.documentId, original);

        const uppercase = original.toUpperCase();

        // Cloud Firestoreへの書き込みなど、関数内で非同期タスクを実行する場合は、Promiseを返す必要があります。
        // Cloud Firestoreドキュメントに「大文字」フィールドを設定すると、Promiseが返されます。
        return snap.ref.set({uppercase}, {merge: true});
    });

ざっと解説すると以下の二つの関数があります
・addMessage:多分HTTP GETして取得した値をFirestoreに突っ込みます
・makeUppercase:多分firestoreに突っ込まれた値をアッパーケースにしてFirestoreに突っ込みます

実行テストその1

さて,ローカル環境でテスト実行します.

firebase emulators:start

firebase emulators:start --only functions

いろんなサービスが入っている場合「--only functions」してあげないと他のサービスもエミュレートしようとして失敗して怒られます.

functions/に移動して

npm run serve

でもいいです.
「firebase emulators:start --only functions」が入ってます.

後,多分
http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme
こんな感じでアクセスできます.
Firebaseのコンソールで確認するとFirestoreのmessagesに”uppercaseme”が入っているのが確認できます.

めでたしめでたし,と思っていたのか?

「addMessage」関数は動いてますが「makeUppercase」は動いていません.

https://firebase.google.com/docs/rules/emulator-setup
https://firebase.google.com/docs/emulator-suite/install_and_configure?hl=ja

この辺に書いてあります.
エミュレータの設定がいります.
で,Javaです.,,,Java?Javaナンデ?
なんで今どきJavaなんですか私はJavaを許しません(偏見3).

まあ,仕方なくJavaを入れます.
因みにこの段階でデプロイしてもちゃんと動くと思います.
でもテストせずにデプロイとか現実的にはあり得ないので,ちゃんと環境作ります.
個人的には自分のPCにJavaが入ってなくてびっくりです.
もうそういう時代っすよ.

Javaのインストールわからない方は以下のページを発見いたしましたのでご参照ください.
初学者の鬼門環境変数の何とやらです
https://masalib.hatenablog.com/entry/2020/11/28/131550#java%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

エミュレータのインストール

firebase init emulators

これでインストール.
後で増やせばいいので一応FunctionsとFirestoreに絞るのが無難です.

再び以下にアクセス
http://localhost:5001/nexstimemanagementapi/us-central1/addMessage?text=uppercaseme

で,ちゃんと動いているかの確認ですが,
ちゃんとエミュレータが起動した後は本番のFirebaseには変化がありません.

http://localhost:4000
とかにローカルのエミュレータが起動しますのでそちらで確認してください.

以下のような感じ

めでたしめでたし

ちょと古いですが以下の記事なぞ参考になると思います.
https://qiita.com/HALU5071/items/e43729ac5b06b0506fbe