2009年10月31日土曜日

Zend_Db_Adapter_Abstractを継承した拡張自作Adapter

どうも、俺@遊び帰宅です。
眠いっす。

Zend Frameworkを使ってWebアプリケーションを作ってて
「あー、DBへのクエリのログ取りたいなー」ってよくあると思います。
特にトランザクションの発生するクエリに関しては、Webプログラマとしては必需品だと思います。

方法はすべてのXXController内でクエリを発行する度に
<?php
// Zend_Db_Adapter_Abstractでクエリ発行
$adapter->query("INSERT INTO foo_table (column) VALUES ('value')");

// Zend_Db_Profiler
$profiler = $adapter->getProfiler();
$queries = $profiler->getQueryProfiles(Zend_Db_Profiler::INSERT);
if (is_array($queries)) {
foreach ($queries as $query) {
file_put_contents($filename, $query->getQuery());
}
}
と、簡単なサンプルを書くとこんな感じでしょうか。

ただ、これだとクエリを発行する度にZend_Db_Profilerを生成し、ログを取得しなければなりません。
面倒くさいです。

そんな面倒くさがりな貴方にはZend_Db_Adapter_Abstractを継承した自作クラスを作成することをオススメします。
例えばPostgreSQLを使っている場合は
<?php
/**
* Zend_Db_Adapter_Pdo_Pgsqlを継承した自作アダプター
*/
class MyPdoPgsql extends Zend_Db_Adapter_Pdo_Pgsql {
/**
* @Override
*/
public function insert($table, array $bind) {
// 略 Zend_Db_Adapter_Pdo_Pgsql::insert()と同じ処理

// Zend_Db_Profilerでログる
$profiler = $adapter->getProfiler();
$queries = $profiler->getQueryProfiles(Zend_Db_Profiler::INSERT);
if (is_array($queries)) {
foreach ($queries as $query) {
file_put_contents($filename, $query->getQuery());
}
}
}


/**
* @Override
*/
public function update($table, array $bind, $where) {
// 略 Zend_Db_Adapter_Pdo_Pgsql::update()と同じ処理

// Zend_Db_Profilerでログる
$profiler = $adapter->getProfiler();
$queries = $profiler->getQueryProfiles(Zend_Db_Profiler::UPDATE);
if (is_array($queries)) {
foreach ($queries as $query) {
file_put_contents($filename, $query->getQuery());
}
}
}

public function delete($table, $where = '') {
// 以下同じ
}
}
このようにinsert/update/deleteメソッドにログ処理を書いてZend_Db_Adapterの子クラスを作成します。

あとはindex.php内の処理でZend_Db_Adapter_Abstractを生成するときに
<?php
$db = new MyPdoPgsql($options);
Zend_Db_Table_Abstract::setDefaultAdapter($db);
のようにデフォルトアダプターをセットしておけば、全てOK!!

基本的にZend FrameworkのクエリはZend_Db_Adapter_Abstractを経由して発行されるので、あとは自動でログを取ってくれます。
他にもトランザクションや例外処理も全てこの中に書けば、面倒なことを書かずに済みますね。


以上、面倒くさがり屋さんへ。

2009年10月22日木曜日

phpで三項演算子の注意点

どうも、俺@始業です。
別に暇なわけじゃないですよ。

今日はphpで三項演算子を利用した際の注意点をメモります。
三項演算子は例えば
<?php
$a = 1;
// 三項演算子
echo $a == 1 ? "$aは1です。" : "$aは1ではありません。";
と書くと、出力は
$aは1です。
となります。
書き方は
(式) ? 真の場合 : 偽の場合
です。
三項演算子は短く条件分岐を書くことができるので、phpでプログラムを書いた際のView側などで利用できます。

で、
三項演算子を入れ子(ネスト)にした場合、php三項演算子ならではの注意点があります。
<?php
$a = 1;
// 三項演算子
echo $a == 1 ? "$aは1です。" : $a == 2 ? "$aは2です。" : "$aは1でも2でもありません。";
とすると、プログラマーは
$aは1です。
と出力されると予想します。
ところがドッコイこの結果は
$aは2です。
と出力されてしまいます。危ないですねー。
理由はPHPマニュアル@三項演算子にあるように、phpの三項演算子は左から右へ評価の順が移っていくので、上の例でいくと
1)$a == 1 が評価されtrue
2)"$aは1です。"をechoしようとする
3)(1)で評価されたtrueが次の $a == 2で評価されtrue
4)"$aは2です。"をechoする。
という流れになるみたいです。たぶん、、。

要は(3)で$a == 2 が評価されるときに(1)で評価された結果(true)を持ち越してしまうみたいです。

というわけで、どうしても三項演算子を利用して入れ子をしたい場合は
<?php
echo $a == 1 ? "$aは1です。" : ($a == 2 ? "$aは2です。" : "$aは1でも2でもありません。");
と書きましょう。


以上ーー。

2009年10月7日水曜日

PostgreSQLでコマンドラインから直接クエリ実行

おはようございます、俺@朝礼後です。

今日はPostgreSQLでコマンドラインで直接クエリを実行する方法をメモります。
説明が難しいのですが、「コマンドラインから直接」というのは
$ psql foo_database
psql> SELECT * FROM bar;
というのではなく、
postgresqlサーバへログインせずにクエリ発行、結果取得という意味です。
(※内部的にはpostgresqlログインしてるのかもやけど、、、)


やり方は、
$ psql -c 'SELECT * FROM bar' foo_database
です。
ちなみに
$ psql -c 'SELECT * FROM bar' -o output_file foo_database
とやると、
output_fileへクエリ結果を出力します。

ついでにMySQLでは
$ mysql -e 'SELECT * FROM bar' foo_database
で直接クエリを実行できます。



以上どぇぇぇぇぇす。