Chad 2010-05-07
Recently I've been working on a project which is using Symfony 1.4 and has the following features:
1. multiple database connectinos;
2. using sfDoctrineGuardPlugin.
Here's what the database configuration looks like:
- // config/databases.yml
- all:
- my_db:
- class: sfDoctrineDatabase
- param:
- dsn: mysql:host=localhost;dbname=my_db
- username: root
- db_to_read:
- class: sfDoctrineDatabase
- param:
- dsn: mysql:host=localhost;dbname=db_to_read
- username: root
And the shema:
- // config/doctrine/schema.yml
- People:
- actAs:
- Timestampable: ~
- columns:
- name: { type: string(255), notnull: true }
But something undesired happened when I run this command:
I want the `People` table to be added into `my_db`, but it's added into `db_to_read`. Aparently, that command was using the "db_to_read" connection, instead of "my_db".
It's OK if I change the order of the connections in database.yml, but I wonder if there is a configuration option to set "default database connection" or not.
To set a defalut database in Symfony
After searching for a while, I found that there're already some posts about this topic[1] [2].
It is said that although we don't have a default database connection configuration opton, there are two alternative solutions to this:
A. Because the last connection would be used by default for those tables which does not specify a database connection explicitly in doctrine schema files, we can change the sequence of the database connections in the databases.yml to have our "default" database.
B. Explicitly set the connection property on all schema definitions, including those from plugins (we can take advantage of the cascading configuration feature of Symfony, by simply define each tables' connection property from each plugins).
- // config/doctrine/schema.yml
- # #
- # some configurations
- # ...
- # #
- sfGuardGroup:
- connection: my_db
- sfGuardPermission:
- connection: my_db
- sfGuardGroupPermission:
- connection: my_db
- sfGuardUser:
- connection: my_db
- sfGuardUserPermission:
- connection: my_db
- sfGuardUserGroup:
- connection: my_db
- sfGuardRememberKey:
- connection: my_db
I'd like to use solution B since it looks clearer. Everything went fine until I created a fixture file for the `sf_guard_user` table:
- // data/fixtures/fixtures.yml
- sfGuardUser:
- sgu_admin:
- username: admin
- password: admin
- is_super_admin: true
The doctrine:data-load task will try to delete and insert the data defined above to the "db_to_read" connection, which is defined as the last connection. But the fixture data for the `people` table is OK. That's weird!
Since I don't have a better solution for this "default database connection" issue now, I have no choice but to define the one at the end in databases.yml, which I want the sfDoctrineGuardPlugin to use.
Work with readonly databases in Symfony
After the changes caused by the reasons illustrated above, I now have the following database connection configuration:
- // config/databases.yml
- all:
- db_to_read:
- class: sfDoctrineDatabase
- param:
- dsn: mysql:host=localhost;dbname=db_to_read
- username: root
- my_db:
- class: sfDoctrineDatabase
- param:
- dsn: mysql:host=localhost;dbname=my_db
- username: root
This is still not what exactly I want. Because when I run the doctrine:build --all --and-load task, all the data in `db_to_read` will also be DELETED!!!
Then I tried to create a database user with only the "select" privilege just for the connection of the`db_to_read` table, and run that task again. Perfect this time!
So, to prevent the doctrine:build --all --and-load task from modifying the structure and data of a specific database, we can supply the connection of it a user with few privileges (only "select" in my case).
But later I found that there's still a drawback for this simple solution: if I have one or more table set to use the readonly database, then an insufficient privilege error will occur when running the doctrine:build --all --and-load task. This is because the doctrine:insert-sql task trys to create table into the readonly table with readonly privilege. To avoid this, I don't have a better solution so far rather than to change the SQL script manually.
Here's the final configurations of the databases.yml.
- // config/databases.yml
- all:
- db_to_read:
- class: sfDoctrineDatabase
- param:
- dsn: mysql:host=localhost;dbname=db_to_read
- username: readonly
- password: readonly
- my_db:
- class: sfDoctrineDatabase
- param:
- dsn: mysql:host=localhost;dbname=my_db
- username: root
References: