Symfony2,$ form-> bind()不调用加法器的实体方法 [英] Symfony2, $form->bind() not calling adder methods of entity

查看:237
本文介绍了Symfony2,$ form-> bind()不调用加法器的实体方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这个问题很简单(本文结尾),但是我已经写了一些理论基础,



理由



如果你愿意,你可以跳过这个理由,直接跳转到问题本身。



我一直在尝试几个小时,试图获得一个ManyToMany关系,从逆向使用 doctrine:generate:entities doctrine:generate:crud 在Symfony2控制台上。



从拥有的一方,被保存在数据库中,生成的crud开箱即用,但不是从反面(这是预期的: http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#owning -side-and-inverse-side



我是什么想要的是使它从反面工作,而不改变自动生成的控制器;我想更改模型(实体)。



简单的方法是将几个自定义代码行添加到控制器中:

  //控制器工作方式我想要
//控制器/ 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();

//开始自定义代码
foreach($ entity-> getResponsaveis()as $ responsavel){
$ responsavel-> addAluno($ entity);
}
//结束自定义代码

$ em-> persist($ entity);
$ em-> flush();

return $ this-> redirect($ this-> generateUrl('aluno_edit',array('id'=> $ entity-> getId())));
}

返回数组(
'entity'=> $ entity,
'form'=> $ form-> createView(),
);
}

...

以前的代码有效,但是这不是我想要的,因为这些自定义的代码行是指关系逻辑,并且应该集中在Entity本身中(如果不是,则必须在更新该实体的控制器上重复)。 p>

所以,接下来我做的是更改实体文件中的加法器和删除器来执行所需的逻辑,添加代码以自动更新反向和拥有方(推荐在 http ://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#picking-owning-and-inverse-side https://stackoverflow.com/a/7045693/1501575

  // Entity / Aluno.php 

...

/ **
*添加Responsaveis
*
* @param \MyBundle\Entity\Responsavel $ responsaveis
* @return Aluno
* /
public function addResponsavei(\MBBlele\Entity\Responsavel $ responsaveis)
{

/ *开始自定义代码* /
// var_dump('addResponsavei');
$ responsavel-> addAluno($ this);
/ *结束自定义代码* /

$ this-> responsaveis [] = $ responsaveis;
return $ this;
}

...

这应该工作,因为当控制器中的代码相同时,它的工作正常,但实际上没有。



问题是方法 Aluno ## addResponsavei )在控制器(第一个代码示例)中运行的 $ form-> bind($ request)时不会被调用(我意识到这个var_dump()行,我也把var_dumps放在一些其他的getter中,那些其他方法被正常调用)。



所以,所有的常规设置器都是确实在 $ form-> bind($ request)内调用,但不是这一个。这是奇怪的,因为方法名称是由doctrine:generate:entities自动生成的,我假设将使$ form-> bind()知道如何调用所有的setter,getter和adders。





为什么$ form-> bind()不调用加法器方法(Aluno ## addResponsavei())?



有没有一个特殊的命名约定,不遵循 doctrine:generate:crud ,阻止该方法被发现和执行?谢谢你的来自user1452962的评论,后来来自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))

...

这样,关系逻辑从控制器中消失,而我正在寻找。谢谢你们。

解决方案

你需要设置 by_reference 选项 false 为了加载器被调用。


I'm sorry for my bad English, I'm not a native speaker. Feel free to correct my text if needed.

The question is really simple (it's in the end of this text), but I've written a rationale with some research and tests.

Rationale

If you want, you can skip this rationale and jump directly to the question itself.

I've been trying for several hours on trying to get a ManyToMany relationship to persist from the inverse side using doctrine:generate:entities and doctrine:generate:crud on Symfony2 console.

From the owning side, the relationship is saved in the database with the generated crud out of the box, but not from the inverse side (this is expected: http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#owning-side-and-inverse-side)

What I want is to make it work from the inverse side as well without changing the autogenerated controllers; I'd like to change only the model (entity).

The easy way would be to add a couple of custom code lines to the controller:

// 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(),
    ); 
}

...

The previous code works, but it is not what I want, because those custom lines of code refer to the relationship logic, and should be centralized in the Entity itself (if not, it would have to be duplicated all over the controllers that update this entity).

So, what I did next was to change my adders and removers in the Entity file to execute that required logic, adding the code to automatically update both inverse and owning side (as recommended in http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#picking-owning-and-inverse-side and https://stackoverflow.com/a/7045693/1501575)

// 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;
}

...

This should work, because it does work when the same code is in the controller, but it actually does not.

The problem is that the method Aluno##addResponsavei() is never being called when $form->bind($request) runs in the controller (first code sample up there) (I realized this with that var_dump() line. I've also put var_dumps in some other getters and those other methods were called as normal).

So, all the regular setters are indeed called inside $form->bind($request), but not this one. This is weird, because the method names were autogenerated by `doctrine:generate:entities', which I assumed would make $form->bind() know how to call all the setters, getters and adders.

Question

Why is $form->bind() not calling the adder method (Aluno##addResponsavei())?

Is there a special naming convention not followed by doctrine:generate:crud that is preventing the method from being found and executed?

Solution

Thanks for the comment from user1452962 and later the answer from Elnur Abdurrakhimov, I've got it to work and it is actually pretty simple.

All I had to do is to add the option 'by_reference' to false in the properties that hold the inverse side of the relationship, and suddenly addResponsavei() began to be called.

// 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))

...

This way, the relationship logic is gone from the controller, and that what I was looking for. Thank you guys.

解决方案

You need to set the by_reference option to false in order for adders to be called.

这篇关于Symfony2,$ form-> bind()不调用加法器的实体方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆