doctrine-orm

Doctrine swap out table at runtime


Typically when you implement a entity using Doctrine you map it to a table explicitly:

<?php
/**
 * @Entity
 * @Table(name="message")
 */
class Message
{
    //...
}

Or you reply on doctrine to implicitly map your class name to a table...I have several tables which are identical in schema but I do not wish to re-create the class for each time...there fore at runtime (dynamically) I would like to change the table name accordingly.

Where do I start or what would I look into overriding to implement this odd requirement???


Solution

  • Surprisingly (to me), the solution is very simple. All you have to do is to get the ClassMetadata of your entity and change the name of the table it maps to:

    /** @var EntityManager $em */
    $class = $em->getClassMetadata('Message');
    $class->setPrimaryTable(['name' => 'message_23']);
    

    You need to be careful and do not change the table name after you have loaded some entities of type Message and changed them. It's a big chance it will either produce SQL errors on saving (because of the table constraints, for example), if you are lucky or it will modify the wrong row (from the new table).

    I suggest the following workflow:

    1. set the desired table name;
    2. load some entities;
    3. modify them at will;
    4. save them;
    5. detach them from the entity manager (the method EntityManager::clear() is a quick way to start over);
    6. go back to step 1 (i.e. repeat using another table).

    The step #5 (detach the entities from the entity manager) is useful even if you don't change or don't save the entities. It allows the entity manager use less memory and work faster.

    This is just one of the many methods you can use to dynamically set/change the mapping. Take a look at the documentation of class ClassMetadata for the rest of them. You can find more inspiration in the documentation page of the PHP mapping.