Symfony2 形式的交叉引用无法按预期工作

发布于 2025-01-05 03:35:50 字数 2267 浏览 0 评论 0 原文

这是我的第一个问题,所以请原谅任何错误 - 下次我会尽力避免它们。 ;-)

我已经为 FOSUserBundle 编写了一个自定义的 RegistrationFormType。除了捆绑包的默认字段之外,此表单还处理 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 它还应在表单生成器中添加引用..?或者这可能是教义注释中的问题?

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

This is my first question here, so please excuse any mistakes - I'll try to avoid them the next time. ;-)

I've written a custom RegistrationFormType for the FOSUserBundle. This form handles - in addition to the default fields of the bundle - a PlayerType. This PlayerType itself again contains a PlayerSkillsType. Here the classes:

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

(I've left out getters and setters and unimportant properties and methods.)
This is working fine so far, the form is shown and persisted. Now, my problem is, that after persisting the data, the PlayerSkills entity in the data is missing the reference back to the Player entity.

I think it's something that I need to tell the PlayerSkillsType that it shall also add the reference in the form builder..? Or maybe this is issue in the Doctrine annotations?

Any hint is very appreciated! :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

流云如水 2025-01-12 03:35:50

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

如果使用 $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-bidirection ) 。

它应该是这样的:

 /**
 * @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 .

The problem could come from the initialization of your data and/or doctrine mapping.

The form will create the data_class if none is passed using $form->setData.
When you submit the form and bind data, It will call $player>setPlayerSkills($playerSkill),
but it won't call $playerSkill->setPlayer($player);

Depending of the owning side of your oneToOne association, you should call one of the two methods so that Doctrine will be aware of this association ( http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#owning-side-and-inverse-side ).

Try to modify your annotation mapping in PlayerSkills to introduce the inversedBy information also ( http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#one-to-one-bidirectional ).

It should be something like this:

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

Same thing for the Player class:

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

Last, you can code your methods to automatically synchronize inverse side, as explained here: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#picking-owning-and-inverse-side .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文