Symfony2,$ form-> bind()不调用实体的加法方法

时间:2013-02-27 01:26:12

标签: symfony doctrine-orm many-to-many

我很抱歉我的英语不好,我不是母语人士。如果需要,请随时更正我的文字。

这个问题非常简单(在本文的最后),但我已经写了一些研究和测试的理由。

原理

如果您愿意,可以跳过此理由并直接跳到问题本身。

我一直试图在Symfony2控制台上使用doctrine:generate:entitiesdoctrine: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))

...

这样,关系逻辑就从控制器中消失了,那就是我在寻找的东西。谢谢你们。

1 个答案:

答案 0 :(得分:9)

您需要将by_reference option设置为false才能调用加法器。