Like in question topic, how can I setup default table prefix in symfony2?
The best if it can be set by default for all entities, but with option to override for individual ones.
Like in question topic, how can I setup default table prefix in symfony2?
The best if it can be set by default for all entities, but with option to override for individual ones.
I don't when to implement a solution that involved catching event (performance concern), so I have tried the Alternate Solution but it doesn't work for me. I was adding the JMSPaymentCoreBundle and wanted to add a prefix on the payment tables. In this bundle, the definition of the tables are in the Resources\config\doctrine directory (xml format). I have finally found this solution:
1) copy doctrine directory containing the definitions on the table and paste it in my main bundle
2) modify the name of the tables in the definitions to add your prefix
3) declare it in your config.yml, in the doctrine/orm/entity manager/mapping section (the dir is the directory where you have put the modified definitions):
I found solution: http://www.doctrine-project.org/docs/orm/2.0/en/cookbook/sql-table-prefixes.html
@simshaun answer is good, but there is a problem with Many-to-Many relationships and inheritance.
If you have a parent class
User
and a child classEmployee
, and theEmployee
own a Many-to-Many field$addresses
, this field's table will not have a prefix. That is because of:User class (parent)
Employee class (child)
Address class (relation with Employee)
With the original solution, if you apply
pref_
prefixe to this mapping, you will end up with tables :pref_user
pref_address
employee_address
Solution
A solution can be to modify, in the answer of @simshaun, the point 4 like this:
Create MyBundle\Subscriber\TablePrefixSubscriber.php
Here we handle the Many-to-Many relationship before verifying if the class is the child of an inheritance, and we add
$mapping['sourceEntity'] == $classMetadata->getName()
to add the prefix only one time, on the owning entity of the field.Having just figured this out myself, I'd like to shed some light on exactly how to accomplish this.
Symfony 2 & Doctrine 2.1
Note: I use YML for config, so that's what I'll be showing.
Instructions
Open up your bundle's Resources/config/services.yml
Define a table prefix parameter:
Be sure to change mybundle and myprefix_
Add a new service:
Create MyBundle\Subscriber\TablePrefixSubscriber.php
Optional step for postgres users: do something similary for sequences
Alternate answer
This is an update taking into account the newer features available in Doctrine2.
Doctrine2 naming strategy
Doctrine2 uses
NamingStrategy
classes which implement the conversion from a class name to a table name or from a property name to a column name.The
DefaultNamingStrategy
just finds the "short class name" (without its namespace) in order to deduce the table name.The
UnderscoreNamingStrategy
does the same thing but it also lowercases and "underscorifies" the "short class name".Your
CustomNamingStrategy
class could extend either one of the above (as you see fit) and override theclassToTableName
andjoinTableName
methods to allow you to specify how the table name should be constructed (with the use of a prefix).For example my
CustomNamingStrategy
class extends theUnderscoreNamingStrategy
and finds the bundle name based on the namespacing conventions and uses that as a prefix for all tables.Symfony2 naming strategy
Using the above in Symfony2 requires declaring your
CustomNamingStragery
class as a service and then referencing it in your config:Pros and cons
Pros:
Cons:
Simshaun's answer works fine, but has a problem when you have a single_table inheritance, with associations on the child entity. The first if-statement returns when the entity is not the rootEntity, while this entity might still have associations that have to be prefixed.
I fixed this by adjusting the subscriber to the following:
This has a drawback though; A not wisely chosen prefix might cause conflicts when it's actually already part of a table name. E.g. using prefix 'co' when theres a table called 'content' will result in a non-prefixed table, so using an underscore like 'co_' will reduce this risk.