第 7 章 INTER-Mediator の適用範囲と評価 95
3.1 定義ファイルの例(asset_context.php)
1 require_once ('../INTER-Mediator.php') ;
2
3 IM_Entry ( array(
4 array( / /一覧領域用のコンテキスト定義(一覧ページ)
5 'name'=>'asset', / /ページファイルからの参照名
6 'key'=>'asset_id', / /キーフィールド名
7 'repeat-control'=>'insert delete', / /挿入,削除ボタンを設置
8 'records'=>5, / / 5レ コ ー ド ず つ 表 示 す る
9 'paging'=>true, / /一定数のレコードごとに表示
10 'sort'=>array( / /並べ替えのフィールドと方向
11 array('field'=>'purchase', 'direction'=>'ASC') , / / p u r c h a s eフ ィ ー ル ド を 昇 順 で 並 べ る
12 ) ,
13 'navi-control'=>'master-hide', / /このコンテキストが一覧ページのものであることを示している
14 / /この設定により,詳細ページにジャンプするボタンを配置する
15 'default-values'=>array( / /レコード作成時の初期値.今日の日付が設定される
16 array('field'=>'purchase', 'value'=> IM_TODAY) ,
17 ) ,
18 array( / /詳細領域表示用のコンテキスト定義(詳細表示)
19 'name' => 'assetdetail', / /ページファイルからの参照名
20 'view'=>'asset', / /データベース側のテーブル名(参照時)
21 'table' => 'asset', / /データベース側のテーブル名(更新時)
22 'records' => 1 , / /詳細なので,1レ コ ー ド の み
23 'key' => 'asset_id', / /キーフィールド名
24 'navi-control' => 'detail-bottom', / /詳細ページであること示す
25 ) , / /一覧に戻るボタンを下部に追加する
26 array( / / 1つ の 資 産 に つ い て の 貸 出 履 歴 の コ ン テ キ ス ト
27 'name' => 'rent', / /ページファイルからの参照名で,データベース上でもr e n tテ ー ブ ル
28 'key' => 'rent_id', / /キーフィールド名
29 'sort' => array( / /貸出日フィールドの昇順でソートする
30 array('field' => 'rentdate', 'direction' => 'ASC') ,
31 ) ,
32 'relation' => array( / /リレーションシップについての定義.外部キー,親コンテキストの対応するキー,演算子を指定
33 array('foreign-key' => 'asset_id', 'join-field'=> 'asset_id', 'operator' => '=') ,
34 ) ,
35 'repeat-control'=>'insert delete', / /追加ボタンと削除ボタンを配置する
36 'default-values'=>array( / /レコード作成時の初期値.今日の日付が設定される
37 array('field'=>'rentdate', 'value'=> IM_TODAY) ,
38 )
39 ) ,
40 array( / /担当者のポップアップの選択肢を取り出すコンテキスト.
41 'name' => 'staff', / /ページファイルからの参照名で,データベース上でもs t a f fテ ー ブ ル
資産管理アプリケーションのページファイルをリスト3.2に示す.前述の通り,2つのレイアウトをこの 1つのファイルで実現している.BODYタグ内に2つのTABLEタグ要素があり,前の方が一覧ページ用,
後の方が詳細ページ用のレイアウトである.ページファイルでの記述内容について,図中の番号と対比させ て解説する.また,リスト内の#以降の文字列はコメントである.
3.4. データベース連動ページ作成 23
図3.4:定義ファイルエディタ(主要な項目のみを表示)
リスト3.2:「資産一覧」のページファイルの例
1 <html>
2 <head>
3 !<sc ript src=1 "asset_contexts.php">< /sc rip t>
4 <scr ipt>
5 !f u n c t i o n setBackDate ( i d )8 {
6 var context = IMLibContextPool . getContextFromName ("rent") [ 0 ] ;
7 context . setDataAtLastRecord ( ' backdate ' , generateToday ( ) ) ;
8 }
9 f u n c t i o n generateToday ( ) { . . . . } #今日の日付の文字列を返す関数(内容は省略)
10 < /scr ipt>
11 < /head>
12 <body onload="INTERMediator.construct()">!3
13 <div id="IM_NAVIGATOR">< /div>!4
14 <table> #一覧ページのレイアウト領域.assetコンテキストを利用している
15 <thead><t r><th>< /th><th>分類< /th><th>名称< /th><th>メーカー< /th>
16 <th>型番< /th><th>取得日< /th><th>破棄日< /th><th>< /th>< /t r>< /thead>
17 <tbody>
18 <t r>
19 <td>< /td> #ここに自動的にディテール領域を表示するボタンが挿入される
20 !<td data2 −im="asset@category">< /td><td data−im="asset@name">< /td>
21 <td data−im="asset@manifacture">< /td><td data−im="asset@productinfo">< /td>
22 <td data−im="asset@purchase">< /td><td data−im="asset@discard">< /td>
23 <td>< /td> #ここに自動的にレコード削除ボタンが挿入される
24 < /t r>
25 < /tbody>
26 < /table>
27
28 <table> #詳細ページのレイアウト領域.最上位階層では,assetdetailコンテキストを利用する
29 <tbody>
30 <t r> <th>名称< /th><td><input type="text" data−im="assetdetail@name"/ >< /td>
31 <th>分類< /th><td><input type="text" data−im="assetdetail@category"/ >< /td>
32 <th>メモ< /th>
33 < /t r>
34 <t r> <th>メーカー< /th>
35 <td>!<input type=2 "text" data−im="assetdetail@manifacture"/ >< /td>
36 <th>型番< /th><td><input type="text" data−im="assetdetail@productinfo"/ >< /td>
37 <td rowspan="4">
38 <textarea data−im="assetdetail@memo">< /textarea><hr>
39 !<button onclick=7 "setBackDate()">本日返却< /button>
40 < /td>
41 < /t r>
42 <t r> <th>取得日< /th><td><input type="text" data−im="assetdetail@purchase"/ >< /td>
43 <th>破棄日< /th><td><input type="text" data−im="assetdetail@discard"/ >< /td>
44 < /t r>
45 <t r> <td colspan="4">
46 <table><thead><t r><th>貸出日< /th><th>返却日< /th><th>担当者< /th><th>メモ< /th>< /t r>< /thead>
47 <tbody><t r>
48 !<td data5 −im="rent@rentdate">< /td><td data−im="rent@backdate">< /td>
49 <td> !<select data6 −im="rent@staff_id">
50 <option data−im="staff@staff_id@value staff@name">< /option>
51 < /select>
52 < /td>
53 <td><input type="text" data−im="rent@memo"/ >< /td>
54 < /t r>< /tbody>
55 < /table>
56 < /td>< /t r>
57 < /tbody>
58 < /table>
59 < /body>
60 < /html>
以下,リスト3.2に記述した内容を解説するが,どういった仕組みで実現しているかについては,第5章 において詳細に解説を行う.
!ヘッダ部の1 SCRIPTタグの要素で,リスト3.1の定義ファイルを読み込む部分があり,これによりペー ジにフレームワークが組み込まれる.定義ファイルにアクセスすることで得られるのはJavaScriptのプログ ラムであるが,固定的なプログラムだけでなく,一部はサーバー側でフレームワークによって動的にプログ ラムを生成している.これらを取り込んだJavaScriptのプログラムを利用して,テンプレート処理や更新処 理を行っている.
リスト3.2の20行目にある!は一覧ページ内にあり,TD2 タグ内に「data-im="asset@category"」といった 記述が見られる.ここでは,定義ファイル側でのコンテキストを参照する名前(nameキーの値)と,データ ベース側のフィールド名を,@で区切って記述する.この指定のある要素を「リンクノード」と呼び,data-im 属性を「ターゲット指定」と呼ぶ.INTER-Mediatorがテンプレート処理をするとき,この要素に対して,
assetコンテキスト,つまりassetテーブルにあるcategoryフィールドの値を挿入する.この場合は,TDタ
グの間にTDタグ要素のテキスト子要素として,フィールドの値が追加され,その結果,フィールドの値が テーブルのセルに見えるようになる.ここではTRタグ要素が1つだけの1行分の表であるが,レコードが 複数あれば,レコードの数だけTRタグ要素を複製してレコードが一覧されて見える.
一方,リスト3.2の35行目にある!は,INPUT2 タグ内に「assetdetail@manifacture」といったターゲッ ト指定がある.assetdetailはリスト3.1の定義ファイルを見れば,表示,更新ともにassetテーブルを利用 し,manifactureフィールドの値がテキストフィールドに表示される.一覧ページはasset,詳細ページは assetdatailと異なる名前をつけるようにした.assetコンテキストのrecordsは5であり,5レコードずつ表 示される.一方,assetdatailコンテキストのrecordsキーの値は1であり,1レコードずつ表示されること を想定している.また,navi-controlキーの値はassetコンテキストは「master-hide」,assetdatailコンテキ
3.4. データベース連動ページ作成 25 ストは「detail-bottom」であり,前者が一覧ページ,後者が詳細ページとして機能するような指示がある.
master-hideの場合は初期状態では詳細ページを非表示にする.detail-bottomにより詳細ページの下部に一
覧ページに戻るボタンを付与する.navi-controlキーの値によって,マスター/ディテール形式のユーザーイ ンタフェースが実現している.
!テンプレート処理を始めるには,3 「INTERMediator.construct()」というJavaScriptの呼び出しを行う.こ のページでは,BODY要素のonload属性で記述したので,ページファイルの内容をブラウザが読み出した 直後にテンプレート処理が行われることになる.スクリプト処理として完全に分離したい場合は,SCRIPT タグ内やあるいは別途拡張子が.jsのファイルに「window.onload=function()INTERMediator.construct();」と いった記述をしてもよい.
!に4 id属性が「IM_NAVIGATOR」の要素がある.これにより,図3.2に見られるような,5レコードず つ表示しつつ,前後のページへ移動するためのユーザーインターフェース(ページネーション)が,フレー ムワークによって自動的に挿入される.ページネーションは,リスト3.1の定義ファイルでpagingキーの 値がtrueに設定されているコンテキストにのみ作用する.
図3.2では,1行ごとに「削除」ボタンがあり,画面上部には「レコード追加asset」というリンクがある.
これらは,リスト3.1の定義ファイルにあるrepeat-controlキーによって指示でき,フレームワークによっ て自動的に挿入される.assetコンテキストでは「insert delete」という値になっており,挿入ボタン,削除 ボタンのいずれも作成される.
!の部分は,TABLE5 タグ内の1つのセル内にさらにTABLEタグがあるといった構成になっている.こ のように,リピーター内にさらに別のエンクロージャーがあるような場合,内部のエンクロージャーを解 析して,この場合はrentというコンテキストを使っているということを判別する.rentコンテキストには
relationキーの値があるため,ここでは,上位のassetdatailコンテキストの現在のレコードと,下位のrent
コンテキストにあるいくつかのレコードが関連することをが定義されている.ここで,rentコンテキストの 定義に従ってrentテーブルから値を取り出すが,外部キー値を上位のコンテキストから取り出すことによ り,関連レコードを取り出すクエリーを自動的に生成する.
!の部分は,さらに6 rentコンテキストの中に,staffコンテキストを内包している.staffコンテキストは
relationがないため,特に関連レコードは関係なく,この場合はすべてのレコードを取り出して,OPTION
タグに設定することで,ポップアップメニューにはスタッフの氏名が並ぶようになっている.
「本日返却」のボタンは!の部分で記述されている.ここでは,ページヘッダ内の7 !の部分のプログラム8
を呼び出している.汎用的な機能は宣言的な記述で可能な限り対処できるように機能を用意しているが,フ レームワークに存在しない機能はどうしてもJavaScriptを利用したプログラムが必要である.ここで,貸 出履歴に対して「本日返却」ということは,貸し借りの情報の最後のレコードの返却日に今日の日付を入 力することであり,言い換えれば,ここでのrentコンテキストで得られたレコード群の最後のレコードの
backdateフィールドに今日の日付を入力すればよい.関数に記述されたプログラムは2行だけで,コンテキ
スト名からフレームワークが管理しているモデルを得て,そのモデルの最後のレコードの指定フィールド の値を更新するメソッドを利用している.