17 Nov 2010

Doctrine - Versionable behavior configuration for use in symfony

If you use doctrine's Versionable behavior you might notice some performance issues, especially if you use a large number of models. The behavior generates a second model for each model. This second model represents the history log. It happens on demand and in memory for each request. The lazy generation can be turned off by option generateFiles: true. The generated model is then written to the location specified by generatePath.

Everything is fine except you're using symfony. The generated models are not extended from sfDoctrineRecord and written to another directory because of the default configuration of Doctrine_Import_Builder inside of Doctrine_AuditLog. It took me a while to figure out how to configure doctrine's Versionable behavior for symfony's directory structure.

Here is the result:  

19 Jun 2010

RecordColumnNameDecorator - A Doctrine Compatibility Decorator

I mentioned that we’re migrate our application from pure SQL to an ORM-Layer. Many of the existing functions work with column names of the database tables. Sometimes these column names are used hard coded or directly linked to the view layer. The actual problem is that we used the opportunity of the migration to unify the denotation of our tables and column names via the doctrine alias functionality. At the end we had functions using the old syntax and models with a new stylish unified nomenclature.

Fortunately it’s all OOP :)

The functions need a way to get the data from a given “Array”, but with the real column names instead of the new field names. The Doctrine_Record implements the ArrayAccess-Interface, which solves the problem that Doctrine_Record object should behave like an Array. The compatibility issue is solved through a small decorator which is currently not more as a proof of concept. The decorator change the functionality of the implemented ArrayAccess-Interface so that will accept real column names.

/**
 * A Doctrine_Record uses field names instead of columns names
 *
 * The RecordColumnNameDecorator change the functionality how
 * you call data from a Doctrine_Record. You can use the original
 * column names instead of the field alias.
 *
 * @author     Enrico Stahn <stahn@rib.de>
 * @version    SVN: $Id$
 */
class RecordColumnNameDecorator extends Doctrine_Record
{
  protected $record;

  public function __construct(Doctrine_Record $record)
  {
    $this->record = $record;
  }

  public function offsetGet($key)
  {
    return $this->record[$this->record->getTable()->getFieldName($key)];
  }

  // ... Implement the rest of the interface
}

Example:

// old: ugly_tablename.ugly_column_name
// new: foo.bar
$a = new Foo();
$b = new RecordColumnNameDecorator($a);
echo $a->bar;
echo $b->ugly_column_name

easy-peasy :)