在运行Symfony迁移时添加数据
我有一个Symfony项目正在使用doctrinmortmigrations包,我有一个非常简单的问题:当我运行迁移时(例如,当我将更新推送到生产时),如何将数据插入数据库 例如:我有一个add类型的实体。该实体为:在运行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),我想向数据库添
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而不是当前实体类。