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.7

Last updated at Posted at 2025-02-09

サンプルデータの作成は 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.1.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,
		array &$script_name_array,
		array &$script_param_array,
		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) : '';

        $script_prerequest			= '';
    	$script_prerequest_param	= '';
    	$script_presort				= '';
    	$script_presort_param		= '';
    	$script						= '';
    	$script_param				= '';
		// リクエスト処理前のスクリプト
		if ($script_name_array[0] !== '') {
			$script_prerequest	= '&script.prerequest=' . $script_name_array[0];
			$script_prerequest_param = '&script.prerequest.param=' . urlencode(json_encode($script_param_array[0]));
		}
		
		// ソート前のスクリプト
		if ($script_name_array[1] !== '') {
			$script_presort	= '&script.presort=' . $script_name_array[1];
			$script_presort_param = '&script.presort.param=' . urlencode(json_encode($script_param_array[1]));
		}

		// リクエスト処理後のスクリプト
		if ($script_name_array[2] !== '') {
			$script	= '&script=' . $script_name_array[2];
			$script_param = '&script.param=' . urlencode(json_encode($script_param_array[2]));
		}
		
		$endpoint        	= "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/layouts/{$layout}/records?_offset={$_offset}&_limit={$_limit}{$_sort_string}{$script_prerequest}{$script_prerequest_param}{$script_presort}{$script_presort_param}{$script}{$script_param}";
		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;
	}
}

Find Records

前回まで、records - Get Records を使用してレコードを取得していましたが、今回は、records - Find Records を使用して同じことをやってみたいと思います。

Get Records と Find Records の顕著な違いは、リクエストメソッドが GETPOST かということにあります。GET である Get Records では、クエリパラメータを URL の一部として渡していました。Find Records は、POST なので、URL でクエリパラメータを渡すということはありません。
Find Records では、JSON形式で、リクエストボディを作り、ポストフィールドとして渡します。
 渡せるクエリパラメータは、ほとんど Get Records と同じです。但し、すべてを JSON 形式で渡すということになります。

では、まず、filemaker-data-api-v2.1.php に findRecords() メソッドを getRecords() メソッドの下に追加します。

// 検索の実行
	public function findRecords(
		string $database,
		string $layout,
		string $bearer_session_token,
		string $request_body
		): string
	{
		$authorization      = 'Authorization: Bearer ' . $bearer_session_token;
		$content_type       = 'Content-Type: application/json';
		$curlopt_httpheader = array($authorization, $content_type);
		$endpoint        	= "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/layouts/{$layout}/_find";

		return self::executeCurl($endpoint, 'POST', $curlopt_httpheader, $request_body);
	}
    

さらに、executeCurl() メソッドもアップデートして、ファイル名を filemaker-data-api-v2.2.php とします。

    // cURL 実行
    static function executeCurl(string $curlopt_url, string $curlopt_customrequest, array $curlopt_httpheader = [], string $current_postfields = ''): string
    {
		$current_postfields	= !empty($current_postfields) ? json_encode(json_decode($current_postfields)) : '{}';

		$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_POSTFIELDS => $current_postfields,
			CURLOPT_HTTPHEADER => $curlopt_httpheader,
		));
	
		$response   = curl_exec($curl);
	
		curl_close($curl);
		return $response;
	}
    

 メインプログラムも、ほとんど変わりませんが、クエリパラメータの作成が大変、楽になります。

find_records.php

<?php

require_once(__DIR__ . '/filemaker-data-api-v2.2.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') {
    // セッション有効なら、行いたいリクエスト実行
    $request_body   = <<<_JSON_
{
    "query" :
    [
        {
            "year" : "2024",
            "omit" : "false"
        }
    ],
    "sort" :
    [
        {
            "fieldName" : "on_base_percent",
            "sortOrder" : "descend"
        }
    ],
    "offset" : "1",
    "limit" : "10"
}
_JSON_;

    // レコードの検索
    $response   = $fmda->findRecords($database, $layout, $bearer_session_token, $request_body);

    // 結果セット処理
    $result = $fmda->json2array($response);
    
    if ($fmda->getMessagesCode($response) === '0') {
        $player_data    = $result['response']['data'];
        foreach ($player_data as $key => $value) {
            echo $value['fieldData']['last_name_ first_name'] . ' - ';
            echo $value['fieldData']['on_base_percent'], PHP_EOL;
        }
    }

    echo "総レコード数: {$result['response']['dataInfo']['totalRecordCount']}\n";
    echo "現在レコード数: {$result['response']['dataInfo']['foundCount']}\n";
    echo "取得レコード数: {$result['response']['dataInfo']['returnedCount']}\n";

} else {
    // セッション無効なら、必要な Web データを保持して、ユーザに再ログインを促す
    echo "再ログインしてください。\n";
}

// (何らかの処理)

// ログアウト

$response = $fmda->logOut($database, $bearer_session_token);

 リクエストメソッドが POST の場合、ポストフィールドに JSON をそのまま渡せばいいので、ソースコード内に JSON をハードコードしています。
 このままでは、空白、改行が沢山含まれてしまうので、一旦、配列にして、それをまた JSON に戻すという処理を入れて、一気に、空白文字を削除しています。正規表現を使うよりシンプルに変換できると思います。

JSON を外部ファイルとして持てば、条件に応じて結果セットを変えるという応用もできるでしょう。

 Get Records では、2024年の選手データに絞り込むためにスクリプトを使用しましたが、Find Records では、キー query の中に、次の形式で、条件を設定していくだけで、同じことが実現できます。

"query" :
    [
        {
            "フィールド名" : "検索する値",
            "omit" : "false"
        },
        {
            "フィールド名r" : "検索する値",
            "omit" : "false"
        }
    ] 

この キー query はFind Records リクエストでは必須です。
キー omit は、除外検索のフラグになっています。true とすれば、除外検索になります。

 スクリプトも、次の形式で JSON に追加すれば指定できます。

"script.prerequest" : "リクエスト処理前に実行するスクリプト名",
"script.prerequest.param" : "リクエスト処理前に実行するスクリプトの引数",
"script.presort" : "ソート実行前に実行するスクリプト名",
"script.presort.param" : "ソート実行前に実行するスクリプトの引数",
"script" : "リクエスト処理後に実行するスクリプト名",
"script.param" : "リクエスト処理後に実行するスクリプトの引数"

 考え方は、Get Records のスクリプト指定と同じです。

完成版 filemaker-data-api-v2.2.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,
		array &$script_name_array,
		array &$script_param_array,
		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) : '';

        $script_prerequest			= '';
    	$script_prerequest_param	= '';
    	$script_presort				= '';
    	$script_presort_param		= '';
    	$script						= '';
    	$script_param				= '';
		// リクエスト処理前のスクリプト
		if ($script_name_array[0] !== '') {
			$script_prerequest	= '&script.prerequest=' . $script_name_array[0];
			$script_prerequest_param = '&script.prerequest.param=' . urlencode(json_encode($script_param_array[0]));
		}
		
		// ソート前のスクリプト
		if ($script_name_array[1] !== '') {
			$script_presort	= '&script.presort=' . $script_name_array[1];
			$script_presort_param = '&script.presort.param=' . urlencode(json_encode($script_param_array[1]));
		}

		// リクエスト処理後のスクリプト
		if ($script_name_array[2] !== '') {
			$script	= '&script=' . $script_name_array[2];
			$script_param = '&script.param=' . urlencode(json_encode($script_param_array[2]));
		}
		
		$endpoint        	= "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/layouts/{$layout}/records?_offset={$_offset}&_limit={$_limit}{$_sort_string}{$script_prerequest}{$script_prerequest_param}{$script_presort}{$script_presort_param}{$script}{$script_param}";
		return self::executeCurl($endpoint, 'GET', $curlopt_httpheader);
	}

	// 検索の実行
	public function findRecords(
		string $database,
		string $layout,
		string $bearer_session_token,
		string $request_body
		): string
	{
		$authorization      = 'Authorization: Bearer ' . $bearer_session_token;
		$content_type       = 'Content-Type: application/json';
		$curlopt_httpheader = array($authorization, $content_type);
		$endpoint        	= "https://{$this->host}/fmi/data/{$this->version}/databases/{$database}/layouts/{$layout}/_find";

		return self::executeCurl($endpoint, 'POST', $curlopt_httpheader, $request_body);
	}

    /**
     * ユーティリティ
     **/

    // レスポンスコードの取得
	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 $current_postfields = ''): string
    {
		$current_postfields	= !empty($current_postfields) ? json_encode(json_decode($current_postfields)) : '{}';

		$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_POSTFIELDS => $current_postfields,
			CURLOPT_HTTPHEADER => $curlopt_httpheader,
		));
	
		$response   = curl_exec($curl);
	
		curl_close($curl);
		return $response;
	}
}

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?