Symfony2表单中的交叉引用不能按预期工作

时间:2012-02-11 13:24:37

标签: symfony doctrine-orm symfony-forms fosuserbundle

这是我的第一个问题,所以请原谅任何错误 - 我会在下次尝试避免这些错误。 ; - )

我为FOSUserBundle编写了一个自定义RegistrationFormType。除了bundle的默认字段外,此表单还处理PlayerType。此PlayerType本身再次包含PlayerSkillsType。这里的课程:

class RegistrationFormType extends BaseType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder->add('player', new PlayerType());
    }

    public function getName()
    {
        return 'signup_form';
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'Acme\AcmeBundle\Entity\User',
        );
    }
}

class PlayerType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('firstname');
        $builder->add('lastname');
        $builder->add('age');
        $builder->add('playerSkills', new PlayerSkillsType());
    }

    public function getName()
    {
        return 'player_form';
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'Acme\AcmeBundle\Entity\Player',
        );
    }
}

class PlayerSkillsType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('tackling');
        $builder->add('passing');
        $builder->add('shooting');
    }

    public function getName()
    {
        return 'playerSkills_form';
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'Acme\AcmeBundle\Entity\PlayerSkills',
        );
    }
}

/**
 * @ORM\Entity
 */
class Player
{
    /**
     * @ORM\OneToOne(targetEntity="PlayerSkills", cascade={"persist"})
     *
     * @var PlayerSkills
     */
    private $playerSkills;
}

/**
 * @ORM\Entity
 */
class PlayerSkills
{
    /**
     * @ORM\OneToOne(targetEntity="Player", cascade={"persist"})
     *
     * @var Player
     */
    private $player;
}

(我遗漏了getter和setter以及不重要​​的属性和方法。) 到目前为止,此工作正常,表单显示并保持不变。现在,我的问题是,在持久化数据后,数据中的PlayerSkills实体将缺少引用返回给Player实体。

我认为我需要告诉PlayerSkillsType它还应该在表单生成器中添加引用..?或者这可能是Doctrine注释中的问题?

任何提示都非常感谢! : - )

1 个答案:

答案 0 :(得分:0)

问题可能来自数据初始化和/或学说映射。

如果没有使用$form->setData传递,则表单将创建data_class。 当您提交表单并绑定数据时,它将调用$player>setPlayerSkills($playerSkill), 但它不会调用$ playerSkill-> setPlayer($ player);

根据oneToOne关联的拥有方,您应该调用两种方法中的一种,以便Doctrine知道这种关联(http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#owning-side-and-inverse-side)。

尝试修改PlayerSkills中的注释映射以引入inversedBy信息(http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#one-to-one-bidirectional)。

它应该是这样的:

 /**
 * @ORM\OneToOne(targetEntity="Player", mappedBy="playerSkills", cascade={"persist"})
 *
 * @var Player
 */
private $player;

Player类同样如此:

/**
 * @ORM\OneToOne(targetEntity="PlayerSkills", inversedBy="player" cascade={"persist"})
 *
 * @var PlayerSkills
 */
private $playerSkills;

最后,您可以将方法编码为自动同步反面,如下所述:http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#picking-owning-and-inverse-side