Using Long Varchar Columns with Doctrine

Using Long Varchar Columns with Doctrine

MySQL has supported large varchar columns since 5.0.3, about four years ago (previously, you could only have varchar columns of up to 255 characters in length). So, for quite a while now, you've been able to use them with lengths up to 65,536 characters - depending on a few variables like your maximum row length and character set.

Unfortunately, that doesn't seem to be the case if you're using Doctrine. By default, if you use a string column with a length larger that 255 characters, Doctrine will silently use a text column, not a varchar. That has a bunch of follow-on effects, that you might not notice at first. For example, MySQL will only use the first 1024 characters of your column for sorting. I could see this leading to some pretty hard to find bugs.

Investigating where the 255 character limit comes from, it does seem to be a property of the Doctrine Connection. That's good: it's the right place for the restriction to be recorded. But, even though Doctrine_Connection extends Doctrine_Configurable, the varchar_max_length property of the connection doesn't seem to be configurable. In any way. At all.

Let me make it clear. They could have implemented varchar_max_length as an attribute, or as a parameter, in which case Doctrine_Configurable would have let you change its value. But they didn't. Or they could have implemented it as an option, in which case Doctrine_Connection would have let you change its value. But they didn't. They implemented it as a property, which you can't change without subclassing the connection object. Yuck.

OK, I thought. Not too bad. I'll just subclass the connection and use that. Oh, wait. All the connection drivers are hard coded in Doctrine_Manager:

        $drivers = array('mysql'    => 'Doctrine_Connection_Mysql',
                         'sqlite'   => 'Doctrine_Connection_Sqlite',
                         'pgsql'    => 'Doctrine_Connection_Pgsql',
                         'oci'      => 'Doctrine_Connection_Oracle',
                         'oci8'     => 'Doctrine_Connection_Oracle',
                         'oracle'   => 'Doctrine_Connection_Oracle',
                         'mssql'    => 'Doctrine_Connection_Mssql',
                         'dblib'    => 'Doctrine_Connection_Mssql',
                         'odbc'     => 'Doctrine_Connection_Mssql', 
                         'firebird' => 'Doctrine_Connection_Firebird',
                         'informix' => 'Doctrine_Connection_Informix',
                         'mock'     => 'Doctrine_Connection_Mock');

        if ( ! isset($drivers[$driverName])) {
            throw new Doctrine_Manager_Exception('Unknown driver ' . $driverName);

WTF? Who thought that was a great idea?