0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2025-02-08

 サンプルデータの作成は 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 で、スクリプトを使う方法を説明します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?