Col*_*ine 15 php symfony doctrine-orm doctrine-migrations
我有一个数据库(实际上是在Symfony1应用程序中使用Propel创建的).我在Symfony2和Doctrine中重新实现它,但我也想借此机会在某种程度上重构数据库.
我已经定义了一组Doctrine Entities并运行了doctrine:migrations:diff,它创建了一个基本的Migration来添加表,列和约束,并删除一堆列.
但是,在删除这些列之前,我想将数据复制到一些新表中,然后将这些表中的新记录链接到第一个表中的新列.我不相信在纯SQL中可以这样做(通常,一个表的内容分布在三个或四个表中).
这给了我一个提示,并让我找到了这个(我已经跳过了,因为我不知道"容器"与我的问题有什么相关性).
但是我在Symfony或Doctrine文档中没有找到的是在迁移中实际移动数据的一个例子 - 对我来说这似乎是迁移的核心目的之一!
我可以使用上面那些链接中的提示,但后来我不知道如何继续.我没有(并且真的不想花时间创建,虽然我确定我能做到)现有数据库模式的Doctrine实体:我可以使用DQL吗?我根本就不知道.
所以有两个问题:
有人能给我一个在表之间移动数据的Doctrine迁移的例子吗?
或者,任何人都可以澄清DQL的语法如何依赖于Doctrine中实体的定义?我可以使用它来指定不在实体定义中的列吗?
Col*_*ine 20
好吧,我似乎从许多来源(包括这个)和反复试验找到了它.
Cerad的评论有点帮助,但主要是我通过使用DBAL层读取数据(我可以得到$this->connection
)和ORM来保存新数据(这需要EntityManager,所以我做了)必须使用容器的技巧).
我把所有代码都postUp()
包括在内,包括生成的代码从表中删除列.
我的代码的示例位:
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'];
$item = $em->getRepository('PGInventoryBundle:Item')->find($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");
.
.
.
}
Run Code Online (Sandbox Code Playgroud)