FMCakeMixのUser Guide.pdfを参考に、CakePHP x FileMakerでWebアプリの作成方法を紹介する。FX.phpに添付されているFileMakerファイルをベースに、Paginationを使った一覧画面の実装方法を。5回目よりCakePHP, FMCakeMixの規約、FileMakerデータベース、database.php、モデル、Booksの登録・一覧・詳細・編集・削除処理、そして値一覧を使ったひととおりの処理を紹介した。FMCakeMixチュートリアルもいよいよ大詰め。最後に紹介するテーマは、関連レコード/ポータルレコードの取扱いについてだ。

Hello, FMCakeMix! チュートリアル / ポータルの取扱いの違い

FMCakeMixチュートリアルで最後に紹介するテーマは「関連レコード/ポータルレコードの取扱い」について。これまでFX.phpやFileMaker API for PHPを使用してポータルのUIをWebで実現してきたデベロッパにとっては、ややとっつきづらいものになると思うのであらかじめ注意したい。

まずFX.phpとFMCakeMixとでポータルレコードの取扱いがどう違うかを簡単に紹介しよう。チュートリアルで使用しているFileMakerデータベースは、現在(1)authors-(複)booksの関係となっている。レコードを表示するテーブルが「authors」のレイアウトを作成し、authorsのフィールドを配置。その後、関連するbooksのレコードを表示するポータルを配置する。

FileMakerレイアウト「author_view」を作成。authorテーブルのフィールドと、関連するbooksのレコードを表示するポータルを配置

1つの著者(Author)に複数の書籍(Book)が紐づく

レイアウトを作成したら、まずはFX.phpでアクセスしてどのような配列データが返るかを確認してみよう。authors_controller.phpにfx_portal_testアクションを作成し、FX.phpでアクセスするコードを追加する。

authorsコントローラ記述例(FX.php接続テスト) - /app/controller/authors_controller.php

function fx_portal_test()
{
    $this->autoRender = false;
    $data = new FX('localhost', 80, 'FMPro9', 'http');
    $data->SetDBData('fmcakemix_db','author_view', 1);
    $data->SetDBUserPass('fmcakemix_user','fmcakemix_password');
    $data->AddDBParam('id', 4); 
    $dataSet = $data->FMFind();
    echo '<pre>';
    var_dump($dataSet);
}

このアクションではFMCakeMix経由ではなく、直接FX.phpを使ってauthor_viewレイアウトにアクセス。idが4のレコードを取得し、var_dump()で展開する。Webブラウザでhttp://localhost/cake/authors/fx_portal_testにアクセスすると、配列が表示される。

FMCakeMixを経由せず、直接FX.phpでauthor_viewレイアウトにアクセスした場合に返る配列

取得した配列のdata部は次のとおり。

  ["data"]=>
  array(1) {
    ["4.0"]=>
    array(8) {
      ["id"]=>
      array(1) {
        [0]=>
        string(1) "4"
      }
      ["created"]=>
      array(1) {
        [0]=>
        string(10) "1290488528"
      }
      ["modified"]=>
      array(1) {
        [0]=>
        string(10) "1290488528"
      }
      ["name"]=>
      array(1) {
        [0]=>
        string(15) "池波正太郎"
      }
      ["books::id"]=>
      array(7) {
        [0]=>
        string(2) "10"
        [1]=>
        string(2) "11"
        [2]=>
        string(2) "12"
        [3]=>
        string(2) "13"
        [4]=>
        string(2) "14"
        [5]=>
        string(2) "15"
        [6]=>
        string(2) "16"
      }
      ["books::created"]=>
      array(7) {
        [0]=>
        string(10) "1290488572"
        [1]=>
        string(10) "1290488579"
        [2]=>
        string(10) "1290488587"
        [3]=>
        string(10) "1290488594"
        [4]=>
        string(10) "1290488648"
        [5]=>
        string(10) "1290488671"
        [6]=>
        string(10) "1290488679"
      }
      ["books::modified"]=>
      array(7) {
        [0]=>
        string(10) "1290488572"
        [1]=>
        string(10) "1290488579"
        [2]=>
        string(10) "1290488587"
        [3]=>
        string(10) "1290488594"
        [4]=>
        string(10) "1290488648"
        [5]=>
        string(10) "1290488671"
        [6]=>
        string(10) "1290488679"
      }
      ["books::title"]=>
      array(7) {
        [0]=>
        string(15) "鬼平犯科帳"
        [1]=>
        string(12) "剣客商売"
        [2]=>
        string(24) "仕掛人・藤枝梅安"
        [3]=>
        string(15) "真田太平記"
        [4]=>
        string(15) "田園の微風"
        [5]=>
        string(21) "江戸切絵図散歩"
        [6]=>
        string(12) "男の作法"
      }
    }
  }

ポータルに配置されているフィールド「books::id」や「books::title」については、その配列内に関連レコードのフィールド内容が格納されていることがわかる。従来、FX.phpを使った実装ではこれらをwhileなりforeachなりforなりで展開し、ポータルのUIを実現していた。

それでは次に、FMCakeMixでこれらのデータがどう変数に格納されるかを確認してみよう。さきほどと同様、テスト用のアクションを作成し、FMCakeMixでアクセスするコードを追加する。

authorsコントローラ記述例(FMCakeMix接続テスト) - /app/controller/authors_controller.php

function fmcakemix_portal_test()
{
    $this->autoRender = false;
    $this->Author->defaultLayout = 'author_view';
    echo '<pre>';
    var_dump($this->Author->read(null, 4));
}

fmcakemix_portal_test()ではコントローラ側で接続先のFileMakerレイアウト($this->Author->defaultLayout)を変更している。あとはFX.php同様、read()をもちいてidが4のレコードを取得し、var_dump()で展開する。Webブラウザでhttp://localhost/cake/authors/fmcakemix_portal_testにアクセスする。

さきほどのFX.phpと同様の条件下でFMCakeMixをもちいてアクセス

取得した配列は次のとおり。

array(1) {
  ["Author"]=>
  array(10) {
    ["-recid"]=>
    string(1) "4"
    ["-modid"]=>
    string(1) "0"
    ["id"]=>
    string(1) "4"
    ["created"]=>
    string(10) "1290488528"
    ["modified"]=>
    string(10) "1290488528"
    ["name"]=>
    string(15) "池波正太郎"
    ["books::id"]=>
    string(2) "10"
    ["books::created"]=>
    string(10) "1290488572"
    ["books::modified"]=>
    string(10) "1290488572"
    ["books::title"]=>
    string(15) "鬼平犯科帳"
  }
}

ポータルに配置されているフィールド「books::id」や「books::title」については、ポータル先頭レコードのフィールド内容しか格納されていることがわかる。FX.phpのデバッグ機能を使用して確認してみると

  • FX.php: http://fmcakemix_user:fmcakemix_password@localhost:80/fmi/xml/FMPXMLRESULT.xml?-db=fmcakemix_db&-lay=author_view&-max=1&id=4&-find
  • FMCakeMix: http://fmcakemix_user:fmcakemix_password@localhost:80/fmi/xml/FMPXMLRESULT.xml?-db=fmcakemix_db&-lay=author_view&-max=1&id.op=eq&id=4&-find

このように両者ともほとんど同じ条件でauthor_viewレイアウトにアクセスしていることがわかる。FMCakeMixでポータルのレコードが取得できていないのは、モデル(/model/author.php)内において、AuthorモデルとBookモデルの関連付けがおこなわれていないため。関連先レコードを取得するには、事前にbelongToまたはhasManyを使ってモデル同士の関連付けをおこなう必要がある。次回、モデルの関連付け方法とFileMaker Web公開エンジンへのリクエストの違い、パフォーマンス注意点について詳しく紹介していこう。