运行 Symfony 迁移时添加数据

问题描述 投票:0回答:8

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

例如:我有一个 Entity,它是 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;

如何使用 DoctrineMigrations 来完成此操作?可以吗?

symfony doctrine-orm database-migration
8个回答
16
投票

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

在第一次迁移中,我创建了一个包含 users 的表,并通过

$em->persist($user);
填充了一些用户,一开始看起来不错。

但是一个月后,我在我的用户模型中添加了一个

phone
列。 Doctrine 在第一次迁移中使用此列生成 INSERT 语句,由于不存在列
phone
,该语句失败。当然,在第一次迁移中它还不存在。所以最好使用纯 SQL INSERT。


10
投票

我刚刚问了一个相关的相关问题

可以使用迁移包将数据添加到数据库。如果您添加新属性并使用学说映射,那么

php app/console doctrine:migrations:diff

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

$this->addSql('INSERT INTO your_table (name) VALUES ("foo")');

请确保将其放在自动生成的架构更改之后。如果您想将架构更改和数据更改分开,那么您可以使用

php app/console doctrine:migrations:generate

创建一个空的迁移文件来放入插入语句。

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

编辑:

由于这个答案似乎得到了一些观点,我认为值得添加的是,为了更清楚地将数据更改与模式更改分开,有一个可以重写的

postUp
方法,并且将在
up
方法之后调用。

https://www.doctrine-project.org/projects/doctrine-migrations/en/3.0/reference/migration-classes.html#postup


4
投票

确实如此,如果您知道如何格式化数组;

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

3
投票

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

这里是:https://stackoverflow.com/a/25960400

想法是将迁移声明为

ContainerAware
,然后从
postUp
函数中调用 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
    }
}

3
投票

当您创建新字段时,您需要输入此注释“

options={"default":1}
”,它应该可以工作。

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

我花了一些时间才弄清楚这一点:)


0
投票

这对我来说是一个很好的解决方案。只需使用 bin/console make:migration ,生成迁移时只需编辑 if 并添加“DEFAULT TRUE”: $this->addSql('ALTER TABLE 事件 ADD active TINYINT(1) NOT NULL DEFAULT TRUE');


0
投票

使用 Symfony 7 的简短摘要

<?php 

// symfony 7
// php 8.2

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use App\Entity\CustomEntity;

final class Version20230101000000 extends AbstractMigration 
{
  /** @var CustomEntity[] */
  private static function getData(): array
  {
    return [
      (new CustomEntity())->setProperty('value'),
      (new CustomEntity())->setProperty('nextValue'),
    ];
  }

  public function up(Schema $schema): void 
  {
    // table structure is create here
  }

  public function postUp(Schema $schema): void
  {
    foreach(self::getData() as $entity) {
      $this->connection->insert(
        table:'table_name', 
        data: ['property' => $entity->getProperty()]
      );
    }
  }

  public function down(Schema $schema):void
  {
    // no changes required
  }

}

Fixtures 是为在开发环境中处理示例数据而构建的。因此,它们不是用来阻止数据进入高效数据库的选项。

对于组默认条目,可以使用迁移文件。如果您需要防止大量数据,请考虑构建一个 TaskRunner 并分块工作。


-1
投票

在迁移中填写日期听起来不是一个好主意,这不是它的责任,symfony 有办法做到这一点。 https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html

© www.soinside.com 2019 - 2024. All rights reserved.