问题描述
我正在使用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();
}
因此,在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()
确实是用于设置User对象,而不仅仅是用户名(为什么它不称为setUser?)