FileMaker Data API を使う 2025 年版 vol.2

## 利用環境

　以下の環境を前提に説明しています。

 - Claris FileMaker Pro 21.1.1.41 macOS
 - Claris FileMaker Server 21.1.1.40 Ubuntu 22(AMD)
 - サーバ: Ubuntu 22.04.5 LTS
 - SSL 証明書
 - リクエストする側のサーバ（任意）

 　開発段階では、以下を使用した方が楽でしょう。

 - Postman Version 11.30.0

## FileMaker Data API を利用するシーン

　FileMaker Data API は様々なシーンが想定できます。ここでは、以下のような利用場面を想定しています。

 - データソースとして FileMaker Server 上の FileMaker ソリューションを利用する
 - ユーザは Web サイトで閲覧する
 - データソースの管理は FileMaker Pro/Go で行う

## FileMaker Data API のリクエストに必要な基本情報

　FileMaker Data API のリクエストに必要な基本情報は以下の通りです。
 - FileMaker Server のドメイン名（以下、**host** と言う）
 - FileMaker Data API のバージョン名(以下、**version** と言う)
 - FileMaker Server 上の FileMaker ソリューション名（以下、**database** と言う）
 - FileMaker ソリューションのアカウント名（以下、**username** と言う）
 - FileMaker ソリューションのパスワード（以下、**password** と言う）
 - FileMaker ソリューション内のレイアウト名（以下、**layout** と言う）

　前回、[FileMaker Data API を使う 2025 年版 vol.1](https://qiita.com/RemixWorksLLC/items/0e5f2741e7f50547b427) で、サンプルソリューションを作りましたので、それを使っているという想定で、進めていきます。

#### リクエスト URL の基本構造 ####

　リクエスト URL は、次のように始めます。

```
https://{{host}}/fmi/data/{{version}}/
```

{{...}} は、Postman での変数の指定方法です。
host が domain.com で、version が v2 なら、上の URL は、以下のように展開されるということです。

```
https://domain.com/fmi/data/v2/
```

 これに続けてリクエストの種類ごとに URL が続きます。

 version は、利用する FileMaker Data API のバージョン名が入ります。
  バージョン名は、
  - v1
  - v2
  - vLatest

　以上が選べますが、vLatest を指定することで、最新バージョンを選択したことになります。

 ## リクエストに使用する言語、FileMaker レイアウトの作成

 　環境が決まったので、早速、リクエストしたいのですが、リクエストに使用する言語をどうするかということです。
　R、Python、JavaScript、PHP 何でもいいのですが、とりあえず、PHP で書くことにして、適宜、他の言語も、使っていくことにします。

 　さて、FileMaker 開発をしていて、私が、一番、イライラするのは、レイアウト作成です。数枚のレイアウトで完結する小規模なものなら、FileMaker レイアウトでサクッと作るのが楽なんですが、Web アプリケーションのように、FileMaker で考えると大量のレイアウトが必要になる場合、もう、FileMaker レイアウトだと、全体に及ぶ、軽微な変更が発生してもイライラが沸点を超えてしまいます。
  そこで、利用するのが、Web ビューア。Web ビューアを一つ置いておけば、あとは、HTML、CSS、JavaScript という組み合わせで量産できます。

  これはこれでいいわけですが、この Web ビューアで見せるレイアウトの場合、不可視領域に、必要なフィールドを並べて置く必要があるということを忘れないで下さい。

　これは FileMaker Data API で、そのレイアウトを操作する場合も同じで、UI/UX が、HTML で作ってあっても、FileMaker Data API を使用する場合、レイアウトに操作するフィールドが存在していなければなりません。

 ## Product info

　まずは、FileMaker Server で、FileMaker Data API が動作し、FileMaker ソリューションが正しく設定されているか確認するために、FileMaker Data API のリクエスト「metadata - Product info」を PHP でやってみましょう

  Product info は、動作中の FileMaker Server/Cloud のホストの情報を得るもので、日付、時刻、タイムスタンプの FileMaker Data API のレスポンスのフォーマットを調べられます。

 　以下のように仮定しますので、適宜、読み替えてください。

 - host ... domain.com ... ドメイン名
 - version ... vLatest ... バージョン名

```
<?php
// metadata - Product info
$host           = 'domain.com';
$version        = 'vLatest';
$endpoint       = 'productInfo';
$request_url    = 'https://' . $host . '/fmi/data/' . $version . '/' . $endpoint;
$request_method	= 'GET';

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => $request_url,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => $request_method,

));

$response = curl_exec($curl);

curl_close($curl);

echo $response, PHP_EOL;
```

　リクエストが成功すると、以下のようなレスポンスが得られます。

```
{"response":{"productInfo":{"name":"FileMaker Data API Engine","dateFormat":"MM/dd/yyyy","timeFormat":"HH:mm:ss","timeStampFormat":"MM/dd/yyyy HH:mm:ss"}},"messages":[{"code":"0","message":"OK"}]}
```

　このように JSON が戻ってきます。ちょっと整型してみます。

```
{
    "response":
    {
        "productInfo":
        {
            "name":"FileMaker Data API Engine",
            "dateFormat":"MM/dd/yyyy",
            "timeFormat":"HH:mm:ss",
            "timeStampFormat":"MM/dd/yyyy HH:mm:ss"
        }
    },
    "messages":
    [
        {
            "code":"0",
            "message":"OK"
        }
    ]
}
```

　FileMaker Data API のレスポンスの基本構造は、このような形で、messages のブロックにエラーコードが戻ってきます。0 なら、エラーなしということです。

 　この JSON を 配列に変換した場合、コードは、['messages'][0]['code'] に入ります。ここをチェックして次の処理に移ると良いと思います。
　先ほどのコードを少し、変えて、そのような形にしてみます。

### 完成版 product_info.php
```
<?php
$host           = 'domain.com';
$version        = 'vLatest';
$endpoint       = 'productInfo';
$request_url    = 'https://' . $host . '/fmi/data/' . $version . '/' . $endpoint;
$request_method	= 'GET';

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => $request_url,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => $request_method,
));

$response = curl_exec($curl);

curl_close($curl);

$result = mb_convert_encoding($response, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
$result = json_decode($result, true);

$product_info = $result['response']['productInfo'];
$messages     = $result['messages'][0];

if ($messages['code'] === '0') {
  echo 'response.productInfo.name: ', $product_info['name'], PHP_EOL;
  echo 'response.productInfo.dateFormat: ', $product_info['dateFormat'], PHP_EOL;
  echo 'response.productInfo.timeFormat: ', $product_info['timeFormat'], PHP_EOL;
  echo 'response.productInfo.timeStampFormat: ', $product_info['timeStampFormat'], PHP_EOL;
}
```
　リクエスト後、JSON を配列に変換し、さらに、JSONのブロックごとに配列を分割してみました。変数 `$product_info` に代入する部分はリクエストの種類ごとに異なりますが、変数 `$messages` に代入した部分は、どのリクエストでも同じです。

 ## Database Names

　metadata - Database Names は、FileMaker Server/Cloud にホストされている FileMaker ソリューションのリストを得るものです。

　このリクエストも認証が必要のないものなので、先ほどのコードとリクエスト段階までは、ほとんど変わりがありません。

```
<?php
// metadata - Database Names
$host           = 'domain.com';
$version		= 'vLatest';
$endpoint		= 'databases';
$request_url	= 'https://' . $host . '/fmi/data/' . $version . '/' . $endpoint;
$request_method	= 'GET';

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => $request_url,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => $request_method,
));

$response = curl_exec($curl);

curl_close($curl);

echo $response, PHP_EOL;
```
　得られる JSON は、次のような構造になります。

```
{
  "response": {
    "databases": [
      {
        "name": "FileMaker ソリューション名"
      }
    ]
  },
  "messages": [
    {
      "code": "0",
      "message": "OK"
    }
  ]
}
```

　当然ですが、databases ブロックの中身は、ソリューションの数だけ戻ってきます。
 `curl_close($curl);` 以降の処理を Product info でやった方法を踏襲すると、次のようになるでしょうか。

### 完成版 database_names.php
```
<?php
// metadata - Database Names
$host           = 'domain.com';
$version		= 'vLatest';
$endpoint		= 'databases';
$request_url	= 'https://' . $host . '/fmi/data/' . $version . '/' . $endpoint;
$request_method	= 'GET';

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => $request_url,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => $request_method,
));

$response = curl_exec($curl);

curl_close($curl);

$result = mb_convert_encoding($response, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
$result = json_decode($result, true);

$databases  = $result['response']['databases'];
$messages   = $result['messages'][0];

if ($messages['code'] === '0') {
  foreach ($databases as $key => $item) {
    echo 'response.databases.name: ', $item['name'], PHP_EOL;
  }
}
```

　次回は、認証の必要なリクエストを取り上げてみたいと思います。