Doctrine不会在通过API POST创建的子实体中设置父引用

问题描述 投票:3回答:2

情况

我们正在使用JMS进行实体(de)序列化,使用Doctrine和FOSRestBundle开发基于Symfony 3构建的REST API。

在POST操作期间出现问题,我们使用一组新的子实体(玩家)创建一个新实体(Team)。正确反序列化JSON数据 - 创建一个Team对象,并将所有子实体反序列化为Team对象中的players-collection中的Player对象。

问题

反序列化后,Player对象没有Team-reference。因此,我们无法存储Player对象,因为所需的Team FK为空。

我们目前在PrePersist事件中“手动”设置了Player - > Team关系:

/**
 * @ORM\PrePersist
 */
public function doSetParentRelation()
{
    foreach ($this->getPlayers() as $player) {
        $player->setTeam($this);
    }
}

在Team.php中:

/**
 * @var \AppBundle\Entity\Player[]
 *
 * @ORM\OneToMany(targetEntity="Player", mappedBy="team", cascade={"persist"})
 * @Type("array<AppBundle\Entity\Player>")
 * @Groups({"create-version"})
 * @Assert\Valid(traverse="true")
 */
private $players;

在Player.php中:

/**
 * @var \AppBundle\Entity\Team
 *
 * @ORM\ManyToOne(targetEntity="Team", inversedBy="players", fetch="EAGER")
 * @ORM\JoinColumn(nullable=false)
 * @Exclude
 */
private $team;

我想知道是否有更优雅的方法。我们不需要将自定义PrePersist事件添加到通过API调用创建的OneToMany关系的每个实体,而是需要更全面的解决方法。

php symfony doctrine-orm fosrestbundle jmsserializerbundle
2个回答
1
投票

我们找到了一个适合我们的解决方案,并且不依赖于自定义的PrePersist事件。我们已经设置JMS来使用getter和setter而不是反射(de)序列化:

use JMS\Serializer\Annotation\AccessType;

/**
 * [...]
 * @AccessType("public_method")
 */
class Team
{
    [...]
}

然后我们添加了一个setPlayers()方法并更改了addPlayer()方法,以便在每个Player中设置team-reference。

/**
 * Set players
 *
 * @param Player[] $players
 */
public function setPlayers(array $players)
{
    foreach ($players as $player) {
        $this->addPlayer($player);
    }
}

/**
 * Add player
 *
 * @param Player $player
 */
public function addPlayer(Player $player)
{
    $this->players[] = $player;
    $player->setTeam($this);
}

0
投票

对于API的POST请求,我们使用表单来获取请求参数并创建实体或执行操作。 (注意,您总是必须在后端提交表单,因为用户没有。请参阅下面的submit方法调用。)

$yourEntity = new YourEntity();
$form = $this->createForm(YourFormType::class, $yourEntity)
             ->submit($request->request->all())
;

if ($form->isValid()) {
    // your entity logic
}

或者,根据您的帖子的内容,您可能需要先解码它。

$yourEntity = new YourEntity();
$form = $this->createForm(YourFormType::class, $yourEntity);
$data = json_decode($request->getContent(), true);
$form->submit($data);

if ($form->isValid()) {
    // your entity logic
}

与此以及常规形式的唯一区别在于,您永远不会使用$form->createView();在前端(通过树枝模板)创建表单。您只是始终捕获POST请求并将表单用作实体转换器。

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.