FX.php を初めて触る人のために

# FX.php の現状
現時点で`FX.php`の最新版は[GitHubに公開されています](https://github.com/yodarunamok/fxphp)。一時期はウェブ上で検索しても見当たらない（ページが消失）か、バージョンが極端に古いかのときがあったのですが、GitHubにコミットされていて安心しました。

# 初めての FX.php
さて、それでは FX.php を用いて XML 経由で FileMaker Server のデータを操作していきます。CRUD のいずれも可能ですが、ここでは基礎となる R（Read）のみを見ていきます。

# 下準備
12/7（水）の記事にあるとおりの FX.php のインストールは済んでいるものとします。あとはこれを`require`してあげればいいです。

```php:fxphp_first_trial.php
<?php
require_once("./fxphp/FX.php"); # fxphp/ に展開した場合
```

# FX クラスのインスタンス（クエリ）を作る
FX.php も FileMaker API for PHP と同じような感じで検索ができます。まずは FX クラスから`$query`というインスタンスを作成しましょう。その際、必須の引数が二つあり、第一引数として FileMaker Server のアドレス、第二引数としてポート番号を取ります。

#### FileMaker Server のアドレスとポート番号

```php:fxphp_first_trial.php
$query = new FX("FileMaker Server のアドレス", 80);
```

#### ユーザー名とパスワード
あとは`$query`の必要なメソッドをどんどん実行していきます。まずはユーザー名とパスワードです。

```php:fxphp_first_trial.php
$query->SetDBUserPass("ユーザー名", "パスワード");
```

#### データベース名とレイアウト名
次にデータベース名とレイアウト名です。

```php:fxphp_first_trial.php
$query->SetDBData("データベース名", "レイアウト名");
```

#### 検索条件
そして検索条件です。第一引数にフィールド名、第二引数に検索条件を入力します。第二引数に取る検索条件の指定方法は FileMaker でのそれと同じ書式になります。

```php:fxphp_first_trial.php
$query->AddDBParam("フィールド名", "==apple");
```

# 検索を実行する
あとは`FMFind()`メソッドを実行すれば検索完了です。

```php:fxphp_first_trial.php
$query->FMFind();
```

# 検索結果について（生の XML）
FX.php は XML の Web 公開機能を用いているため、内部的には XML でデータが返ってきています。こんな感じですね。

![fm_Qiita_20.png](https://qiita-image-store.s3.amazonaws.com/0/72181/b8d0f54e-ccd6-62b7-0652-5fb0b37ad775.png)

# 検索結果について（FX.php の返り値）
FX.php では上記の結果を配列に格納しています。詳しくは`var_dump()`で見てほしいのですが、`["data"]`以下に検索にヒットした分だけのレコードが並んでいます。ただ、そのレコードの添字（キー）が例えば`["426639.218"]`のような形になっています（以下参照）。

```bash
array(9) {
  ["data"]=>
  array(1) {
    ["426639.218"]=>
    array(11) {
      ["hogehoge"]=>
      array(1) {
        [0]=>
        string(17) "fugafuga"
      }
      ["FOOBAR"]=>
      array(1) {
        [0]=>
        string(0) ""
```

この数値は、前述した 生XML の`<ROW MODID="218" RECORDID="426639">`の部分を、`RECORDID.MODID`というように連結した値になります。

このキーを事前に予想することは不可能であり、このキーの配列が`["data"]["426639.218"]`という上部の階層に来ていることから、検索結果のレコードを取り出すには`foreach`を使うのが一般的ということになります。

# レコードIDだけを取得するために
FX.php を用いて手動で（？）レコードIDを取得するためには、一意にヒットする検索を行い、以下のような処理を行えばいいでしょうか[^1]。

```php
$record_id = strtok(array_keys($find_results["data"])[0], ".");
```

`foreach`で回すのがやはりよさそうです。

# なぜレコードIDがそんなにほしいか
Read はいいのですが、[Update や Delete にはレコードIDを使う](http://news.mynavi.jp/column/fmxphp/003/)からです。

# 具体例
いろいろ余談的なことも書いてきましたが、具体例で考えましょう。。

以下のように`Staff`というデータベースの`StaffData`レイアウト内の`staff_data`というテーブルを用います[^2]。

![fm_Qiita_02.png](https://qiita-image-store.s3.amazonaws.com/0/72181/fdefe835-1538-1f7e-41ff-08d165504f1f.png)

![fm_Qiita_03.png](https://qiita-image-store.s3.amazonaws.com/0/72181/2fb3cf37-c1d7-92e7-5344-31b579ed7df0.png)

以下の5つのカラムが定義されているのが分かります。

- `id`
- `name`
- `gender`
- `work`
- `point`

このテーブルに対して 7 つのデータが投入されています。

## コードを書く
これまでに書いた内容をまとめて、以下のような検索条件で検索をしてみましょう。

> `gender`が`female`であるレコード

以下がコードになります。

```php:find_record_for_gender_female_fxphp.php
<?php
require_once("./fxphp/FX.php"); # fxphp/ に展開した場合

$query = new FX("FileMaker Server のアドレス", 80);
$query->SetDBUserPass("ユーザー名", "パスワード");
$query->SetDBData("Staff", "StaffData");
$query->AddDBParam("gender", "==female");
$result_records = $query->FMFind();

# 検索結果の表示
echo count($result_records["data"]) . " 件ヒットしました！" . "\n\n";
echo "ヒットした方のお名前は以下のとおりです" . "\n";
foreach ($result_records["data"] as $result_record) {
    echo $result_record["name"] . "\n";
}
```

```bash:結果
3 件ヒットしました！

ヒットした方のお名前は以下のとおりです
higashino
ishikawa
kawano
```

# エラーコード
エラーコードは上記での`$query`に対して以下のようにして取得できます。エラーコード一覧は[こちら](http://news.mynavi.jp/column/fmxphp/014/)に詳しくまとまっています。

```php
echo $query->fxError
```

他に、デバッグ方法として、`FX_Fuzzy_Debugger(DEBUG_FUZZY)`というものを使う方法もあります。

# 結論
返り値の配列の構造に注意すれば、手続きは FileMaker API for PHP より簡潔に書けるかと思います。アーカイブに同梱の`Documentation`に詳しいドキュメントがありますので参考にするといいでしょう。FX.php のコード内にも少し設定できる箇所がありますので、さらに興味があればソースを読み込んでみるのも面白いかと思います。

[^1]: どう見ても無理矢理過ぎる
[^2]: いろいろ問題がある設計ですが、あくまでサンプルとして分かりやすさを重視しています