教义装置加载时,具有问题设置引用外键违反了-not-null约束

问题描述

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

我的AppFixtures.PHP类的设置方式是已经用以下方式编写了每个模型值:

 private const USERS = [
      [
          'last_name' => 'Goodman','first_name'=> 'Robert','email' => '[email protected]','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()方法,但是我得到的引用不存在,所以我切换到addReference()时遇到另一个错误,即引用已经存在,我需要使用{{1} }覆盖它,所以我收到错误后将方法更改为setReference()

setReference()

我在sqlSTATE[23502]: Not null violation: 7 ERROR: null value in column "theme_id" violates not-null constraint 上也遇到相同的错误。 当我将user.id值添加主题中时,user.id可以很好地工作,但是对于southeme却无法正常工作,我想弄清楚为什么,是因为我要注入两个外键,所以我高度怀疑,我不知道自己要缺少什么,在有人说出来之前,是的,我是先按正确的顺序加载用户的值,然后再加载主题,然后再添加主题

getReference

这是UploadUsers函数

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

解决方法

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

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');时,您都会获得可以在设置器中使用的User对象。 setUser();

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

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()确实是用于设置User对象,而不仅仅是用户名(为什么它不称为setUser?)