Doctrine 固定装置加载,有问题设置引用(外键)违反 -not-null 约束
Posted
技术标签:
【中文标题】Doctrine 固定装置加载,有问题设置引用(外键)违反 -not-null 约束【英文标题】:Doctrine fixtures load, having issue setting references (foreign key) violates -not-null constraint 【发布时间】:2020-08-20 15:29:30 【问题描述】:我正在使用 Doctrine Fixtures 将一些数据加载到我的数据库中, 有 3 个不同的表 User、Theme 和 Sous_Theme,最后两个表有外键,Theme as (user.id) 和 Sous_Theme 作为两个外键 (user.id & theme.id)
我的AppFixtures.php
类的设置方式是每个模型值都已经以这种方式写入:
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 部分之前,我已经加载了用户和主题值以及它完美工作的参考:
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
上也遇到了同样的错误。
getReference
在我将 user.id 值添加到我的主题时完美运行,但它不适用于 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();
【问题讨论】:
还显示 loadUsers 方法。在您的 loadSousThemes 中,这些绝对应该是使用的 getReference 方法,而不是 setReference。 @blahy 刚刚添加了 loaduser 函数,是的,我知道它应该是 getReference,但是当我使用该方法时我得到了一个引用,当我使用 setReference 时我得到一个关于 null 约束的 sqlite 错误 【参考方案1】:首先,您根本不需要 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 中使用的User 对象,例如。设置用户();
但您从未在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();
所以在loadUsers
和loadThemes
之后,这些引用将可用:
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?)
【讨论】:
谢谢!是的,我刚刚意识到使用需要应用于主题加载器的 addreference 方法。现在更有意义了以上是关于Doctrine 固定装置加载,有问题设置引用(外键)违反 -not-null 约束的主要内容,如果未能解决你的问题,请参考以下文章
Symfony 3.3 Doctrine Fixtures 加载跳过 SQL 视图