symfony: doctrine build-all and table collation

by prettyscripts on 2009-11-02 12:14:38

phpsymfony

when working on symfony project it's common to run symfony doctrine:build-all (update - in V1.4 symfony doctrine:build --all) constantly. but after the command is run, the collation / encoding is changed to something that wasn’t used when the database was created.

eg, the database was created with utf8_general_ci. when the task is run, it’s changed to latin1_swedish_ci.

unlike propel task, when doctrine task is run, database is dropped and re-created. hence system default encoding is used. it seems that you can’t set default collation for database in symfony / doctrine.

i run into this problem when testing out symfony V1.2 and now it’s still happening in V1.3 beta (update - still the same in V1.4).

the problem was reported. this can be fixed by hacking the file 'path/to/symfony/lib/plugins/sfDoctrinePlugin/lib/database/sfDoctrineDatabase.class.php'. go to line 84 and replace:

PHP:

if (is_string($value)) { 
  if (defined('Doctrine::' strtoupper($stringName) . '_' strtoupper($value))) { 
    $value constant('Doctrine::'.strtoupper($stringName) . '_' strtoupper($value)); 
  } else { 
    $value strtoupper($value); 
  } 
}

add attributes to 'path/to/project/config/databases.yml':

Code:

all:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=mydbname'
      username: user
      password: password
      attributes:
        default_table_collate: utf8_general_ci
        default_table_charset: utf8

run 'symfony doctrine:build-all' again. the tables should be created with the correct encoding.

until this is fixed in the core code, you have to hack this code everytime symfony is upgraded.

without hacking the core code

another way is to add options to all tables defined in config/doctrine/schema.yml:

Code:

MyTable:
  options: { collate: utf8_unicode_ci, charset: utf8 }
  columns:
    ....

the database will be re-created to system default encoding, but the table will use the specified collation.

the cons: tables created by plugins still use system default. individual schema.yml has to be hacked, and you have to remember to do this everytime the plugin is upgraded.

update: a even better solution

imo, this is a better solution.

Tags: collation, database, doctrine, encoding, php, symfony

4 comments

Comment by Alex @ 2010-03-09 06:33:07
*****
Thank you for your comment! It helped me to save a lot of my time. And I'd like to ask you correct the structure of the databases.yml - it should be as follows:

all:
..doctrine:
....class: sfDoctrineDatabase
....param:
......dsn: 'mysql:host=localhost;dbname=mydbname'
......username: user
......password: password
......attributes:
........default_table_collate: utf8_general_ci
........default_table_charset: utf8
Comment by prettyscripts @ 2010-03-09 10:07:27
@alex, thanks for the correction. updated.
Comment by Ben @ 2010-10-05 06:16:25
After reading your three different ways to set collation on symfony database (editing core, specifying collation on each table, and editing configuration file), and actually trying all of them, I found out you can set collation by....

1. set
options:
charset: utf8
collate: utf8_unicode_ci

2. add
attributes:
default_table_charset: utf8
default_table_collate: utf8_unicode_ci
to 'all' environment in your database.yml

also make sure your default char set/collation is set correctly on your database.

It's possible my methods works because Symfony fixed it.
I'm using Symfony 1.4.6

I'm writing this because this post is one of highest ranked page on Google when I search "symfony collate."
Comment by Ron Tedwater @ 2010-11-13 16:07:20
Great work keep it coming

Leave a comment


Your email address will not be revealed on this site.
PoorExcellent
note: all comments are moderated. do not spam and do not advertise. only comments relevant to the post will be published.
(Line breaks become <br />)
(For my next comment on this site)
(Allow users to contact me through a message form -- Your email will not be revealed!)