フルクエリロギング

おそらくお気づきになられているでしょうが、Propelのロギングによってすべてが改善されていて(Propel::LOG_DEBUG)、ログされたSQLクエリはそれらの中にプレースホルダを持ちます:

SELECT table.COL1, table.COL2 FROM table WHERE table.COL1 = ?

不幸にも、これはバグではありませんが、Propelにおける抽象レイヤの動作方法のシンプルな結果です。Propelレイヤは終わったクエリが何であるのかを実際には知りません。クエリコンパイリング(とエスケーピング、など)は下層のデータベースAPIレイヤ(Creole)によって取り扱われるからです。Propelはシンプルに終わったSQLクエリをCreoleに渡し、プレースホルダに置き換える値を設定するミューテータメソッドを呼び出し利用している特定のデータベースのためにCreoleにタイプキャスティングとエスケーピングをさせます。

データベースに送られる実際のクエリを記録したい場合、DebugConnectionクラスを使う必要があります。このクラスはMichael Simsが寄付したもので、Creole CVSで利用可能です(creole/contrib/DebugConnection.phpにあります)。

簡潔にするために、実行環境であなたがフルSQLクエリを記録したいことを前提とします(ビルド環境についてはあまり気にかけないことにします)

カスタムCreoleドライバを指定する

カスタムCreoleドライバをruntime-conf.xmlファイルで指定することが出来ます; しかしながら、"decorator"スタイルのドライバを指定したいので、Propelコンフィギュレーションの外部でこれをする必要があります。"decorator"ドライバはどんなデータベースを使っているのであれ、すべてのCreole接続を取り扱うために登録されるシンプルなドライバです; これらのドライバは本当のドライバはインスタンス化して追加機能を持つ本当のドライバへのすべてのコールをラップします(この場合欲しい機能はロギングです)。

runtime-conf.xmlファイルでdecoratorスタイルのドライバを指定できない理由はあなたのドライバが何であれ(例えば'pgsql')Propelが公式のドライバとしてそのドライバを登録するからです。decoratorドライバ(我々の場合はDebugConnection)が読み込まれるときにデータベース(例えば'pgsql')のために本当のドライバをインスタンス化しようとしますがそのタイプを取り扱うためにドライバとして登録されていることを発見し、...直後にPHPがセグメンテーション違反(segmentation faultもしくはsegfault)をします

ですので、Propelをインスタンス化する前に、Creoleでcatch-all/decoratorドライバとしてDebugConnectionを登録をする場合は次の通りです:

<?php

require_once 'creole/Creole.php';

// デバッグ接続decoratorドライバを登録する
Creole::registerDriver('*', 'creole.contrib.DebugConnection');


ロギングをセットアップする

PHPランタイムコンフィギュレーションファイルをビルドした後で、初期化スクリプト(Propelを初期化する場所)を編集してPropelのロギングとDebugConnectionクラスのロガーの両方に使用されるPEAR Logクラスをセットアップすることが出来ます。

<?php

require_once 'creole/Creole.php';

// デバッグ接続デコレータドライバを登録する
Creole::registerDriver('*', 'creole.contrib.DebugConnection');


// 変換されたコンフィグファイルでPropelを初期化する
Propel::init('/path/to/runtime-conf.php');

// PEAR Logインスタンスを作成/取得する
$logger = Log::singleton('file', 'log.txt', 'db-log');

// Propelのログのためにロガーを使う
Propel::setLogger($logger);

$con = Propel::getConnection(); // assume we're using default connection
if ($con instanceof DebugConnection) {
  $con->setLogger($logger);
}

これでDebugConnectionログからのすべてのPropelログとSQLクエリは指定されたテキストファイル(log.txt)に記録されます。

独自のドライバを作成する

DebugConnectionクラスを見ると、これが極端にシンプル化されたコードのピースであることに気付きます。Creoleは可能なレイヤリングのこのタイプのためにとりわけ設計されました。クラスが適切なCreoleインターフェイスを実装する限り独自のデータベースドライバクラスを作成して指定することは簡単です。ドライバのためのメインクラスは常にConnectionクラスです; DebugConnectionの場合オーバーライドする必要がある唯一のクラスでもあります。