Symfony 级联持久化或合并复制
Symfony cascade persist or merge duplication
我的级联持久化或合并有问题,我的应用程序有两个实体任务和 table (task_implements)
当我创建任务时,我选择链接的文化:
- 如果用户选择 3 种文化 => 创建 3 个任务
- 如果用户选择 3 种文化,则 2 辆车 => 必须有 3 个任务
已创建且每个任务绑定 2 辆车
TaskController new()
if ( $form->isSubmitted() && $form->isValid() ) {
// Cultures
foreach ( $form->get('cultures')->getData() as $culture) {
// Set correct status
if ( $task->getUser() === null ) {
$task->setStatus( 2 );
} else {
$task->setStatus( 3 );
}
$task->setCulture( $culture );
// Implements
foreach ( $form->get('implements')->getData() as $implement) {
$taskImplement = new TaskImplement();
$taskImplement->setImplement( $implement );
$task->addImplement( $taskImplement );
}
$this->em->merge( $task );
$this->em->flush();
}
$this->addFlash('success', 'Nouvelle tache ajoutée avec succès');
return $this->redirectToRoute('admin_task_index');
}
任务新类型
->add('implements', EntityType::class, [
'class' => Implement::class,
'query_builder' => function( ImplementRepository $ir ) {
return $ir->createQueryBuilder('i');
},
'choice_label' => function( Implement $implement ) {
return $implement->getName();
},
'mapped' => false,
'required' => false,
'expanded' => true,
'multiple' => true
])
任务实体
/**
* @ORM\OneToMany(targetEntity=TaskImplement::class, mappedBy="task", orphanRemoval=true, cascade={"persist", "merge"})
*/
private $implements;
public function addImplement(TaskImplement $taskImplement): self
{
if (!$this->implements->contains($taskImplement)) {
$this->implements[] = $taskImplement;
$taskImplement->setTask($this);
}
return $this;
}
期望的行为
如果我举个例子,如果我选择 3 种文化应用程序创建 3 个任务并在每个任务中创建 2 个实现绑定
id / culture_id
#1 10
#2 11
#3 12
在task_implement
id / task_id / implement_id
#1 1 20
#2 1 21
#3 2 20
#4 2 21
#5 3 20
#6 3 21
我得到的
id / culture_id
#1 10
#2 11
#3 12
于 task_implement
id / task_id / implement_id
#1 | 1 | 20 @
#2 | 1 | 21
#3 | 2 | 20 @
#4 | 2 | 21 @
#5 | 2 | 20 @
#6 | 2 | 21
#7 | 3 | 20 @
#8 | 3 | 21 @
#9 | 3 | 20 @
#10 | 3 | 21 @
#11 | 3 | 20 @
#12 | 3 | 21
我不明白为什么它不能在数据库中的每条记录之间清除,如果我放入 4 个区域性我在最后一个 TaskImplement 上有 4 个条目,它会重复
感谢您的帮助
显然,merge
会在您每次调用它时创建一个新的任务条目(这可能意味着,您的 $task
没有 ID。
在外部 foreach
的第一个循环中,您添加了 2 个同样没有 ID 的 TaskImplements。您的任务现在有 2 个 TaskImplements(这是您此时想要的)。
在外部 foreach
的第二个循环中,您添加 另一个 2 个 TaskImplements - 现在您的任务有 4 个 TaskImplements。
解决方案选项:
- 您需要在第一个外部 foreach 之后停止添加 TaskImplements(这会很奇怪,但会起作用)或者
- 你设置你的任务实现而不是添加它们或
- 在添加新任务之前清除任务工具的任务对象或
- 您在添加任务工具之前“克隆”了任务(创建一个新任务可能就足够了吗?)。
事后思考
您对 merge
的使用非常有趣。使用 persist,您应该只有 one Task,其中包含 6 个 TaskImplement 并且只有最后一个文化集。老实说,在没有任务 ID 的情况下进行合并感觉像是一种反模式。
我假设您的表单本身有 data_type 任务,这基本上是错误的,因为您是 editing/creating 多项任务。您处理表单时就好像您有多项任务一样,但实际上您只有一项任务。你的问题的根源在于错误的语义......
没关系,我在提交时成功地完成了我的控制器代码
if ( $form->isSubmitted() && $form->isValid() ) {
// Cultures
foreach ( $form->get('cultures')->getData() as $culture) {
// Set correct status
if ( $task->getUser() === null ) {
$task->setStatus( 2 );
} else {
$task->setStatus( 3 );
}
$task->setCulture( $culture );
$this->em->persist( $task );
// Implements
foreach ( $form->get('implements')->getData() as $implement) {
$taskImplement = new TaskImplement();
$taskImplement->setImplement( $implement );
$taskImplement->setTask( $task );
$this->em->persist( $taskImplement );
}
$this->em->flush();
$this->em->clear( Task::class );
$this->em->clear( TaskImplement::class );
}
$this->addFlash('success', 'Nouvelle tache ajoutée avec succès');
return $this->redirectToRoute('admin_task_index');
}
我只是清除每个实体上的两个实体
并且正在工作
我的级联持久化或合并有问题,我的应用程序有两个实体任务和 table (task_implements)
当我创建任务时,我选择链接的文化:
- 如果用户选择 3 种文化 => 创建 3 个任务
- 如果用户选择 3 种文化,则 2 辆车 => 必须有 3 个任务 已创建且每个任务绑定 2 辆车
TaskController new()
if ( $form->isSubmitted() && $form->isValid() ) {
// Cultures
foreach ( $form->get('cultures')->getData() as $culture) {
// Set correct status
if ( $task->getUser() === null ) {
$task->setStatus( 2 );
} else {
$task->setStatus( 3 );
}
$task->setCulture( $culture );
// Implements
foreach ( $form->get('implements')->getData() as $implement) {
$taskImplement = new TaskImplement();
$taskImplement->setImplement( $implement );
$task->addImplement( $taskImplement );
}
$this->em->merge( $task );
$this->em->flush();
}
$this->addFlash('success', 'Nouvelle tache ajoutée avec succès');
return $this->redirectToRoute('admin_task_index');
}
任务新类型
->add('implements', EntityType::class, [
'class' => Implement::class,
'query_builder' => function( ImplementRepository $ir ) {
return $ir->createQueryBuilder('i');
},
'choice_label' => function( Implement $implement ) {
return $implement->getName();
},
'mapped' => false,
'required' => false,
'expanded' => true,
'multiple' => true
])
任务实体
/**
* @ORM\OneToMany(targetEntity=TaskImplement::class, mappedBy="task", orphanRemoval=true, cascade={"persist", "merge"})
*/
private $implements;
public function addImplement(TaskImplement $taskImplement): self
{
if (!$this->implements->contains($taskImplement)) {
$this->implements[] = $taskImplement;
$taskImplement->setTask($this);
}
return $this;
}
期望的行为
如果我举个例子,如果我选择 3 种文化应用程序创建 3 个任务并在每个任务中创建 2 个实现绑定
id / culture_id
#1 10
#2 11
#3 12
在task_implement
id / task_id / implement_id
#1 1 20
#2 1 21
#3 2 20
#4 2 21
#5 3 20
#6 3 21
我得到的
id / culture_id
#1 10
#2 11
#3 12
于 task_implement
id / task_id / implement_id
#1 | 1 | 20 @
#2 | 1 | 21
#3 | 2 | 20 @
#4 | 2 | 21 @
#5 | 2 | 20 @
#6 | 2 | 21
#7 | 3 | 20 @
#8 | 3 | 21 @
#9 | 3 | 20 @
#10 | 3 | 21 @
#11 | 3 | 20 @
#12 | 3 | 21
我不明白为什么它不能在数据库中的每条记录之间清除,如果我放入 4 个区域性我在最后一个 TaskImplement 上有 4 个条目,它会重复
感谢您的帮助
显然,merge
会在您每次调用它时创建一个新的任务条目(这可能意味着,您的 $task
没有 ID。
在外部 foreach
的第一个循环中,您添加了 2 个同样没有 ID 的 TaskImplements。您的任务现在有 2 个 TaskImplements(这是您此时想要的)。
在外部 foreach
的第二个循环中,您添加 另一个 2 个 TaskImplements - 现在您的任务有 4 个 TaskImplements。
解决方案选项:
- 您需要在第一个外部 foreach 之后停止添加 TaskImplements(这会很奇怪,但会起作用)或者
- 你设置你的任务实现而不是添加它们或
- 在添加新任务之前清除任务工具的任务对象或
- 您在添加任务工具之前“克隆”了任务(创建一个新任务可能就足够了吗?)。
事后思考
您对 merge
的使用非常有趣。使用 persist,您应该只有 one Task,其中包含 6 个 TaskImplement 并且只有最后一个文化集。老实说,在没有任务 ID 的情况下进行合并感觉像是一种反模式。
我假设您的表单本身有 data_type 任务,这基本上是错误的,因为您是 editing/creating 多项任务。您处理表单时就好像您有多项任务一样,但实际上您只有一项任务。你的问题的根源在于错误的语义......
没关系,我在提交时成功地完成了我的控制器代码
if ( $form->isSubmitted() && $form->isValid() ) {
// Cultures
foreach ( $form->get('cultures')->getData() as $culture) {
// Set correct status
if ( $task->getUser() === null ) {
$task->setStatus( 2 );
} else {
$task->setStatus( 3 );
}
$task->setCulture( $culture );
$this->em->persist( $task );
// Implements
foreach ( $form->get('implements')->getData() as $implement) {
$taskImplement = new TaskImplement();
$taskImplement->setImplement( $implement );
$taskImplement->setTask( $task );
$this->em->persist( $taskImplement );
}
$this->em->flush();
$this->em->clear( Task::class );
$this->em->clear( TaskImplement::class );
}
$this->addFlash('success', 'Nouvelle tache ajoutée avec succès');
return $this->redirectToRoute('admin_task_index');
}
我只是清除每个实体上的两个实体
并且正在工作