Mysql+Prado+(XML)+OpenLaszlo で表示

OpenLaszloの日本語チュートリアルチャプター11でXMLからのデータバインドをやると、じゃDBとはどうやって?となるのでしょうが、この辺は通常のFLashやAjaxと考え方は一緒なのでしょう・・・。でもそんなこと意識しなくてよいPRADOフレームワークではどうやるんだ?XML生成部分だけ外出しのコンテンツじゃ台無しやし・・・。OpenLaszloのコンテンツは、非常に洗練されていて全部これで作りたい衝動にかられるのですが、フレームワーク的ではないから、ユーザー認証なども考えると、そこは何かフレームワークっぽいものと連動させたページにすべきなのかなぁと思ってしまうのです。(まだチャプター10付近のユーザーの感想ですが)
そんなことから、ちょっと不安になったDB連動部分を Mysql+PradoでXML生成して、OpenLaszloに表示させるサンプルを作成してみました。

備忘録

DB設定

DB作成とTable作成
$ mysql -uroot -p
>create database test;
>grant all on test.* to flabo@localhost;
>quit
$ mysql -uflabo -p
>use test;
>create table users (username varchar(20) primary key,email varchar(50),password varchar(20));
>insert users (username,email,password) values ('felix','juhnfelixkusano@gmail.com','felix');
>insert users ・・・ 適当にあといくつか

PRADO設定

DB連動のための設定。

ファイルは以下の感じになります。(Pradoのインストール・初期設定は ここなどから)
Screenshot-1.png

application.xml の中身

ページ全体の設定ファイル。ちょっと不要なものもありますが・・・こんな感じ
<?xml version="1.0" encoding="utf-8"?>

<application id="myprado" mode="Debug">
 <paths>
   <using namespace="Application.common.*" />
	<using namespace="System.Data.*" />
   <using namespace="System.Web.UI.ActiveControls.*" />
 </paths>

 <!-- configurations for modules -->
 <modules>
 	<module class="System.Data.TDataSourceConfig" id="db1">
			<database ConnectionString="mysql:host=localhost;dbname=test"
				username="flabo" password="flabo" />
		</module>

 	<module class="System.Data.ActiveRecord.TActiveRecordConfig"
      ConnectionID="db1" EnableCache="true"  />
 </modules>

 <!-- configuration for available services -->
 <services>
   <service id="page" class="TPageService" DefaultPage="Home" />
 </services>
</application>

UserRecord.php の中身

ActiveRecordでusersテーブルをオブジェクト化します。common以下の UserRecord.php を以下の様に編集します。
<?php
class UserRecord extends TActiveRecord
{
   const TABLE='users'; //table name

   public $username; //the column named "username" in the "users" table
   public $email;
   public $password;

   /**
    * @return TActiveRecord active record finder instance
    */
   public static function finder($className=__CLASS__)
   {
       return parent::finder($className);
   }
}

?>

ActiveRecordからXML表示まで

PRADOでXMLファイルを出力するには、テンプレートの下準備が必要でした。まず、pages/loadXml 以下に layout.tpl を作り以下の様に一行だけ書きます。
<com:TContentPlaceHolder ID="content"/>
ポイントは、ファイルの冒頭から改行せずに書き出すことです。(XMLファイルに改行が反映されてしまうからです)次に、同じく layout.phpを設置します。この中身は、意味がありませんが、無いとエラーになります。
<?php
class layout extends TTemplateControl
{
}
?>
この layout.tpl と layout.php のテンプレートクラスは、フォルダー下のページに共通で適用されるものです。絶対に必要なものではないのですが、デフォルトのテンプレートは、<head>タグを持っているため、その下にxmlノードを書いてもxmlファイルとして認識してくれません。そのため、わざわざ空に近いテンプレートクラスを設定する訳です。このテンプレートをloadXml下のファイルに影響を与える config ファイルで設定します。 config.xml を以下の内容にします。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <pages MasterClass="Application.pages.loadXml.Layout" />
</configuration>
これで下準備が完了です。なお、このloadXmlディレクトリよりも上位に config.xml があると、そちらの設定も適用してしまうので、注意が必要です。
いよいよXmlファイル生成の主要部分です。クラスは TXMLDocumentSample です。同名の .page と .php ファイルを作っていきます。まずは TXMLDocument.page の方です。
<com:TContent ID="content"><%% header('Content-Type: application/xml; charset=utf-8'); %><%=
$this->Page->query %></com:TContent>
長いので改行していますが、このファイルの改行もXML表示に反映されるのでNGです。続いて TXMLDocumentSample.php の方ですが 以下の様な感じです。
<?php
class TXMLDocumentSample extends TPage{

	public $query;

	public function onLoad($param)
	{
		$doc=new TXmlDocument('1.0','utf-8');
		$doc->TagName='Root';

		$finder=UserRecord::finder();
		$users=$finder->findAll();

		foreach($users as $u){
			$proc=new TXmlElement('user');
			$doc->Elements[]=$proc;
				$query=new TXmlElement('username');
				$query->Value=$u->username;
				$proc->Elements[]=$query;

				$query=new TXmlElement('email');
				$query->Value=$u->email;
				$proc->Elements[]=$query;

				$query=new TXmlElement('password');
				$query->Value=$u->password;
				$query->setAttribute('pass_length',strlen($u->password));
				$proc->Elements[]=$query;
		}

		$this->setquery($doc);
	}

	public function getquery(){
		return $this->query;
	}

	public function setquery($value){
		$this->query=$value;
	}
}
?>
ActiveRecordのオブジェクトから自動的なXMLファイル生成があってもよさそうですが、ちょっと見つけられませんでした。XMLDocument XMLElement の あたりは、 APIマニュアルそのまんまですが、Element と Attribute の違いが分かっていれば難しくありません。結果として、 (root)/?page=loadXml.TXMLDocumentSample は、以下の様なXMLが返ってきます。
<Root>
−<user>
   <username>felix</username>
   <email>juhnfelixkusano@gmail.com</email>
   <password pass_length="5">felix</password>
 </user>
−<user>
   <username>felix2</username>
   <email>juhnfelixkusano@gmail.com</email>
   <password pass_length="6">felix2</password>
 </user>
</Root>

OpenLaszlo上へ反映

結構PRADOで手間取ったので、もう十分な感じがしてしまったのですが、もう一度気を取り直して・・・
OpenLaszlo のサンプル用のアプリのルート lps-4.1.1/my-apps/ に Ch11-3.lzx といった感じのファイルを作成して・・・
<canvas debug="true">
	<dataset name="myData" request="true"
		src="http://localhost/felix-labo/myprado/?page=loadXml.TXMLDocumentSample" />
	<simplelayout axis="y" spacing="10" />
	<view name="myTable">
		<simplelayout axis="y" />
		<view name="rowOfdata" datapath="myData:/Root/user">
			<simplelayout axis="x" />
			<text datapath="username/text()" />
			<text datapath="email/text()" />
			<text datapath="password/text()" />
			<text datapath="password/@pass_length" />
		</view>
	</view>
	<button text="更新" onclick="this.parent.myData.doRequest()" />
</canvas>

いい感じに表示されています・・・^^。最後の button は、データ更新用のメソッド doRequest() を実行させます。試しに DBのテーブルを変更して、更新ボタンを押してみるとちゃんと反映します。

XML介すことで・・・

仲介するXMLは公開になってしまうので、上記の様にパスワードをDBからXMLで表示する様なことはできなくなります。処理はPRADO側で行い。例えばログイン状態なのか否かのフラグだけを返す様な処理になるのでしょう・・・。結構面倒くさい。それに値をXMLを介してDBへGET・POSTで渡す時も、意図しない画面から渡されたりすることが出てくる場合に気をつけなくてはならない時があるのでしょう(たぶん)