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

 サンプルソリューションのデータは、[新しいサンプルデータを作る](https://qiita.com/RemixWorksLLC/items/04a5e616e59eb062bba9#新しいサンプルテーブルを作る) を参照してください。

 この記事で使用するソースコードは、[FileMaker Data API を使う 2025年版 vol.12#残りの HTML ソースコードの PHP 化](https://qiita.com/RemixWorksLLC/items/f04d4b7ed441e38a54cb#残りの-html-ソースコードの-php-化) にまとめてあります。

 その後の変更(Find Records のテストと JSON ファイル)は、[FileMaker Data API を使う 2025年版 vol.13](https://qiita.com/RemixWorksLLC/items/1353124d7ef044bee7df) 、及び、[FileMaker Data API を使う 2025年版 vol.14](https://qiita.com/RemixWorksLLC/items/162f5b5455bbe8db6aa1) 参照してください。

  現在の構造は以下の通りです。
```
.
├── css
│   ├── bootstrap-common.css
│   └── fmda-form.css
├── find-records-test.php
├── find-records-test2.php
├── find-records-test3.php
├── html
│   └── edit-record.html
├── index.php
├── js
│   ├── fmda-form-check.js
│   └── fmda-select-page.js
├── json
│   ├── html-contents.json
│   ├── standings-al-east-2024.json
│   └── standings-all-2024.json
└── php
    ├── bs-builder-class.php
    ├── bs-frame-class.php
    ├── filemaker-data-api-class.php
    ├── php-functions.php
    ├── preferences.php
    └── temporary-functions.php
```

## 利用環境

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

 - 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](https://www.postman.com)

 Web ページの作成は、以下を条件とします。
 - Bootstrap v5.3.3
 - [Bootstrap Examples Checkout](https://getbootstrap.com/docs/5.3/examples/checkout/) を土台にしています。
 - PHP 8.2.22

## フォームデータを表示する

　前回までの記事で、FileMaker 情報ブロックの表示が出来ているはずです。
 今回は、左側のフォームデータを表示させてみます。
  目標イメージは次の画像です。
![スクリーンショット 2025-02-15 21.09.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833520/44855d5e-8c94-495d-b377-ca4262007d50.png)

　Find Records リクエストで、リーグ昇順と勝利数降順で全件取得しているので、ヤンキースが 1件目になります。この画像だと、分かりにくいのですが、「勝率（任意）」に表示されている「.500」はデータではなくプレースホルダです。このプレースホルダはやめていいかもしれませんね。
 やめてしまいましょう。

 　こんなとき弄るのは JSON です。`html-contents.json` の `formControls` JSON 配列の８番目のデータのキー `placeholder` を弄れば、変更できます。

### `html-contents.json` の `formControls` JSON 配列の８番目
```
        {
            "id" : "winning_percentage",
            "label" : "勝率",
            "type" : "text",
            "name" : "winning_percentage",
            "placeholder" : "",
            "required" : "",
            "disabled" : "",
            "feedback" : "",
            "option" : [
                {
                    "value" : ""
                }
            ]
        },
```

 これで、プレースホルダは表示されなくなります。
 ![スクリーンショット 2025-02-15 21.18.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833520/e4be03ce-ce1c-4f9a-8449-4a4ae74e16a0.png)

 FileMaker を使っている場合、こういったテキストのコンテンツは JSON 化しておくて、FileMaker Pro で管理することが容易になります。
 実際には、`html-contents.json` のような網羅的な JSON よりも、この場合でしたら `form-controls.json` のような形に特化してあげれば、FileMaker Pro 側の処理が単純になります。
 この管理情報が入っているテーブルを更新し、スクリプトで、JSON 作成〜「URL から挿入」スクリプトステップの「cURL オプション」で、サーバ上の JSON を更新してあげれば、今、手作業でやったことと同じことが FileMaker Pro 上で可能です。

 それでは、フォームデータを表示するための変更を施していきましょう。
 現在、`temporary_functions.php` の `records_find_records()` 関数の中で、全件データは、`$team_data` 配列に入っています。
　これを Form の該当コントロールの `value` として渡してあげれば表示されます。但し、「リーグ」と「地区」は `<select>` を使っているので、該当オプションに `selected` を与える必要があります。
　以上のことを、次の流れで行います。

 1. ファーストアクセスで、Find Records 発行で全件取得（前回記事）
 1. フォーム表示用のデータを抜き出して、配列に入れておく
 1. フォームに表示

 まず、フォーム表示用データを入れる配列を用意しておきましょう。

 ### preferences.php 66行目に追加
```
$response_field_data  = [];
```

　次に、`temporary-functions.php` の中の `records_find_records()` 関数で、Find Records の処理後に、`$response_field_data` へ データをセットします。

## temporary-functions.php の records_find_records() 関数
```
function records_find_records( ): void
{

    global $fmda, $response, $bearer_session_token, $database, $layout, $request_body;
    global $result, $data_info, $team_data, $response_field_data;
    global $info_item_content;
    if ($fmda->getMessagesCode($response) === '0') {
        // セッション有効なら、行いたいリクエスト実行
    
        // レコードの検索
        $response   = $fmda->findRecords($database, $layout, $bearer_session_token, $request_body);
    
        // 結果セット処理
        $result = $fmda->json2array($response);
        
        if ($fmda->getMessagesCode($response) === '0') {
            $data_info  = $result['response']['dataInfo'];
            $team_data  = $result['response']['data'];

            // 追加部分
            array_push($info_item_content, $data_info['database']);
            array_push($info_item_content, $data_info['layout']);
            array_push($info_item_content, $data_info['table']);
            array_push($info_item_content, $team_data[0]['recordId']);
            array_push($info_item_content, $team_data[0]['modId']);
            array_push($info_item_content, $data_info['totalRecordCount']);
            array_push($info_item_content, $data_info['foundCount']);
            array_push($info_item_content, $data_info['returnedCount']);
            $response_field_data    = [
                $team_data[0]['fieldData']['mlb_site_id'],
                $team_data[0]['fieldData']['year'],
                $team_data[0]['fieldData']['league'],
                $team_data[0]['fieldData']['division'],
                $team_data[0]['fieldData']['team'],
                $team_data[0]['fieldData']['wins'],
                $team_data[0]['fieldData']['losses'],
                $team_data[0]['fieldData']['winning_percentage'],
                $team_data[0]['fieldData']['runs_scored'],
                $team_data[0]['fieldData']['runs_allowed'],
                $team_data[0]['fieldData']['pythagorean_expectation'],
                $team_data[0]['fieldData']['expected_win_loss'],
                $team_data[0]['fieldData']['winning_percentage_diﬀerence']
            ];
        }
    } else {
        // セッション無効なら、必要な Web データを保持して、ユーザに再ログインを促す
        echo "<div class=\"alert alert-warning\" role=\"alert\">セッションが切れました。再ログインしてください。</div>\n";
    }
}
```

　これで１件目のフォームデータが、`$response_field_data` に入るので、あとはフォームに渡してあげればいいだけです。
 フォームは、`bs-builder-class.php` の `BsBuilder` クラス、`CreateForm` メソッドで作っていますので、各コントロールが `value` を持つように、加えて、`<select>` コントロールでは、該当データが `selected` されるように変更を加えます。

 ### CreateForm() メソッド
```
  static function CreateForm (
    array &$form_prefernces,
    array &$form_controls,
    array &$field_data,
  ): void {

    echo <<<_HTML_
<div class="col-md-7 col-lg-8">
  <h4 class="mb-3">{$form_prefernces[0]}</h4>
    <form action="{$form_prefernces[1]}" method="POST" class="needs-validation" novalidate>
      <div class="row g-3">
    
_HTML_; // begin

    $i = 0;
    foreach ($form_controls as $key => $value) {
      $required         = '';
      $secondary_label  = '';
      if ($value['required'] === '1')
        $required         = 'required';
      else
        $secondary_label  = '<span class="text-body-secondary">（任意）</span>';

      if ($value['type'] === 'select') {
        echo <<<_HTML_
<div class="col-sm-6">
  <label for="{$value['id']}" class="form-label">{$value['label']}{$secondary_label}</label>
  <select class="form-select" id="{$value['id']}" name="{$value['name']}" {$required} {$value['disabled']}>
    <option value="">選択...</option>

_HTML_;

        foreach ($value['option'] as $option_key => $option_value) {
          $selected       = $field_data[$i] === $option_value['value'] ? 'selected' : '';
          $current_value  = $selected === 'selected' ? $field_data[$i] : $option_value['value'];
          echo "<option value=\"{$current_value}\" {$selected} >{$option_value['value']}</option>\n";{$option_value['value']}</option>\n";
        }
        echo "</select>\n";

      } else {
        echo <<<_HTML_
<div class="col-sm-6">
  <label for="{$value['id']}" class="form-label">{$value['label']}{$secondary_label}</label>
  <input type="{$value['type']}" class="form-control" id="{$value['id']}" name="{$value['name']}"  value="{$field_data[$i]}" placeholder="{$value['placeholder']}" {$required} {$value['disabled']}>

_HTML_;

      } // if ($value['type'] === 'select')

      if (!empty($required)) {
        echo <<<_HTML_
<div class="invalid-feedback">
  {$value['feedback']}
</div>

_HTML_;

      } // if (!empty($required))

      echo "</div>\n";

      $i += 1;
    } // foreach ($form_controls as $key => $value)

  echo <<<_HTML_
  </div> <!-- / .row -->

  <hr class="my-4">

  <button class="w-100 btn {$form_prefernces[2]} btn-lg" type="submit">{$form_prefernces[3]}</button>
</form> <!-- / .needs-validation -->

_HTML_;

  }
```

　変更部分は、まず、フォームデータを参照するための引数を追加しています。
```
static function CreateForm (
    array &$form_prefernces,
    array &$form_controls,
    array &$field_data,
  ): void {
```

　次に、`<select>` コントロールの `<option>` タグに `selected` されることの判別を行なっています。ここでは、一応、`value` も与えていますが、選択要素と渡す値が同じなら、与えなくても結果は一緒です。
 例えば、選択要素「アメリカン・リーグ」、値「AL」のような場合は、`value` が必要になるので、一応、これに対応しておこうと思います。
```
        foreach ($value['option'] as $option_key => $option_value) {
          $selected       = $field_data[$i] === $option_value['value'] ? 'selected' : '';
          $current_value  = $selected === 'selected' ? $field_data[$i] : $option_value['value'];
          echo "<option value=\"{$current_value}\" {$selected} >{$option_value['value']}</option>\n";
        }
        echo "</select>\n";
```

　三項演算子で、現在の `$field_data[$i]` が、選択要素 `$option_value['value']` と一致するなら、`$selected` を　`'selected'` に、そうでなければ `''` を与えます。
 値が「ニューヨーク・ヤンキース」で、選択要素も「ニューヨーク・ヤンキース」なら、`selected` ということです。

 　この部分の HTML 出力は、例えば、リーグなら以下のようになります。
```
<div class="col-sm-6">
  <label for="league" class="form-label">リーグ</label>
  <select class="form-select" id="league" name="league" required >
    <option value="">選択...</option>
<option value="アメリカン・リーグ" selected>アメリカン・リーグ</option>
<option value="ナショナル・リーグ" >ナショナル・リーグ</option>
</select>
<div class="invalid-feedback">
  リーグを選択してください。
</div>
</div>

```

 これはチェックボックスでも原理は同じになります。チェックボックスの場合は、`selected` ではなく、`checked` を与えます。

 `<select>` 以外は、次の箇所を変更しています。
```
        echo <<<_HTML_
<div class="col-sm-6">
  <label for="{$value['id']}" class="form-label">{$value['label']}{$secondary_label}</label>
  <input type="{$value['type']}" class="form-control" id="{$value['id']}" name="{$value['name']}"  value="{$field_data[$i]}" placeholder="{$value['placeholder']}" {$required} {$value['disabled']}>

_HTML_;
```

　一例として、チーム名の HTML 出力は次のようになります。
```
<div class="col-sm-6">
  <label for="team" class="form-label">チーム名</label>
  <input type="text" class="form-control" id="team" name="team"  value="ニューヨーク・ヤンキース" placeholder="" required >
<div class="invalid-feedback">
  チーム名を入力してください。
</div>
</div>
```

 最後に、`CreateForm` メソッドに引数を増やしていますから、呼び出し側も変更します。

 ### index.php 40行目
```
BsBuilder::CreateForm($form_preferences, $form_controls, $response_field_data);
```

　以上で、フォームデータが表示されるようになります。

 　これで積み残しは、以下になります。
・フッタのリンクからの機能切り替え
・ページネーション
・FileMaker 情報ブロックの下の「取得する」フォーム
・各機能の FIleMaker Data API リクエスト

　現在、表示中の機能はレコード編集ですが、次回は、レコード更新（records - Edit Record）と、空欄になっているフィールドをどうするかという問題に取り組みたいと思います。