FileMakerとFirebase

#FileMakerでFirebase RealtimeDatabaseを操作する。

FileMakerから[Firebase](https://console.firebase.google.com/)のRealtimeDatabaseとのやり取りって意外と情報がないです。情報に疎い自分でも何度も耳にするGoogle様謹製NoSQLサービスだというのに。
日本語で出てくるのはFM関連の翻訳情報でお世話になる[こちらのサイト](https://notonlyfilemaker.com/2018/10/filemaker-and-firebase-integration/)くらい。しかもそのリンク先のファイルはもうないし。
そのFirebase眺めていたら、とてもシンプルでFMでちょっとAPI操作の練習したい人には最適だなと思ったので、これからFileMakerでAPIって人向けに作文しました。本当はそこからWEBアプリまでサクッと作って「ほらでけた！」みたいにやるつもりだったのですが、JavaScriptはアレなんで・・・。まあサンプルも多いのでコピペでもそこそこいけそうです。

FileMakerカンファレンス2018でもAPIでのやり取りがどのセミナーにも絡んできていて、なにがなんでもFileMakerでやってやる！って世界から、API使って水平展開!って方向にすっかり変わった感じがしました。

それなのにFileMkerからのAPI操作って使い勝手洗練されていないし、他のシステムに比べるとわかりづらい。
ここでは基本的な操作の解説になっていますが、Firebaseに関しては他に事例が少なかったので取り上げてみました。

##一応、、、Firebaseとは
言うまでもないでしょうがGoogleが提供するサービス。mBaaS（モバイルバックエンドサービス)。モバイルアプリのバックエンドをサポートするサービスが主眼ですが、あまりにも簡単にデータベースをWEB上に公開できるのですね。
詳細は[ドットインストール](https://dotinstall.com/lessons/hosting_firebase)を見ればよくわかります。

注意)Googleは今はFirebaseのデータベースサービスはここで書いているRealtimeDatabaseではなく、Beta提供のFirestoreを推している。

##FileMakerをFirebaseでどんな用途に？##
Firebaseでは、RealtimeDatabaseへ追加されたデータを即ホスティングできます。このスピードが半端ない。Railsで3日でサイト作成！爆速！とかの自慢勢の更に上をいっています。（速く作成できるからいいとは全然思いませんよ。）

例えばFileMakerで得意先リストとか商品リストとかを管理していて、その中にはパブリックにしたくない情報・機密情報とかも一緒のテーブルに入っていると思います。
その中から、必要なレコード・フィールドのみをFirebaseへアップすれば簡単にWEB公開できます。まるでFileMakerから直接WEBをコントロールしている感じです。
商品管理や集計は使いやすいFileMakerで行って、公開情報だけFirebaseのRealtimeDatabaseにUPすればいいのです。
そんなの他のシステムでもやれます。確かに。ただ、Firebase RealtimeDatabaseはJSON形式そのままでデータを持っているのでFileMakerからのデータコントロールが直感的で非常に簡単です。ここが一番の利点。

###ここで具体的にやることを動画で###

[Youtubeリンク](https://youtu.be/5t725LYF29A)

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/5t725LYF29A/0.jpg)](http://www.youtube.com/watch?v=5t725LYF29A)

画面左側がwebブラウザ上のRealtimeDatabaseの画面
画面右側がFileMakerです。

今回はこんな感じのを作ります。

#スクリプトステップ"urlから挿入"の意味わかりますか？#
**FileMakerからのAPI連携に馴染みのない方向けに最初から解説。API利用による他システムからのデータ取得方法**

FileMakerからAPIを利用してRESTで他所からデータ引っ張ってくるのって
スクリプト[urlから挿入]だけで簡単です。とよく言われます。しかしこれとてもわかりづらい。その[urlから挿入]という言葉からは他所からデータを取ってくるのが連想できない。まんま直訳ですね。[計算式繰返し位置番号]の次くらいにヘンテコだと思います。もはや日本語ではない。命名ってプログラムにとって非常に大切な要素だと思うのですが、その意識が全く感じられない。よくこんなローカライズでGoサインが出るな〜と不思議に思うのは私だけではないはず。どの本にも命名の重要性がとくとくと語られていますよね。
**昔の洋楽の邦題センスを見習って欲しい。あれくらい頭ひねって欲しい。**

スクリプトステップの名前くらいぱっと見で意図することがわかる内容にして欲しいのです。大切な部分なので頭をひねって欲しいところ。ユーザーには変更できないので。
ここは「urlを指定して得た値を挿入」くらい意味のわかる日本語にして下さいと切に願います。

urlから挿入ステップの更にその中にオプションとか指定する箇所が５つもあるから余計に混乱します。結局たくさんのコメントを併記しないといけない。

<img width="291" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/05b292bf-128d-ad9f-986f-01bbf2a26e31.png">

まあ[ヘルプ](https://fmhelp.filemaker.com/help/16/fmp/ja/index.html#page/FMP_Help/insert-from-url.html)をよく読むしかない。でもほとんどの人は以下のようにやってると思います（王道パターン）。

- ターゲットの指定はとりあえず変数（例えば$json)を指定しておく（フィールド直指定はしない）。
- URLを指定は予め別のスクリプトで組み立てて変数（例えば$url）に入れておく。
- cURLオプションも同じく変数（例えば$option）に入れておく。

なのでここのURLを指定の中は\$url、cURLオプションの指定の中は\$optionという変数名だけ書いておくというのが定石です。そうしないと中身を確認するのに数クリックを要して手間がかかります。変数で別指定にしておけば見通しも良く、アクセスも最短というわけです。

#Firebase RealtimeDatabase APIの良さ#

APIでのデータ連携ってそのサービスやシステムによって作法が微妙に違っていたり、マニュアルが分かりづらかったりと、ベテランの人でも毎回試行錯誤すると思います。ましてや慣れない人にとってはアクセスTOKEN??、秘密鍵??、リダイレクトurl??の段階で面倒になって辞めてしまうと思うのです。
で、実はこのFirebase RealtimeDatabaseはここの部分がとてもわかりやすいのです。というか設定しなくていい（もちろん本番では設定しますよ）。
テストモードで動かす限りはTOKENやら何もないですからcURLオプションを組み立てるだけ。
どうやったらどういうデータを得られるか、送信できるかが瞬時に視覚的にわかるのです。Firebaseのwebコンソール画面に即座にデータが反映されるので。なのでFileMakerからの初めてのAPI操作練習にはうってつけかと。

##Firebaseの動きをGETで追う。
###FileMaker側の準備###
まず最初にテストで使用するFileMakerのテーブル構造から
２つ用意します。
グローバルフィールド用テーブル
<img width="678" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/a7c216ef-ef7f-30ab-3900-97a791dbe955.png">

- urlはベースとなるurlの値 この場合は「https://\_\_APPNAME\_\_.firebaseio.com/\_\_SHOPID\_\_.json」
- app_nameはプロジェクトID このサンプルの場合は「my-firebase-48a9a」<=この値は後ほど説明します。
フィールドは２つともグローバル保存にしてください。

ここのポイントはurlフィールドの値　"\_\_APPNAME\_\_"の部分と"\_\_SHOPID\_\_"の部分で、ここを別途スクリプトで
substitute(urlフィールド;["\_\_APPNAME\_\_";app_nameフィールド];["\_\_SHOPID\_\_";shop_idフィールド])として値を置き換えてやれば汎用的に使えるようになっています。

もう一つはモデルケースとして店舗情報のテーブル
<img width="539" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/05f3db97-88f8-66dd-6977-bcdfc9c46575.png">
ここは本当は店舗マスターなので色んな情報が集積していますが、今回はその中でピックアップ対象のみフィールドを作成しています。実際にUPするフィールドは適宜選択できます。

以上がFileMaker側の構造

---
###Firebase側の準備###
まず新しく[Firebase](https://firebase.google.com/?hl=ja)からスタートガイド=>プロジェクトの追加でプロジェクトを作成します。以下のような画面になるので適当に
プロジェクト名に"My-firebase"と入れるとプロジェクトIDを勝手に振ってくれます。今回はmy-firebae-48a9aがプロジェクトIDです。
<img width="775" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/394879c2-a9b6-1f81-fc52-eda31825b0df.png">


プロジェクトができたら、

Databaseの作成ですが、DefaultではBeta版のCloudfirestoreを選択させられそうになりますが、下にスクロールして
RealtimeDatabaseを選択
<img width="1007" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/137b4bf6-8dbb-0612-a855-34659547094a.png">
データベースを作成を選ぶとロックモードかテストモードを選択の画面になりますので、ここは練習ですのでテストモードで開始を選択し、有効化します。
<img width="741" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/d12162e1-b0b0-c0c0-954c-d8c7524582c5.png">

RealtimeDatabaseの箱ができたら、まず適当にこの中にデータを手動で作成します。
my-firebase----null の横のボックスにプラスボタンありますのでそれを押すと第一階層の入力ボックスが現れます。とりあえずそこに1と入れて値は空欄に。

<img width="581" alt="スクリーンショット 2018-11-19 13.12.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/0cbbeda9-0f96-0ac2-1698-19281fa27fe0.png">

次にその空欄の右のプラスボタンを押して第２階層を作成します。
<img width="549" alt="スクリーンショット 2018-11-19 13.14.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/221428c4-2cfe-df0b-6dd3-8e19d71779ab.png">
名前はFileMakerで作ったのと同じフィールド名にして値も入力します。
<img width="544" alt="スクリーンショット 2018-11-19 13.16.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/6a5b65e8-e901-d6a9-2f1e-f406ad80adf3.png">
また上の名前１の右横のプラスボタンを押してshop_nameと同じ階層にadd childします。
<img width="559" alt="スクリーンショット 2018-11-19 13.17.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/04419483-4bd2-0371-23ed-9e59112f01a2.png">
shop_addressとshop_phoneを作成してFileMakerのテーブルと同様にします。
<img width="579" alt="スクリーンショット 2018-11-19 13.17.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/677ee64c-6a78-8400-2de9-ea140c2918d8.png">

以上でRealtimeDatabaseにshop_id1の1レコードを作成しました。


###TerminalでcURLコマンドで取得###
[Firebase=>ドキュメント=>ガイド=>開発=>Realtime Database=>REST=>データの取得](https://firebase.google.com/docs/database/rest/retrieve-data?hl=ja)を見ていきます。
最初のサンプルで
curl 'https://docs-examples.firebaseio.com/rest/saving-data/fireblog/posts.json?print=pretty'
と書いてあります。
これはhttps://[docs-examples].firebaseio.com/の部分がルートとなる部分で不変です。
[docs-examples]の部分は先に取得した自分のプロジェクトID(myfireabase-48a9a)に置き換えます。
/rest/saving-data/fireblog/posts の部分がフォルダ階層と思って下さい。
restフォルダの中のsaving-dataフォルダの中のfireblogフォルダの中のpostsフォルダを探しに行っています。解説例なのに階層が深いですね。
それを.json形式で取得するリクエストです。
print=prettyは不要です。読みやすく整形してくれというリクエストです。
こんなに深い階層はテストでは邪魔です。そのために上で作成したサンプルデータは浅い階層にしました。ルートであるhttps://my-firebae-48a9a.firebaseio.com/の直下にいきなりshop_idのみのフォルダ構造にしています。
shop_id（1）{
 -shop_name:住友直販
 -shop_address:東京都葛飾区
 -shop_phone:333333
}
といった風にshop_idがそのままフォルダ名（第一階層）になっています。
（**実際はフォルダではありませんが、便宜上そう書きます。**）

階層構造を把握したので、FileMakerではなく、まずTerminalで確認します。
APIのテストをするのはいきなりFileMakerから使うのではなく、MacではTerminal.app（Windowsではコマンドプロンプト）を使用した方が速いです。
そこで$の後にcurl ....と続けて打っていき、戻ってくる値を確認していきます。そこで欲しい値がちゃんと出るのを確認してからFileMakerに実装するのが一番確実です。

Terminalで＄の後に

```
curl -X GET 'https://my-firebase-48a9a.firebaseio.com/.json'
```

\*my-firebase-48a9aの部分はご自身に割り当てられたIDに置き換えてください。
でリターンすると

```
[null,{"shop_address":"東京都葛飾区","shop_name":"住友直販","shop_phone":333333}
```
RealtimeDatabaseに登録されていたデータが全て出てきます。今は１件だけですのでこれだけですが。


次に

```
url -X GET 'https://my-firebase-48a9a.firebaseio.com/1.json'
```

は.jsonの前にshop_idである1を付加すると

```
{"shop_address":"東京都葛飾区","shop_name":"住友直販","shop_phone":333333}
```

先頭のnull(shopIDの値は空フィールド名とした使っているから）が除かれた第二階層のみの値が取得できています。


これでちゃんとデータを取れることが確認できました。
**ここまでアクセストークンも秘密鍵もリダイレクトURLも出てきません。いきなりAPIのテストができるのです。**
しかも階層構造も自身で浅く設定しているので長々としたURLにならず、URLを見ただけで何をやっているのか想像がつくと思います。
これ、大抵のサービスは長々としたurlを記述させられ（コピペで済みますが）、初めてだと何をやっているのか初見ではわかりづらいのです。

API練習にRealtimeDatabaseがいいところはこの辺なんです。

##FileMakerに実装していく##

Terminalで確認できたので、ここからFileMakerに同じ処理をさせる手順に入ります。

**curlのコマンドの説明**
上のコマンドで[ -X GET ]の部分が[urlから挿入]スクリプトステップのcURLオプションの指定に当たります。なので事前に
[変数を設定]スクリプトで$optionを作っておきます。
<img width="281" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/29ab5308-62a5-4e4c-a143-8ddabc5018d6.png">
値の中はこのように指定しておきます。
<img width="540" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/836d58f2-dde7-68a4-27f3-b5e50057b5c6.png">

 - -Xはリクエスト（なになにして下さい）の意味
 - GETは（リクエストの種類：なになにをくれ）の意味です。
 
ちなみにFirebaseではGETの場合はこのオプション指定はなくてもデータ取れます。

次にshop_idが5の情報を全てGETするには
curl -X GET 'https://my-firebase-48a9a.firebaseio.com/5.json'
とします。フォルダ（階層）の名前=shop_idですので単なる数字を直接指定しています。
こうやって次にshop_id5のshop_nameを知りたいときは
curl -X GET 'https://my-firebase-48a9a.firebaseio.com/5/shop_name.json'
と/で繋いで階層を辿っていきます。


##ここまでの流れをスクリプトにする

firebaseにあるデータを全部取ってくるスクリプトは

<img width="777" alt="スクリーンショット 2018-11-19 14.24.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/d2098da8-32ea-6dd3-e4e5-ecb0395b2b56.png">

上で書いた通りです。全データなのでshopidを入れる必要がないので、自分のfirebaseのurlを変数にするスクリプトの箇所は
substitute(urlフィールド;["\_\_APPNAME\_\_";app_nameフィールド];["\_\_SHOPID\_\_";""])
と最後の値指定を空欄("")にしています。これで
'https://my-firebase-48a9a.firebaseio.com/.json'
という値が変数$urlに入ります。

このスクリプトを実行すると結果がカスタムダイアログに表示されます。
<img width="328" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/2e0a4f80-8e7e-a4af-9e41-00c5f62529ee.png">
firebaseと全く同じ構造のデータが取れているのが確認できました。

##FirebaseへPOSTでデータを入れる。
次はPOSTでFileMaker上のレコードデータをFirebaseのRealtimeDatabaseに入れます。
Firebaseの[ガイドはこちら](https://firebase.google.com/docs/database/rest/save-data?authuser=0)
スクリプトの流れ
<img width="965" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/f1b3d0c1-0373-8dc9-a54a-130afc138f9e.png">
GETと違う箇所は
２番目のスクリプトでjson関数を使ってjsonデータを作成しています。
その変数$dataの計算式は
<img width="296" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/967a2e6b-19eb-6245-5df9-6383ffadb146.png">

####ここで一応JSONSetElemant関数の解説####
APIでデータをやりとりする時は基本JSON型式でのデータ受け渡しになりますので、JSON関数の理解は必須となります。
***JSONSetElement ( json ; キーまたは索引またはパス ; 値 ; タイプ )***
()の中を以下のように書いています。

```
jsonの部分は""
キーまたは索引またはパスの部分は
["フィールド名を直に書く";FileMakerのフィールドの値を指定;データ型];
["フィールド名を直に書く";FileMakerのフィールドの値を指定;データ型];
["フィールド名を直に書く";FileMakerのフィールドの値を指定;データ型]
```
という風に書きます。
1行目の""はここではあまり気にせず""という値なしということで、深く考えない。
2行目からはFirebase側にアップするフィールドのみここで指定します。[ ];で繋いでいって必要なフィールドの分ずらずらと書きます。公開したい項目をここでピックアップしているわけです。

- 左側の"フィールド名を直に書く"の部分はFirebase側のフィールド名になる部分です。""で囲ったテキスト値を直接書き込みます。好きな名前でいいのですが、ここでは分かりやすいようにFileMaker側と同じフィールド名を書いています。
- 真ん中の「FileMakerのフィールドの値を指定」の部分はスクリプトワークスペース左のフィールド値を選択して指定します。

<img width="635" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/fec02a27-5335-a673-b950-9d55efc3c709.png">

- 最後右側のデータ型は自分は簡単なので数値で指定しています。
<img width="501" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/c132774c-dccd-7ae4-2c05-e5a3240d21c7.png">

1でテキスト型、2だと数値型です。
タイプ名で書くと1（テキスト）の場合はJSONStringと記述します。





これで作成される変数$dataに入っているjsonデータは

```
{
	"shop_address" : "東京都葛飾区",
	"shop_name" : "住友商店",
	"shop_phone" : 111111111
}
```
というjsonデータです。
見ての通りFirebase RealtimeDatabase側と全く同じ構造です。視覚的にとてもわかりやすいです。

次のcurl用のオプション作成の部分はGETに少し足します。
$optionは
<img width="139" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/fcd9548b-748f-5029-ed5c-387c073946be.png">

となっています。GETの時は-X GETだけでしたが、それに-dと"の後に&で繋いで一つ前のスクリプトで作った\$dataを入れています。
-X(なになにをして下さいというリクエスト）
PUT(リクエストの種類:何かを置きます）
-d(ここにデータを用意しましたよ）
$data(データが入っています)
という意味です。

ちなみにPUTとしています。普通はPOSTと書くのですが、Googleガイドの方にPUTの方がいいと書いてあるのでPUTにしています。POSTだとRealtimeDatabase側で勝手にUUIDが発行されてしまうからです。shop_IDというのはFileMker側で管理していますので独自のUUIDは不要ですね。このようにサービスごとにAPIの作法が微妙に違うでガイドには一通り目を通さないと。

>>
Firebase データベースにいくつかのユーザーデータを保存するところから始めましょう。一意のユーザー名を使用して各ユーザーを保存します。また、ユーザーの氏名と生年月日も保存します。ユーザーごとに一意のユーザー名を持つため、ここでは POST ではなく PUT を使用するのが理に適っています。キーをすでに持ち、作成する必要がないからです。





##UPした店舗情報をGETで確認
上でUPした店舗情報がちゃんとfirebaseに入っているかFielMaker側から問い合わせしてみます。

<img width="860" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/409a06a6-e91c-70db-1551-87e2b0802de6.png">
これでカスタムダイアログで表示させてちゃんとGETできてるか確認できます。
<img width="711" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/742b8c78-583b-3814-f9d1-ee519ad802de.png">

Firebaseコンソールを確認
<img width="377" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/171037/356ace75-c78f-5235-503a-40bf3cde9e28.png">
ブラウザとFileMakerを左右に並べて相互に見比べながらやって下さい。

更新はPUTがそのまま使えますのでPOSTするスクリプトと同じ。
削除はGETスクリプトの$optionの中のGETをDELETEにするだけです。

以上ごくごく基本的な内容で目新しさはないですが、あまり事例のなかったFirebaseとの連携でした。


ここからは先はjavascriptでRealtimeDatabaseのデータを引っ張ってきてアプリに表示します。しかもその名の通りデータベースが更新されると即座にフロントにも反映。WEBアプリまで作っておきたかったのですが時間切れ。でもそこは[Google codelab](https://codelabs.developers.google.com)のサンプル見た方が参考になりますね。

[サンプルファイルはこちら](https://bitbucket.org/calafate40/firebase_fliemaker/src/master/)に置いております。

##命名についてもう一度（ポエム）##
余談ですが、個人的に最高の邦題センスは
Pink FloydのAtom Heart Mother => 邦題は「原子心母」
これ一見笑えるほどの直訳で、3つの英単語を日本語にしただけの四つの文字に見えますが、考え過ぎて一周しちゃったわけですかね。「原子・心・母」、、、。
しかし最後に日本語のエッセンスをふりかけて、単語をくっつけて四字熟語にするというスーパーセンス。この邦題だけでアルバムの持つ雰囲気を見事に表現しています（追体験組ですが）。
そういえば今映画が大ヒット中のクイーンの全盛期もこのアルバムとほぼ同時代ですね。

Atom Heart Mother https://www.amazon.co.jp/dp/B0773PTXJ6/ref=cm_sw_r_cp_tai_-eR8Bb3F0KKAF


最後に一応もう一回上と同じ動画貼っておきます。

[Youtubeリンク](https://youtu.be/5t725LYF29A)

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/5t725LYF29A/0.jpg)](http://www.youtube.com/watch?v=5t725LYF29A)