Full Query Logging

You have probably noticed that even with Propel's logging turned all the way up (Propel::LOG_DEBUG), the logged SQL queries have placeholders in them:

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

Unfortunately this isn't a bug, but simply a result of how the layers of abstraction work in Propel. The Propel layer doesn't actually know what the finished query looks like, because the query compiling (and escaping, etc.) is handled by the lower Creole database API layer. Propel simply passes that unfinished SQL query to Creole, calls mutator methods to set the values that will replace the placeholders, and then lets Creole do the typecasting & escaping for the particular database being used.

If you want to log the actual queries that are being sent to the database, then you'll need to use a the DebugConnection class, contributed by Michael Sims, which is available in Creole CVS (located at creole/contrib/DebugConnection.php).

For the sake of simplicity here, I'll assume that you want to log full SQL queries for the runtime environment (and don't care so much about the build environment).

Specifying a Custom Creole Driver

You can specify custom Creole drivers in the runtime-conf.xml file; however, because we want to specify a "decorator"-style driver, we'll need to do this outside of Propel's configuration. The "decorator" drivers are simply drivers that are registered to handle all Creole connections, regardless of which database you are using; these drivers then instantiate the real drivers and wrap all calls to the real drivers with additional functionality (in our case the functionality we want is logging).

The reason you cannot specify a decorator-style driver in the runtime-conf.xml file is that Propel will register that driver as the official driver for whatever your database is (e.g. 'pgsql'). When the decorator driver (in our case DebugConnection) loads it will attempt to instnatiate the real driver for your database (e.g. 'pgsql') but will find that it has been registered as the driver to handle that type. .... and then shortly after PHP will segfault.

So, before you initialize Propel, you want to register the DebugConnection as a catch-all/decorator driver with Creole:

<?php

require_once 'creole/Creole.php';

// register debug connection decorator driver
Creole::registerDriver('*', 'creole.contrib.DebugConnection');


Setup Logging

Now, after building the PHP runtime configuration file, you can edit your initialization script (wherever you initialize Propel) and setup a PEAR Log class to be used both for Propel logging and for the logger of the DebugConnection class.

<?php

require_once 'creole/Creole.php';

// register debug connection decorator driver
Creole::registerDriver('*', 'creole.contrib.DebugConnection');


// initialize Propel with converted config file
Propel::init('/path/to/runtime-conf.php');

// create/retrieve a PEAR Log instance
$logger = Log::singleton('file', 'log.txt', 'db-log');

// use that logger for Propel logs
Propel::setLogger($logger);

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

Now all Propel logs and SQL queries from DebugConnection logs will be logged to the specified text file (log.txt).

Creating Your Own Drivers

If you take a look at the DebugConnection class, you will notice that this is an extremely simple piece of code. Creole was designed specifically for this type of layering to be possible. It's easy to create and specify your own database driver classes so long as the classes implement the appropriate Creole interfaces. The main class for a driver is always the Connection class; in the case of the DebugConnection it is also the only class that we need to override.