アプリケーションオブジェクトについて
http://ml.ethna.jp/pipermail/users/2005-March/000006.html より。
- 更新履歴
- トランザクションをかける場合の注意点を記載(2006/11/22, key)
- Ethna-2.3.0に対応した内容に修正 (2006/11/20, いちい)
(1) DB設定
http://ethna.jp/ethna-document-dev_guide-db.html みたいな感じでDSNを設定します
(2) AppObject
ethnaコマンドを使って簡単に作れます。あらかじめ'user'というテーブルをデータ ベースに作っておけば、
% ethna add-app-object user
とすると、app/Sample_User.phpが作られ、いっしょにapp managerも作られます。中身はほとんどありませんが、(2-1)でやるのとほぼ同様です。
(2-1) AppObject を自力で書く
こんな感じで、Ethna_AppObjectを継承したクラスを書きます。
class Sample_User extends Ethna_AppObject { /**#@+ * @access private */ /** * @var array テーブル定義 */ var $table_def = array( 'user_tbl' => array( 'primary' => true, ), ); /** * @var array プロパティ定義 */ var $prop_def = array( // user_tbl 'user_id' => array( 'primary' => true, 'key' => true, 'seq' => true, 'type' => VAR_TYPE_INT, 'form_name' => 'user_id', ), 'name' => array( 'primary' => false, 'key' => false, 'type' => VAR_TYPE_STRING, 'form_name' => 'user_name', ), ); /**#@-*/ }
$table_defメンバにはそのAppObjectと対応するDB上のテーブル名を指定しま
す。
現在はJOINにはほとんど対応していないので、記述可能なテーブルは常に
1つで、'primary'も常にtrueです。
$prop_defメンバには、フィールド定義を記述します。
今のところ、スキーマの自動取得は対応していません(有った方がいいですかねー?)。 Ethna-2.3.0では自動取得されるようになりました。
'フィールド名' => array(プロパティ...)
という形での記述になります。プロパティは:
primary | そのフィールドがプライマリキーならtrueとします |
key | そのフィールドがプライマリキー、あるいはuniqueならtrueとします |
seq | そのフィールドが(MySQL的に言うと)AUTO_INCREMENTである場合はtrueとします |
type | 今のところ基本的に使っていませんので、VAR_TYPE_INTかVAR_TYPE_STRINGを適当に指定してください |
form_name | そのフィールドに対応する値がウェブから送信される場合のフォーム名を指定します |
という感じです。form_nameはイマイチ意味が分かりにくいですが、
例えば管理画面等のアクションを書いているとして、
$user =& $this->backend->getObject('User'); $user->importForm();
とすると、form_nameに指定されたフォーム名に対応するフォーム値を自動的
にプロパティにセットしてくれます。
僕が手抜きしたいがために作ったメソッドで、要するに
$user->set('name', $this->af->get('user_name')); $user->set('pref', $this->af->get('user_pref')); ...
とか延々と書くのも頭悪いよね、ということで...。
(3) 使い方
話が前後しましたが、簡単な使い方は以下のようになります。オブジェクトは直接newしてしまっても構いませんが、Ethna_BackendクラスのgetObject()メソッドを利用すれば、オブジェクトのソースファイルを自動的にincludeしてくれます。
[通常の場合]
$user =& $this->backend->getObject('User', 'user_id', $user_id);
として、第2引数にオブジェクトを特定するためのフィールド名、第3引数にその値を指定します。
で、
$user->get('name');
とするとプロパティを取得できます。
$user->set('name', 'foo');
で、プロパティの更新です(当然)。
でもって、
$user->update();
とするとDBを更新できます。
$user->remove();
とすると削除です。
[追加する場合]
新しくDBにエントリを追加する場合は以下のようになります。
// 引数を省略してnew $user =& $this->backend->getObject('User'); $user->set('user_name', 'foo'); $r = $user->add(); if (Ethna::isError($r)) { //... } $id = $user->getId();
プライマリキーのseqフィールドがtrueならプライマリキーのプロパティは設 定しなくてOKです。
[その他]
$user->getName('user_name');
というメソッドもあります。これはプロパティ値と、表示用の値が違う場合 (「県」等)に、オーバーライドしてその表示用の値を返す形で利用します。 つまり
$user->get('user_pref');
では4とかが返ってきて
$user->getName('user_pref');
では「岩手県」が返ってくる、みたいな感じです。
さらには
$user->getNameObject();
というのもあります。これは、全てのプロパティのgetName()の結果を配列に して返します。
(4) トランザクションをかける場合の注意
AppObjectとEthna_PEAR_DBを同時に利用してトランザクションをかける場合、問題があるようなので逃げ方をここに記します。
$db = $this->backend->getDB(); $db->begin(); $db->query("INSERT〜"); $user =& new AppId_UserMst($this->backend); $user->set('username', 'key'); $user->add(); $db->commit();
などとしたい場合、begin()が走っているのでトランザクションが効くと思われるのですが、実際にやるとAutoCommitのまま処理が進んでしまいます。これでは困るので、
$db = $this->backend->getDB(); $db->db->autocommit(false); <--- これを追加 $db->begin(); $db->query("INSERT〜"); $user =& new AppId_UserMst($this->backend); $user->set('username', 'key'); $user->add(); $db->commit();
のようにして、$db->db->autocommit(false)を挟むことでトランザクション処理をすることが出来ます。たいへん気持ち悪いですが…。