FileMakerでWebアプリを実装するにあたり、気をつけたい箇所として挙げられる点のひとつに「オブジェクトフィールド」についての取扱いがある。オブジェクトフィールドに画像やPDFといったファイルが格納されており、PHPからこれらのファイルにアクセスするには1オブジェクトフィールドにたいして、1リクエストが発生するのは以前紹介したとおり。

1から作成する分にはこれらのことを注意して実装すればOK。しかし既存のFileMakerアプリケーションをWeb化する場合、これらオブジェクトフィールドに格納されているファイルをエクスポートし、ファイル参照用のパスを保存しておく作りに変える必要がある。今回はこれらの移行方法を簡単に紹介しよう。

オブジェクトフィールドからの脱却

サンプルで使用するFileMakerファイルの構成は次のとおり。

  • ファイル名: fxphp_tips.fp7
  • テーブル名: object_test
  • レイアウト名: object_test
  • フィールド情報: 別表を参照
フィールド名 コメント タイプ オプション
serial シリアルナンバ 数字 番号自動入力, ユニークな値
registTimeStamp 登録日時 タイムスタンプ 作成タイムスタンプ
updateTimeStamp 更新日時 タイムスタンプ 修正タイムスタンプ
fileName ファイル名 テキスト 計算値の自動入力: "fileObject"
fileObject オブジェクト オブジェクト  

テーブル「object_test」のフィールド一覧。fileObjectにオブジェクトを格納すると、そのファイル名がfileNameに格納される

オブジェクトフィールドが使用されているFileMakerファイルをWebアプリ用に最適化する場合、おおまかな手順は次のとおり。

  1. オブジェクトフィールド内のファイルを格納するディレクトリを決定
  2. 全レコードのオブジェクトフィールド書き出し
  3. エクスポートしたファイルへアクセスするためのパスを格納する、テキストタイプの計算フィールドを作成
  4. FileMaker上で表示するための、オブジェクトタイプの計算フィールドを作成

1 オブジェクトフィールド内のファイルを格納するディレクトリを決定

まず既存のオブジェクトフィールドをどのディレクトリに格納するのかを決定する。Webアプリから参照できる場所に配置する必要があるので、各Webサーバのドキュメントルート以下に配置すること。

  • Windowsでの格納先例: C:\inetpub\wwwroot\attached\
  • MacOS Xでの格納先例: /Library/WebServer/Documents/attached/

そしてレコードごとにファイルが格納されるように、ここではシリアル番号別にファイルを格納していくように定義する。たとえばシリアル番号が7のレコードのオブジェクトフィールドは

  • Windowsでの格納先例: C:\inetpub\wwwroot\attached\7(ファイル名)
  • MacOS Xでの格納先例: /Library/WebServer/Documents/attached/7/(ファイル名)

となる。これらのディレクトリはあらかじめPHPで作成してしまおう。

<?php
for ($n=1; $n<=10000; $n++)
{
    mkdir('./attached/' . $n);
}
?>

このPHPでは、attached以下に1~10000までのディレクトリを作成する。10000という数字は、想定されるレコード上限数を意味している。C:\inetpub\wwwrootまたは/Library/WebServer/Documents/に配置し、コマンドラインかターミナル上でPHPを実行。

ターミナルよりPHPを実行し、FileMakerのシリアル番号に対応するディレクトリをあらかじめ作成しておく

2 全レコードのオブジェクトフィールド書き出し

続いて全レコードのオブジェクトフィールドに格納されているファイルを、1で定義したパスにエクスポートする。全レコードのオブジェクトフィールドの内容をエクスポートするスクリプトステップは用意されていないので、ループで1件1件レコードでオブジェクトフィールドの内容をエクスポートしていくことになる。FileMakerスクリプトは次のとおり。

エラー処理 [ オン ]
ウインドウの固定
変数を設定 [ $ROOT_PATH; 値:Case ( Get ( システムプラットフォーム ) = 1; "filemac:" & Get ( システムドライブ ) & "Library/WebServer/Documents/attached/"; Get ( システムプラットフォーム ) = -2 ; "filewin:" & Get ( システムドライブ ) & "inetpub/wwwroot/attached/"; "" ) ]
レコード/検索条件/ページへ移動 [ 最初の ]
Loop
    If [ not IsEmpty ( object_test::fileName ) and not IsEmpty ( object_test::fileObject ) ]
        変数を設定 [ $serial; 値:object_test::serial ]
        変数を設定 [ $fileName; 値:object_test::fileName ]
        変数を設定 [ $exportFilePath; 値:$ROOT_PATH & $serial & "/" & $fileName ]
        フィールド内容のエクスポート [ object_test::fileObject; 「$exportFilePath」 ]
    End If
    レコード/検索条件/ページへ移動 [ 次の; 最後まできたら終了 ]
End Loop

注意したいのは、ファイルが壊れているなどしてオブジェクトフィールドの内容をエクスポートができない状態になっているレコードがあるとき。この場合、Get ( 最終エラー )でもエラーが補足できない上に、毎回警告のダイアログが出てしまうことになる。あらかじめ一括処理前におかしなレコードがないか確認をしておこう。

オブジェクトフィールドにいくつかファイルを格納してある状態で、上記スクリプトを実行

特定のディレクトリ以下にオブジェクトフィールドの内容がエクスポートされる

3 エクスポートしたファイルへアクセスするためのパスを格納する、テキストタイプの計算フィールドを作成

Webアプリ上で使用するための、テキストタイプの計算フィールドを作成しておく。フィールド名は「filePath」とした。計算式は次のとおり。

WebサーバがMacOS/Apacheの場合

"filemac:" & Get ( システムドライブ ) & "Library/WebServer/Documents/attached/" & serial & "/" & fileName

WebサーバがWindows/IISの場合

"filewin:" & Get ( システムドライブ ) & "inetpub/wwwroot/attached/" & serial & "/" & fileName

この計算フィールドにはファイルへのパス情報がつねに格納される。PHPからはimage_proxy.phpを使ってオブジェクトフィールドにアクセスするのではなく、このフィールドを参照してパスを加工し、<img>タグやheader(file-attached)などと使ってファイルへのアクセスをおこなえば良い。

4 FileMaker上で表示するための、オブジェクトタイプの計算フィールドを作成

最後に、これまで動作していたオブジェクトフィールドに代わる、オブジェクトタイプの計算フィールドを作成する。フィールド名は「fileObject_2」とした。計算式は3で作成したフィールドをそのまま指定するだけ。

filePath

レイアウト上に配置されていた旧オブジェクトフィールドをこの計算フィールドに置換することで、これまでの使い勝手にちかいユーザインタフェースが実現できるようになる。

fileObject_2はオブジェクトタイプの計算フィールド。ダブルクリックでファイルを開く

これでオブジェクトフィールドにファイルを直接格納する手法から、ファイル参照をもちいたへの移行が完了する。運用がうまくおこなえるタイミングになったときに既存のオブジェクトフィールドを削除すれば、ファイルサイズも小さくなり、安定性が増す。ここで紹介した一連の手順はあくまで例だ。1テーブルにオブジェクトフィールドが複数ある場合や、Windows/MacOSが混在している環境などでは各自工夫してほしい。