我很抱歉我的英语不好,我不是母语人士。如果需要,请随时更正我的文字。
这个问题非常简单(在本文的最后),但我已经写了一些研究和测试的理由。
如果您愿意,可以跳过此理由并直接跳到问题本身。
我一直试图在Symfony2控制台上使用doctrine:generate:entities
和doctrine:generate:crud
从反面维持一个ManyToMany关系几个小时。
从拥有方来看,关系将保存在数据库中,生成的crud开箱即用,但不是从反面(这是预期的:http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#owning-side-and-inverse-side)
我想要的是在不改变自动生成的控制器的情况下使其从反面工作;我只想改变模型(实体)。
简单的方法是向控制器添加几个自定义代码行:
// Controller that works the way I want
// Controller/AlunoController.php
...
public function createAction(Request $request)
{
$entity = new Aluno();
$form = $this->createForm(new AlunoType(), $entity);
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
// begin custom code
foreach ($entity->getResponsaveis() as $responsavel) {
$responsavel->addAluno($entity);
}
// end custom code
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('aluno_edit', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
...
以前的代码可以工作,但它不是我想要的,因为那些自定义代码行是指关系逻辑,应该集中在实体本身(如果没有,它必须在整个控制器上重复更新此实体)。
因此,我接下来要做的是更改Entity文件中的加法器和删除器以执行所需的逻辑,添加代码以自动更新反向和拥有方(如http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#picking-owning-and-inverse-side和{{3中所建议的那样) }})
// Entity/Aluno.php
...
/**
* Add responsaveis
*
* @param \MyBundle\Entity\Responsavel $responsaveis
* @return Aluno
*/
public function addResponsavei(\MyBundle\Entity\Responsavel $responsaveis)
{
/* begin custom code */
//var_dump('addResponsavei');
$responsavel->addAluno($this);
/* end custom code */
$this->responsaveis[] = $responsaveis;
return $this;
}
...
这应该可行,因为当控制器中存在相同的代码时它确实有效,但它实际上没有。
问题是当Aluno##addResponsavei()
在控制器中运行时(第一个代码示例在那里),从不调用方法$form->bind($request)
(我用var_dump()行实现了这一点。我也是将var_dumps放在其他一些getter中,其他方法也被正常调用。
因此,所有常规的setter确实在$form->bind($request)
内部调用,但不是这个。这很奇怪,因为方法名称是由`doctrine:generate:entities'自动生成的,我假设它会使$ form-> bind()知道如何调用所有的setter,getters和adders。
为什么$ form-> bind()没有调用加法器方法(Aluno ## addResponsavei())?
是否有一个特殊的命名约定,doctrine:generate:crud
后面没有阻止找到并执行该方法?
感谢用户1452962的评论以及后来来自Elnur Abdurrakhimov的答案,我已经开始工作,实际上非常简单。
我所要做的就是在保持关系反面的属性中将选项'by_reference'添加到false,突然addResponsavei()
开始被调用。
// Form/AlunoType.php
...
$builder
->add('nome')
->add('cidade_natal')
->add('nascimento')
->add('email')
->add('endereco')
->add('nome_sem_acento')
->add('data_hora_cadastro')
->add('responsaveis', null, array('by_reference' => false))
->add('turmas', null, array('by_reference' => false))
...
这样,关系逻辑就从控制器中消失了,那就是我在寻找的东西。谢谢你们。