Doctrine fixtures 加载,有问题设置引用(外键)违反 -not-null 约束

Doctrine fixtures load, having issue setting references (foreign key) violates -not-null constraint

我正在使用 Doctrine Fixtures 将一些数据加载到我的数据库中, 有 3 个不同的表 User、Theme 和 Sous_Theme,最后两个表有外键,Theme 为 (user.id) 和 Sous_Theme 作为两个外键 (user.id & theme.id)

我的 AppFixtures.php class 的设置方式是每个模型值都已经以这种方式写入:

 private const USERS = [
      [
          'last_name' => 'Goodman',
          'first_name'=> 'Robert',
          'email' => 'robert@foobar.com',
          'job' => 'Admin_Tester',
          'password' => 'blablablablablbal',
          'username' => 'blablablabla',
          'roles' => [USER::ROLE_ADMIN]
      ]...
]



private const THEMES =
    [
        ['name' => 'A theme'],
        ['name' => ' A theme 2']
  .....
]

private const SOUSTHEMES = [
    [
        'name' => 'blablabla',
        'part1' => true, //boolean
        ...
    ],

在编写 SOUSTHEMES 部分之前,我已经加载了 Users 和 Themes 值以及它完美运行的参考:

public function loadTheme(ObjectManager $manager)
    {
        foreach (self::THEMES as $themeDate){
            $theme = new Theme();
            $theme->setName($themeDate['name']);
            $date = new \DateTime();
            $date->modify('-'. rand(0, 10) . 'day');
            $theme->setCreatedAt($date);
            //// Setting user Id into our Theme table.
            $theme->setUser($this->getReference(
                self::USERS[rand(0, count(self::USERS) - 1)]['last_name']));
            $manager->persist($theme);
        }
        $manager->flush();
    }

现在我正在尝试使用引用 theme.id 和 user.id 加载 sousthemes :

public function loadSousThemes(ObjectManager $manager){
        foreach (self::SOUSTHEMES as $sousthemeData){
            $sousthemes = new SousTheme();
            $sousthemes->setName($sousthemeData['name']);
            $date = new \DateTime();
            $date->modify('-'. rand(0, 10) . 'day');
            $sousthemes->setCreatedAt($date);
   

            //// Setting boolean values
            $sousthemes->setPart1($sousthemeData['part_n1']);
  $sousthemes->setUsername($this->setReference(
                self::USERS[rand(0, count(self::USERS) - 1)]['last_name'], $sousthemes));
            $sousthemes->setTheme($this->setReference(
                self::THEMES[rand(0, count(self::THEMES) - 1)]['name'], $sousthemes));

            $manager->persist($sousthemes);
        }
        $manager->flush();

我已经开始使用 getReference() 方法,但我发现 ref 不存在,所以我切换到 addReference() 我收到另一个错误,说 ref 已经存在,我需要使用 setReference() 覆盖它所以我将我的方法更改为 setReference() 现在我得到一个错误

SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "theme_id" violates not-null constraint 

我在 user.id 上也遇到同样的错误。 当我将 user.id 值添加到我的主题时,getReference 完美地工作,但它不适用于 southeme 我试图找出原因,是因为我正在注入两个外键,这是我非常怀疑的事情,我不知道我错过了什么,在有人说出来之前大声笑是的,我正在以正确的顺序加载我的价值观,首先是用户,然后是主题,然后是 sousthemes :

public function load(ObjectManager $manager)
    {
        $this->loadUsers($manager);
       $this->loadTheme($manager);
       $this->loadSousThemes($manager);
    }

这是 UploadUsers 函数:

public function loadUsers(ObjectManager $manager)
    {
        foreach (self::USERS as $userData)
        {
            $user = new User();
            $user->setFirstName($userData['first_name']);
            $user->setLastName($userData['last_name']);
            $user->setEmail($userData['email']);
            $user->setJob($userData['job']);
            $user->setPassword($this->passwordEncoder->
            encodePassword($user, $userData['password']));
            $user->setUsername($userData['username']);
            $user->setCreatedAt(new \DateTime());
            $user->setRoles($userData['roles']);
            $this->addReference($userData['last_name'], $user);
            $manager->persist($user);
        }
        $manager->flush();
    }

首先你根本不需要addReference/getReference,因为你只使用一个夹具文件。因此,在您的情况下,您可以只保存对象并在设置器中使用它们,例如:

in loadUsers:

public function loadUsers(ObjectManager $manager)
    {
        foreach (self::USERS as $userData)
        {
            $user = new User();
            ///...
            $manager->persist($user);

            $this->users[$userData['username']] = $user;
        }
        $manager->flush();
    }

and in loadTheme:

$theme->setUser($this->users[self::USERS[rand(0, count(self::USERS) - 1)]['username']]);

您不需要引用,因为您可以访问对象,当夹具位于单独的文件中时,引用很有用,因为这样您就无法访问在不同夹具文件中创建的对象。 此处描述:https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#sharing-objects-between-fixtures .

但是假设您想使用引用,我会尝试提供一些指导来修复您已有的代码。你说通过引用加载用户对主题有用:

$theme->setUser($this->getReference(self::USERS[rand(0, count(self::USERS) - 1)]['last_name']));

之所以有效,是因为您在 loadUsers:

中添加了引用
$this->addReference($userData['last_name'], $user);

所以在 loadUsers 之后,您可以使用这些参考资料:

User objects:
 - Goodman
 - ...

现在,无论何时调用 $this->getReference('Goodman');,您都将获得可在 setter 中使用的用户对象,例如。设置用户();

但您从未在 loadTheme 中调用 addReference 来保存对主题对象的引用。

addReference添加到loadTheme:

public function loadTheme(ObjectManager $manager)
    {
        foreach (self::THEMES as $themeDate){
            $theme = new Theme();
            $theme->setName($themeDate['name']);
            // ...
            $theme->setUser($this->getReference(
                self::USERS[rand(0, count(self::USERS) - 1)]['last_name']));
            $manager->persist($theme);

            $this->addReference($theme->getName(), $theme);
        }
        $manager->flush();
    }

所以在 loadUsersloadThemes 之后,这些参考资料将可用:

User objects:
 - Goodman
 - ...

Theme objects:
 - A theme
 - A theme 2
 - ...

最后在你的 loadSousThemes:

$sousthemes->setUsername($this->getReference(
                self::USERS[rand(0, count(self::USERS) - 1)]['last_name']));
            $sousthemes->setTheme($this->getReference(
                self::THEMES[rand(0, count(self::THEMES) - 1)]['name']));

请注意,我假设 $sousthemes->setUsername() 确实是用于设置用户对象,而不仅仅是用户名(为什么不称为 setUser?)