在运行Symfony迁移时添加数据

在运行Symfony迁移时添加数据,symfony,doctrine-orm,database-migration,Symfony,Doctrine Orm,Database Migration,我有一个Symfony项目正在使用doctrinmortmigrations包,我有一个非常简单的问题:当我运行迁移时(例如,当我将更新推送到生产时),如何将数据插入数据库 例如:我有一个add类型的实体。该实体为: private $addType; // String private $type1; // Boolean private $type2; // Boolean private $type3; // Boolean 我添加了另一个字段($type4),我想向数据库添

我有一个Symfony项目正在使用doctrinmortmigrations包,我有一个非常简单的问题:当我运行迁移时(例如,当我将更新推送到生产时),如何将数据插入数据库

例如:我有一个add类型的实体。该实体为:

private $addType; // String
private $type1;   // Boolean
private $type2;   // Boolean
private $type3;   // Boolean
我添加了另一个字段(
$type4
),我想向数据库添加一条新记录,其值如下:

$addType = 'Type number 4';
$type1 = false;
$type2 = false;
$type3 = false;
$type4 = true;
教条移民怎么能做到这一点?有可能吗?

我刚刚问了一位相关人士

可以使用迁移包向数据库添加数据。如果添加新属性并使用原则映射,则

php应用程序/控制台原则:迁移:diff

命令将生成新的迁移文件。您可以使用以下语法将insert语句放入此文件中:

$this->addSql('INSERT to your_table(name)VALUES(“foo”))

但是,请确保将其放在自动生成的模式更改之后。如果要将模式更改和数据更改分开,则可以使用

php应用程序/控制台原则:迁移:生成

创建一个空迁移文件,将insert语句放入其中

正如我在相关问题中所说的,这是一种方法,但如果要更改数据库中的数据,则需要手动创建这些数据

编辑:

由于这个答案似乎得到了一些观点,我认为值得补充的是,为了更清楚地将数据更改与模式更改分开,有一个
postp
方法可以被覆盖,它将在
up
方法之后被调用

我已经“找到”了解决问题的正确方法(使用我的实体类在运行迁移后插入数据)

这是:

其思想是将迁移声明为
containerware
,然后从
postp
函数调用DI以获取
EntityManager
。这非常简单,您可以使用所有的实体和存储库

// ...
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class Version20130326212938 extends AbstractMigration implements ContainerAwareInterface
{

    private $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function up(Schema $schema)
    {
        // ... migration content
    }

    public function postUp(Schema $schema)
    {
        $em = $this->container->get('doctrine.orm.entity_manager');
        // ... update the entities
    }
}

按照另一个答案中的建议使用实体管理器不是一个好主意,因为它会导致以后的麻烦

在第一次迁移中,我创建了一个包含用户的表,并通过
$em->persist($user)填充了一些用户一开始看起来不错


但一个月后,我在我的用户模型中添加了一个
phone
列。在第一次迁移过程中,Doctrine会使用此列生成INSERT语句,但由于不存在列
phone
,迁移失败。当然,在第一次迁移中它还不存在。因此,最好使用纯SQL插入。

当您创建新字段时,您需要输入此注释“
options={“default”:1}
”,它应该可以工作

/**
 * @var boolean
 * @ORM\Column(name="type4", type="boolean", options={"default":1})
 */
private $type4 = true;

我花了一些时间才弄明白这一点:)

如果你知道如何格式化数组的话,它会的

$this->connection->insert('user', ['id' => 1, 'gender' => 'Male']);

在迁移中填写日期听起来不是一个好主意,不是它的责任,symfony有一种方法可以做到这一点

嗨。我不熟悉移民理论,但我只是想理解你的问题。我是否可以澄清一下,我理解您的意思:当您运行迁移时,您已经向您的实体添加了一个新属性(
$type4
),并且您希望在数据库中插入此属性及其基础db列的默认值(
true
)。这准确吗?@Darragh:不准确。第一部分是正确的:向实体添加新属性。但我不想定义一个默认值,我想要的是向数据库中添加一条新记录。我知道这个例子很傻,但这正是我需要的…哦,对了,对不起,我不明白你的意思。我将删除我的答案。我想您仍然可以使用
$this->connection->executeQuery('INSERT-INTO-add(foo,bar)value('a','b'))
在您的迁移中。我不知道是否可以在迁移中使用ORM层,假设这是您想要做的。使用doctrinefixturebundle@Matteo:AFAIK,这不是一个选项,因为当您运行
fixtures:load
命令时(我不记得它是否就是这个命令),数据库已清除…我不希望每次安装更新时都清除生产数据库…编辑:有一个标志(
--append
)不清除数据库,但这样做会对所有设备收费,而不仅仅是对新设备收费……这是一种不好的做法,不建议这样做,因为如果随后更改实体,则所有使用该实体的迁移都将失败()为了避免这种情况,每项更改都应该由迁移进行,即使是第一个
模式:update
…为了澄清一点,迁移版本一旦迁移,以后将不会在同一数据库中再次运行。每台服务器只运行一次。@smarber我认为还有一个更大的问题,那就是使用ORM取决于您当前的代码基本(实体类),而不是您的数据库架构。因此,假设您在其中一次迁移中删除了一列。如果您必须返回到引用删除的列的早期迁移,则会抛出一个错误,因为当前实体类不具有该属性。因此,您是对的,它需要schema:update,但迁移也应该使用rawsql而不是当前实体类。