モンスターカレンダー

« 2010年1月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

DB_DataObjectの最近のブログ記事

ふと試してみるとCreateTablesでViewのスキーマも生成できるようになっていた。(DB_DataObject1.7.13)

(設定ファイル)
build_views = 1

しかし、今まで動いていたところがエラーになった。「$obj->key($id)が必要だ」とかなんとか。
調べてみると、手でスキーマを書いていたときに定義していたキーの部分が消えてしまっていた。
→Autoで作成されるところ以外にキー定義を改めて書いた。

(Target_view.php)
function keys() {
return array('item_no');
}

※DataObject/targetdb.iniの[target_view__keys]にも定義できるが、iniファイルはCreateTablesで自動生成され、手書き部分は消えてしまう(と思う)ので使用しない。

重い腰をあげて、PHP4.3.8 → PHP4.3.10 へバージョンアップ。
...アプリが、動きません。
どーーーもDB_DataObjectでエラーが出ている。
DBのバージョンが勝手にあがっていたため、前のものに合わせてみるが効果なし。
CreateTableするとイケる??とやってもるも、こいつもエラーで動かない。
????

グーグル先生に聞いてみたら
「PHP4.3.10ではDB_DataObjectのCreateTableは動かない」
「PHP4.3.10ではDB_DataObjectがどうも変」
というブログ発見。。。。

とりあえずアプリ動かないことには仕事にならんので、PHPバージョンダウンしないと。
セキュリティも気になるけど、動かんことには!

...いきなり業務本番サーバでやらないで、まずローカル環境で試してみてよかった、としよう。

===その後===
DB_DataObject 1.7.13 ==> OK!でした。

DB_DataObjectのトランザクション処理。(以下サンプルコード。typoあるかも)


$tbl = DB_DataObject::factory("target_table");
$db = $tbl->getDatabaseConnection(); //これでDBオブジェクトがとれる
$db->autoCommit(False);
$db->query("BEGIN"); //トランザクション開始
$db->query("LOCK TABLE target_table IN SHARE ROW EXCLUSIVE MODE");
//必要に応じてロックレベルを設定。これはPostgreSQLのもの

//$tblにいろいろ値をセットする処理
// :
$cnt = $tbl->update();
if (PEAR::isError($tbl->_lastError) { //エラー判定
$db->query("ROLLBACK"); //ロールバック
return False;
}
if (cnt <= 0) {
$db->query("ROLLBACK");
return False;
}

$db->query("COMMIT"); //正常ならコミット
return True;

要は DBオブジェクトを取得してしまい、後はqueryメソッドで制御するという方法。

複数のテーブルを同じトランザクションでも制御できるんですが、
最初のDataObjectのオブジェクトを作ってからでないとDBオブジェクトがとれな
いのでスマートな作りとはいえません。。が、仕方なくやってます。

#自力でsetDatabaseConnection()を作る方法もあると助言もらいながらも
#時間の都合でまだ果たせず。。

PHP-Usersに投稿したのを機会にこちらにもUPです。

DB_DataObjectをアップグレードしたら、CreateTable.phpがエラーになってしまい、テーブル定義の自動生成ができない。
1.5.3 より上の、1.6, 1.7ともだめだった。
Webでの検索にもエラーはひっかかってこない。

しばらく放置しておいたが、いつまでも古いままというのも情ない。じっくり調べてみた。

エラー:
db_dataobject_generator : 0 : CREATING FOR test

[db_error: message="DB Error: insufficient data supplied" code=-20 mode=return level=notice prefix="" info="SELECT c.relname as "Name"
FROM pg_class c, pg_user u
WHERE c.relowner = u.usesysid AND c.relkind = 'r'
AND not exists (select 1 from pg_views where viewname = c.relname)
AND c.relname !~ '^pg_'
UNION
SELECT c.relname as "Name"
FROM pg_class c
WHERE c.relkind = 'r'
AND not exists (select 1 from pg_views where viewname = c.relname)
AND not exists (select 1 from pg_user where usesysid = c.relowner)
AND c.relname !~ '^pg_' [nativecode=ERROR: relation "sql_features" does not exist]"]

その辺りのソースを見てみたり、iniファイルに何か設定すべきものが増えているのか?と最新のexample.iniを見てみたり(実際増えていたが、この現象とは関係ないものだった)。

ふと、「DB」パッケージをアップグレードしてみたらどうだろうか。。との考えが浮かんだ。
1.6.4(だと思う。。。もしかしたら1.6.2だったかも)→1.6.5へ。

で、実行してみたら、あっさり通ってしまいました。
そんなことだったのかぁぁぁぁ。

現在は DB_DataObject : 1.7.2 となりました。

=======================================

おまけ。iniファイルに、viewの定義も生成してくれる build_views という項目が増えていたので、1を設定してやってみた。
。。。が、エラーとなった。

エラー:

db_dataobject_generator : 0 : CREATING FOR test

[db_error: message="DB Error: insufficient data supplied" code=-20 mode=return level=notice prefix="" info="SELECT viewname FROM pg_views [nativecode=ERROR: relation "table_constraints" does not exist]"]

これも、そのうち。。。。

DB_DataObject.phpを見てみました。


function factory($table) {

//略
if (!$class) {
return DB_DataObject::raiseError(
"factory could not find class $class from $table",
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
}
}

で、「DB_DataObject」のraiseErrorを呼び出していました。


function raiseError($message, $type = null, $behaviour = null)
{
global $_DB_DATAOBJECT;

if ($behaviour == PEAR_ERROR_DIE && @$_DB_DATAOBJECT['CONFIG']['dont_die']) {
$behaviour = null;
}

if (PEAR::isError($message)) {
$error = $message;
} else {
$error = PEAR::raiseError($message, $type, $behaviour);
}
// this will never work totally with PHP's object model.
// as this is passed on static calls (like staticGet in our case)

if (@is_object($this) && is_subclass_of($this,'db_dataobject')) {
$this->_lastError = $error;
}

$_DB_DATAOBJECT[
'LASTERROR'] = $error;

// no checks for production here?.......
DB_DataObject::debug($message,"ERROR",1);
return $error;
}

エラーの場合は、lastErrorにセットすると同時にたしかに PEAR::raiseError でreturnはちゃんとPEAR::Errorになってますね。
factoryはreturnで拾えるということですね。

しかし、他のメソッドは
...なんでもいいんですが、エラー時にはDB_DataObject::raiseErrorしてもそれはreturnしていないです。
return値はTrue/False。
内容を見るにはやはり _lastErrorを取得する必要がありますね。。

#なんでfactoryと同じようにPEAR::Errorを返してくれないんだろう。
#そして_lastErrorを取得するメソッドがないのは。。。?? _lastError使っていいんですね??

*** version : 1.5.3 ***

PEARのERRORの拾い方

| コメント(0)

PEARは本当に便利でいくつか使っているが、エラーの拾い方がよく分からなかった。

DBに関しては雑誌にもネットにもあって

$db = DB::connect($dsn);
if (PEAR::isError($this->db)) {
 $reason = $db->getMessage();
 return;
}

と、$dbオブジェクト自体をisErrorしていた。

DB_DataObjectなども同じかと思いそのように書いていたら実は違っていた。

$user = DB_DataObject::factory("m_user");
if (PEAR::isError($user->_lastError)) {
 $reason = $user->_lastError->getMessage();
 return;
}

と、$user->_lastError がPEARのエラーオブジェクトだった。。。

print_r($user);

としてみて、初めて知った事実(--;;

PEARは資料が少くて。。。。やってみて初めて分かる、またはソースをみて初めて分かるってことが多い。それでも徐々に情報は出てきているのだけど。

ちょっと気になるのが 「_(アンダースコア)」付きのメソッド(プロパティ)ってプライベートなのか。。外から呼んじゃいけないのか。。。。でも他に呼ぶ手立てが、ない。はず。

DB_DataObject insert 完結編

| コメント(0)

DB_DataObject insert の続きに挑戦。
やっと、できた。。。

まず、setFrom()は使えない。

$sale->setFrom($array);
$sale->insert();

としても、setFrom() 内でkeyは SQLの SETから除外されてしまう。

なので地道に

foreach($array $k=>$v){
 $sale->$k = $v;
}
$sale->insert();

とした。
テーブルのキーにシーケンスがない場合はこれでOK。

次に。。。
テーブルのキーにシーケンスがある場合

自分のスクリプトの書き方も悪かった&マニュアル読み込み不足で当初うまくいかず。。
結局DataObject.phpを追ってみて、ようやく次のシーケンスキーがとれず、無条件に1がセットされていると判明。
とれなかったのは、iniファイルにシーケンスキーの定義がなかったからだった。

sequence_m_sale : sale_no:sale_no_sql

などと書く。
これでinsert()はばっちり〜〜〜

と浮かれていたら、今度はupdate()で問題が。

いや大したことないといえばたいしたことはない。。か??
Keyの変更はできないってことです。

今日はDB_DataObject

| コメント(0)

DB_DataObjectについて。

update(),setFrom()を使う。

//フィールド名と値の配列を予め定義。(本当はFormから取得した値)
//フィールドは一部でもよい
$array=array("id"=>1, "name"=>"New Sale");

$sale = new DataObject_sale;
$sale->get(1);
$sale->setFrom($array);
$sale->update();

これでOK。

Insertもこれでいけるかとやってみた。

$sale->setFrom($array);
$ret = $sale->Insert();

...$ret = False でした。

配列を渡すことはできないのかーーーー。
うーん。
いちいち

$sale->id=2;
$sale->name="New Sale";

などと書かないとだめなのか。。

#DataObject_saleのラッパークラス作ってるので
#update($array),insert($array)と作りたかった。

if(strlen($_POST["name"])>0){
 $sale->name = "New Sale";
}
って、全部書く?

....そうするくらいなら$_POST配列から自分でSQL作った方が速い?

もう少し悩もう。

====================================
追記。

>if(strlen($_POST["name"])>0){
> $sale->name = "New Sale";
>}

こんなことしなくても $sale->$field_name って、書けるんですね。。

DataObject.php の中をのぞいてみました。
keyが、渡した値でなく 1 に無条件になっている。
どこかで。insertのはじめの方が怪しそう。

もうちょっと追ってみます。