サンプルデータの作成は FileMaker Data API を使う 2025 年版 vol.1 を参照してください。
利用環境
以下の環境を前提に説明しています。
- Claris FileMaker Pro 21.1.1.41 macOS
- Claris FileMaker Server 21.1.1.40 Ubuntu 22(AMD)
- サーバ: Ubuntu 22.04.5 LTS
- SSL 証明書
- リクエストする側のサーバ(任意)
開発段階では、以下を使用した方が楽でしょう。
filemaker-data-api-v2.php
今回のシナリオに先立ち、以下の修正を施しました。
executeCurl() メソッド
// cURL 実行
static function executeCurl(string $curlopt_url, string $curlopt_customrequest, array $curlopt_httpheader = []): string
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $curlopt_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $curlopt_customrequest,
CURLOPT_HTTPHEADER => $curlopt_httpheader,
CURLOPT_POSTFIELDS => "{}",
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
getRecords() メソッド
今回のシナリオに合わせて、アップデートしました。
// レコード範囲の取得
public function getRecords(string $database, string $layout, string $bearer_session_token, int $_offset = 1, int $_limit = 100, string $_sort = ''): string
{
$this->layout = $layout;
$authorization = 'Authorization: Bearer ' . $bearer_session_token;
$curlopt_httpheader = array($authorization);
$_sort_string = !empty($_sort) ? '&_sort=' . urlencode($_sort) : '';
$endpoint = "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/layouts/{$layout}/records?_offset={$_offset}&_limit={$_limit}{$_sort_string}";
return self::executeCurl($endpoint, 'GET', $curlopt_httpheader);
}
filemaker-data-api-v2.php
<?php
class FileMaker_Data_API
{
public $host, $version, $database, $username, $password, $layout;
public $bearer_session_token;
function __construct (string $host, string $version)
{
$this->host = $host;
$this->version = $version;
}
/**
* リクエスト
**/
// ログイン
public function login (string $database, string $username, string $password): string
{
$this->database = $database;
$this->username = $username;
$this->password = $password;
$auth_value = $username . ':' . $password;
$authorization = 'Authorization: Basic ' . base64_encode($auth_value);
$content_type = 'Content-Type: application/json';
$curlopt_httpheader = array($authorization, $content_type);
$endpoint = "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/sessions";
return self::executeCurl($endpoint, 'POST', $curlopt_httpheader);
}
// ログアウト
public function logOut(string $database, string $bearer_session_token): string
{
$endpoint = "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/sessions/{$bearer_session_token}";
return self::executeCurl($endpoint, 'DELETE');
}
// データベースセッションの検証
public function validateSession (string $session_token): string
{
$authorization = 'Authorization: Bearer ' . $session_token;
$curlopt_httpheader = array($authorization);
$endpoint = "https://{$this->host}/fmi/data/{$this->version}/validateSession";
return self::executeCurl($endpoint, 'GET', $curlopt_httpheader);
}
// レコード範囲の取得
public function getRecords(string $database, string $layout, string $bearer_session_token, int $_offset = 1, int $_limit = 100, string $_sort = ''): string
{
$this->layout = $layout;
$authorization = 'Authorization: Bearer ' . $bearer_session_token;
$curlopt_httpheader = array($authorization);
$_sort_string = !empty($_sort) ? '&_sort=' . urlencode($_sort) : '';
$endpoint = "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/layouts/{$layout}/records?_offset={$_offset}&_limit={$_limit}{$_sort_string}";
return self::executeCurl($endpoint, 'GET', $curlopt_httpheader);
}
/**
* ユーティリティ
**/
// レスポンスコードの取得
public function getMessagesCode (string $response): string
{
$response_array = self::json2array($response);
return $response_array['messages'][0]['code'];
}
// Bearer Session Token 取得
public function getBearerSessionToken (string $response): string
{
$response_array = self::json2array($response);
$this->bearer_session_token = $response_array['response']['token'];
return $this->bearer_session_token;
}
// JSON を 配列へ変換
public function json2array (string $json): array
{
$json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
return json_decode($json, true);
}
// cURL 実行
static function executeCurl(string $curlopt_url, string $curlopt_customrequest, array $curlopt_httpheader = []): string
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $curlopt_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $curlopt_customrequest,
CURLOPT_HTTPHEADER => $curlopt_httpheader,
CURLOPT_POSTFIELDS => "{}",
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
}
Get Records のレスポンスの JSON 構造
前回、リクエストしたレイアウトはポータルのないものでしたので、Get Records のレスポンスの構造は次のようになります。
ここでは、データ件数 2件として、載せています。
{
"response":
{
"dataInfo":
{
"database":"(FileMaker ソリューション名)",
"layout":"player_batting_basic",
"table":"player_batting",
"totalRecordCount":1375,
"foundCount":1375,
"returnedCount":100
},
"data":
[
{
"fieldData":
{
"last_name_ first_name":"Hunter, Torii",
"player_id":"116338",
"year":"2015",
"ab":"521",
"hit":"125",
"single":"81",
"double":"22",
"triple":"0",
"home_run":"22",
"on_base_percent":".293"
},
"portalData":{},
"recordId":"1",
"modId":"0"
},
{
"fieldData":{
"last_name_ first_name":"...d",
"player_id":"...",
"year":"...",
"ab":"...",
"hit":"...",
"single":"...",
"double":"...",
"triple":"...",
"home_run":"...",
"on_base_percent":"..."
},
"portalData":{},
"recordId":"2",
"modId":"0"
}
]
},
"messages":
[
{
"code":"0",
"message":"OK"
}
]
}
大きく分けて、
response.dataInfo
response.data
messages
この3つになります。messages
については、これまでと変わりありません。
response.dataInfo
の中には、以下の情報が入ります。
- "database" FileMaker ソリューション名
- "layout" レイアウト名
- "table" テーブルオカレンス名
- "totalRecordCount" リクエストしたレイアウトの総レコード数
- "foundCOunt" リクエストしたレイアウトの現在のレコード数
- "returnedCount" リクエストしたレイアウトの現在のレコード中、取得したレコード数
response.data
は、レコードのフィールドデータとポータルデータ、レコード ID、modId(修正 ID)が、次の形式で入ります。
"fieldData":{
フィールド名:フィールドデータ
},
"portalData":{}, ※ 今回は空
"recordId":"",
"modId":"",
"portalDataInfo": {} ※ 今回は入りません
取得するデータ件数とソート
_offset と _limit
現在、対象にしている player_batting_basic レイアウトのデータは、2015年〜2024年の MLB の打者データのうち、STATCAST の規定に到達している打者の基本的なデータ(STATCAST のデータではなく、従来からある野球データ)を取得しています。
前回やった Get Records はデフォルトで、最初の 100 件のみが未ソートの状態で取得されます。
まず、取得するデータの件数を操作してみましょう。
これには _offset
と _limit
という2つのクエリパラメータを URL に追加します。
getRecords()
メソッドで呼んでいる executeCurl($endpoint, 'GET', $curlopt_httpheader);
の2番目の引数はリクエストメソッドを指定していますが、この getRecords()
メソッド は GET を使っているので、URL の最後に、次の形式で追加します。
?_offset=1&_limit=30
この場合、1件目から30件取得という意味になります。
これで、想定できるのは、例えば、Bootstrap のページネーションコンポーネント でしょうか。
response.dataInfo.totalRecordCount
でデータ総数は取得できるので、ここからページ数を割り出し、ページネーションコンポーネント を作ることが可能でしょう。
_sort
次に取得するデータをソートした状態で欲しい場合です。
これも、クエリパラメータとして渡します。形式は、以下のようになります。
?_sort=[{"fieldName":"フィールド名","sortOrder":"昇順、降順、または値一覧"}]
尚、前のパラメータに続ける場合は、?
ではなく &
で繋ぎます。
ソート対象のフィールド名を知らなければいけませんので、現在のサンプルデータのフィールド名とその意味を掲載します。
- last_name_ first_name 選手の姓名
- player_id プレイヤーID
- year シーズン
- ab 打数
- hit 安打
- single 単打
- double 二塁打
- triple 三塁打
- home_run 本塁打
- on_base_percent 出塁率
このサンプルデータは、CSV をインポートしてテーブルを作っているので、last_name_ first_name
の間に半角スペースが入っていることに注意してください。(フィールド名は適宜、修正して読み換えてください)
ここでは、on_base_percent
でソートすることにします。
シナリオ
ページネーションを使うことを想定して、1ページ30件で、2ページ目を表示、on_base_percent を降順でソートする。
get_records-v2.php
<?php
require_once(__DIR__ . '/filemaker-data-api-v2.php');
$host = 'FileMaker Server ドメイン名';
$version = 'vLatest';
$database = 'FileMaker ソリューション名';
$username = 'FileMaker ユーザ名';
$password = 'パスワード';
$layout = 'player_batting_basic';
$bearer_session_token = null;
$fmda = new FileMaker_Data_API($host, $version);
// ログイン
$response = $fmda->login($database, $username, $password);
// ログイン成功?
if ($fmda->getMessagesCode($response) === '0') {
// ログイン成功なら、Bearer Session Token を取得する
$bearer_session_token = $fmda->getBearerSessionToken($response);
} else {
// ログイン失敗の処理を書く
echo "FileMaker Data API へのログインに失敗しました。\n";
}
// (何らかの処理があり、リンクでページ遷移した想定)
// セッションの検証
$response = $fmda->validateSession($bearer_session_token);
if ($fmda->getMessagesCode($response) === '0') {
// セッション有効なら、行いたいリクエスト実行
$_offset = 31; // 31 件目から
$_limit = 30; // 30 件取得
$field_name = 'on_base_percent'; // ソート対象フィールド名
$sort_order = 'descend'; // 昇順 -> ascend、降順 -> descend、値一覧 -> 値一覧名
$_sort = [['fieldName' => $field_name, 'sortOrder' => $sort_order]]; // _sort パラメータの配列作成
$_sort = json_encode($_sort); // それを JSON化
$response = $fmda->getRecords($database, $layout, $bearer_session_token, $_offset, $_limit, $_sort);
print_r($response);
// レコード取得
} else {
// セッション無効なら、必要な Web データを保持して、ユーザに再ログインを促す
echo "再ログインしてください。\n";
}
// (何らかの処理)
// ログアウト
$response = $fmda->logOut($database, $bearer_session_token);
コメントにも書いていますが、設定と呼び出しは以下のようにします。
-
$_offset
に取得するレコードの開始位置を指定します。1ページ30件の2ページ目を取得したいので、31 となります -
$_limit
に取得するレコードの件数を指定します -
$_sort
にパラメータを配列で作り、JOSN 化します -
getRecords(FileMaker ソリューション名, レイアウト名, 現在の Bearer Session Token, 開始位置, 件数, ソートJSON)
形式で呼び出します
配列は、次の形式です。
[
[
"fieldName" => "フィールド名",
"sortOrder" => "ソート方法"
]
]
複数のソート条件がある場合は、次のようになります。例えば、プレイヤーID昇順、シーズン降順ならば、
[
[
"fieldName" => "player_id",
"sortOrder" => "ascend"
],
[
"fieldName" => "year",
"sortOrder" => "descend"
[
]
これを JSON エンコードして、引数としています。getRecords()
メソッドでは、この _sort の引数が ''
(空文字)ならば、このパラメータは作成しません。JSON が渡された場合は、URLエンコードして、パラメータを作っています。
次回は、Get Records で、スクリプトを使う方法を説明します。