How do I write a Doctrine migration which can redistribute data into new tables How do I write a Doctrine migration which can redistribute data into new tables symfony symfony

How do I write a Doctrine migration which can redistribute data into new tables


OK, I seem to have found it, from a number of sources (including this) and trial and error.

Cerad's comments were a little help, but mainly I'm doing it by using the DBAL layer to read in the data (which I can get at by $this->connection), and the ORM to save the new data (which requires the EntityManager, so I did have to use the trick with the container).

I put all the code in postUp(), including the generated code to drop columns from tables.

Sample bits of my code:

use Symfony\Component\DependencyInjection\ContainerAwareInterface;use Symfony\Component\DependencyInjection\ContainerInterface;use PG\InventoryBundle\Entity\Item;use PG\InventoryBundle\Entity\Address;         .         .         ./** * Auto-generated Migration: Please modify to your needs! */class Version20140519211228 extends AbstractMigration implements ContainerAwareInterface{  private $container;  public function setContainer(ContainerInterface $container = null)  {    $this->container = $container;  }  public function up(Schema $schema)  {         .         .         .  }}public function postUp(Schema $schema){    $em = $this->container->get('doctrine.orm.entity_manager');    // ... update the entities    $query = "SELECT * FROM item";    $stmt = $this->connection->prepare($query);    $stmt->execute();    // We can't use Doctrine's ORM to fetch the item, because it has a load of extra fields    // that aren't in the entity definition.    while ($row = $stmt->fetch()) {      // But we will also get the entity, so that we can put addresses in it.      $id = $row['id'];      // And create new objects      $stock = new Stock();         .         .         .      $stock->setAssetNo($row['asset_no']);      $stock->setItemId($row['id']);      $em->persist($stock);      $em->flush();    }    // Now we can drop fields we don't need.     $this->connection->executeQuery("ALTER TABLE item DROP container_id");    $this->connection->executeQuery("ALTER TABLE item DROP location_id");         .         .         . }