RESTfm で Read してみよう その2

# RESTfm で Read をしてみる（続き）
「その1」からの続きです。「その1」の内容で API の概略は分かったかなと思います。今回はもう少し深い内容や「その1」で書ききれなかった内容などを書きたいと思います。

# 基礎となる URI と使用するデータベースおよびレイアウト
今後の説明を分かりやすくするために、RESTfm を以下の場所に配置したと仮定します。

**http\://hogehoge/RESTfm/**

また、今後説明に使うデータベース名は`Member`とし、同じくレイアウト名は`categories`とします。

# 取得するフォーマットは HTML
これまた分かりやすさを重視して、返ってくるフォーマットとしては HTML を選択します（拡張子を省略する）。別のフォーマットを選択したい場合は以前の記事に書いた内容を参照してください。

# データベース内のスクリプト一覧
スクリプト一覧の API にアクセスしましょう。以下の URI にどうぞ[^1]。

http\://hogehoge/RESTfm/Member/script

# スクリプトの実行
スクリプトを実行する API です。これはメソッドは GET ですが、内容はスクリプトを実行することですので、データベース内のデータに影響を及ぼす可能性があります。テスト用のスクリプトを作るなどして試してみてください。
 
実行するスクリプト名を`check_record`とした場合の URI は以下のとおりです。スクリプトが実行される場所はどこかのレイアウト上であるため、レイアウトの指定も必要になります。

http\://hogehoge/RESTfm/Member/script/check_record/categories

#### スクリプトに引数を取る場合
スクリプトに引数を取る場合は`RFMscriptParam`に引数の値を指定し、それをパラメータとして URI に持たせます。例えば`check_record`というスクリプトの引数の値に`fugafuga`という値を指定したい場合は以下のようになります。

http\://hogehoge/RESTfm/Member/script/check_record/categories?RFMscriptParam=fugafuga

フォーマットを指定している場合はそのフォーマット名（拡張子）の後ろにパラメータを指定することに注意です。例えば上記の URI を JSON で返す場合は以下の URI になります。

http\://hogehoge/RESTfm/Member/script/check_record/categories.json?RFMscriptParam=fugafuga

#### 一部のスクリプトステップは実行できない
詳しくは後日書きたいと思っていますが、API（FileMaker API for PHP、および XML）で実行できるスクリプトステップには制限があり、**一部のスクリプトステップは API 経由では実行できません**。ただこれには回避方法があったりするのですが、それも含めて後日ということにさせてください。

# レコードを検索する
この API が一番使用頻度が高いかなと思いますが、説明の都合上この位置にきてしまいました。まずはじめに、レコードを検索する方法は 2 種類あります。1 つはレイアウト内のフィールドに対して検索条件を用いて検索するという極めて一般的な方法、そしてもう 1 つが SQL を用いる方法です。

#### フィールドに対して検索条件を指定する
FileMaker を操作する上で高い頻度で行われるのがこの操作でしょう。レイアウト上で特定のフィールドに対して検索条件を当てはめてレコードを検索する、という手法です。さっそくこれを RESTfm の API で実現する方法を見てみます。[公式ドキュメント](http://restfm.com/restfm-manual/web-api-reference-documentation/uri-restfmdatabaselayoutlayout/read-get)が充実しているため、適宜参照してください。

##### RFMsF と RFMsV の 2 つのパラメータをセットで設定する
フィールドへの検索をするためには、レイアウトを示した URI に、検索の対象となるフィールドと検索条件を表したパラメータを付与する必要があります。そのパラメータというのが`RFMsF`と`RFMsV`です。これはペアで用いなければなりません。

`RFMsF`には検索対象としたいフィールド名を指定します。`RFMsV`には当該フィールド名に対する検索条件（FileMaker 準拠）を指定します。例えば、`foo`というフィールドに対して`bar`を完全一致で検索したい場合は、`RFMsF=foo&RFMsV===bar`というパラメータを付与することになります。

……んですが、ここまで書いておいてなんなのですが、`RFMsF`と`RFMsV`は複数個指定することができます（いわゆる AND 検索）。それを踏まえて、この 2 つのパラメータの正確な書式は、**`RFMsF`および`RFMsV`の後ろに半角数字の番号を付与したもの**になります。`RFMsF1`と`RFMsV1`のペアであったり、`RFMsF2`と`RFMsV2`のペアであったりですね。

検索条件のパラメータを複数連結すれば、それが AND 検索となるわけです。先ほどの例を拡張して、あるレイアウトにおいて、`foo`というフィールドが`bar`であり（完全一致）、かつ、`soft`というフィールドが`skills`である（完全一致）というレコードを検索したい場合、付与するパラメータは以下のようになります。

`RFMsF1=foo&RFMsV1===bar&RFMsF2=soft&RFMsV2===skills`

##### URI を作る
それでは実際にアクセスする URI を作りましょう。ベースとなる URI は以下のとおりです。ただし、ここでは戻すフォーマットは JSON としましょう。

http\://hogehoge/RESTfm/Member/layout/categories.json

これにパラメータを付与します。パラメータの付与方法は、第一のパラメータに対しては接頭語を`?`とし、それ以降のパラメータの連結には`&`を使うんでしたね。したがって以下のような URI が作れます。**記号類（「=」など）や日本語はエンコードする必要がありますがここでは見やすくするために省略していますので注意してください**。

http\://hogehoge/RESTfm/Member/layout/categories.json?RFMsF1=foo&RFMsV1===bar&RFMsF2=soft&RFMsV2===skills

これを叩けば希望の検索結果が JSON で返ってきます。

#### 他のパラメータ
他にもいくつかパラメータがあり、[公式ドキュメント](http://restfm.com/restfm-manual/web-api-reference-documentation/uri-restfmdatabaselayoutlayout/read-get)を見ればわかるとは思いますが、2 つだけ簡単に説明します。

- **RFMmax**
    - API を叩いた結果、戻してくるレコードの数を指定します（デフォルトは 24）
- **RFMscript**
    - 検索結果に対して実行するスクリプトを指定します
    - スクリプトにパラメータを指定する場合は`RFMscriptParam`パラメータをさらに付与します

#### SQL 文で検索する
前述したように、SQL 文を使って検索をすることも可能です。これも[公式ドキュメント](http://restfm.com/restfm-manual/web-api-reference-documentation/uri-restfmdatabaselayoutlayout/read-find-request-sql)に詳しいのでぜひご参照ください。

パラメータの指定方法は簡単です。`RFMfind`に対して SQL 文を値として与えましょう。SQL 文それ自体についてはここでは省略します。

# Bulk Operations（特殊）
Read の手法として最後に Bulk Operations について記載します。公式ドキュメントは[こちら](http://restfm.com/restfm-manual/web-api-reference-documentation/uri-restfmdatabasebulklayout-bulk-operations/read-get)です。

この Bulk Operations はその名の通り、複数の条件を投げ込んでレスポンスを得る手法です。ただし、GET メソッドの名を冠してはいますが、**実際に使うメソッドは POST メソッドです**。Read するという意味では GET なのですが、そのための方法として POST を使わざるを得ないため、このような形式になっています。

したがって Webブラウザ で URI を直接叩いても実行できません。所定の書式で message body を POST しなければなりません。

まず、叩くべく URI のパラメータとして`RFMmethod=GET`を与える必要があります。繰り返しますが、使用するメソッドは POST です。しかしながら情報を取得するに過ぎない動作のため、明示的にオーバーライドのようにこのパラメータを指定しているのです。

そして投げ込む message body ですが、例を以下に示します。

```
{
    "meta": [
        {
            "recordID": "1234567"
        },
        {
            "recordID": "9876543"
        },
        {
            "recordID": "foo===bar"
        },
        {
            "recordID": "soft===skills"
        }
    ]
}
```

`recordID`というのが決まり文句（デフォルト）です。レコードIDで検索をかける場合は値に対してレコードIDをそのまま書けばよいです。しかし、その他の任意のフィールドに対して検索を書ける場合は、上記にもあるように、フィールド名と検索条件をパラメータ的につなぎ合わせたものを値として書きます。

PHP のコードで書く場合は以下のように配列を作り、それを`json_encode`すればいいでしょう。

```php
$data = array("meta" => [
        array("recordID" => "1234567"),
        array("recordID" => "9876543"),
        array("recordID" => "foo===bar"),
        array("recordID" => "soft===skills")
        ]);
$post_data = json_encode($data);
```

注意点としては、それぞれの検索条件に対してヒットするレコードが一意に定まるようにしてください。どれか一つの条件に対してでも複数のレコードがヒットしてしまうとエラーが返ってきてしまいます。

ここまでできたならば、あとは curl で POST すれば適切な値が返ってきます。`RFMmethod=GET`のパラメータを付与して実質的に GET であるのを明示することを忘れずに。

この Bulk Operations は、「その検索をすればそれぞれ一意のレコードが返ってくることが保証されているレコード群に対して、一気に検索をかけてまとめて返り値を得る手法」というように認識しておけばいいと思います。

# 日付検索での注意点
補足として日付で検索するときの注意点を付記します。今回の記事内容だけでなく、RESTfm による検索すべてに当てはまる注意点です[^2]。

日本的な書式ですと年月日は 2016/12/24 という書式になりますが、RESTfm では 12/24/2016 という書式を用いなければなりません。年月日の区切り記号については「/」でも「-」でも構いません。ちょっとしたハマりポイントなので注意しましょう。

# その他の Read 手法
公式ドキュメントを詳しく読むとわかりますが、これまでに挙げた以外にも種々の Read 手法が存在します。これまで記した方法で基本的な API へのアクセスの仕方はわかったと思いますので、それらを応用して様々な手法を試してみてください。

[^1]: 間違いやすいのですが、`scripts`ではなく`script`です
[^2]: よくよく考えたら「検索」だけでなく、「作成」や「更新」にもあてはまります