Symfony / Doctrine: вставка OneToMany приводит к пустому идентификатору

0

У меня есть два объекта, которые я пытаюсь применить отношение OneToMany/ManyToOne (в одной игре есть много GameContent).

Игра

/**
 * @ORM\OneToMany(targetEntity="GameContent", mappedBy="game")
 */
private $contents;

public function __construct()
{
    $this->contents = new ArrayCollection();
}

public function getContents()
{
    return $this->contents;
}

GameContent

/**
 * @ORM\ManyToOne(targetEntity="Game", inversedBy="contents")
 */
private $game;

И следующий код вставляет обе записи в соответствующие таблицы:

$game = $form->getData();
$content = new GameContent();
$content->setType('some type');
$game->getContents()->add($content);

$em = $this->getDoctrine()->getManager();
$em->persist($content);
$em->persist($game);
$em->flush();

Однако GameContent game_id вставляется как null:

INSERT INTO game_content (type, game_id) VALUES (?, ?)
Parameters: { 1: 'some type', 2: null }

Я также пробовал:

  • изменение порядка persist()
  • заменив $game->getContents()->add($content) на $game->addContents($content), выполнив $this->contents[] = $content;
  • удаление persist($content) и наличие cascade={"persist"} в игровом объекте.

Почему game_id вставляется как null?


Мое текущее решение:

$em = $this->getDoctrine()->getManager();

$game = $form->getData();
$em->persist($game);

$content = new GameContent();
$content->setType('some type');
$content->setGame($game);
$em->persist($content);

$em->flush();
Теги:
doctrine2
symfony-2.8

2 ответа

0
Лучший ответ

У вас есть 2 решения:

Сохранять детей в контролере

Без cascade={"persist"}

$em = $this->getDoctrine()->getManager();

// Get data
$game = $form->getData();

// Create new GameContent and hydrate
$content = new GameContent();
$content->setType('some type');

// Associate Game <> GameContent
$content->setGame($game);

// Persist GameContent
$em->persist($content);

// Persist Game and commit
$em->persist($game);
$em->flush();

Сохранять детей в каскаде

С cascade={"persist"} persist cascade={"persist"} в отношении OneToMany.

Добавьте в setGame(), чтобы принудительно установить связь:

$game->addContent($this);

И удалить persist:

$em = $this->getDoctrine()->getManager();

// Get data
$game = $form->getData();

// Create new GameContent and hydrate
$content = new GameContent();
$content->setType('some type');

// Associate Game <> GameContent
$content->setGame($game);

// Persist Game and commit
$em->persist($game);
$em->flush();

Я думаю, что ошибка также была связана с позиционированием сохраняющейся игры.

  • 0
    Ах, я пропустил $game->addContent($this); для того, чтобы каскадировать. Является ли любое решение в целом предпочтительным?
  • 0
    Кстати, позиционирование persist в игре не имело значения (см. Мой «обходной путь», который совпадает с вашим первым решением, но с persist в другом порядке).
0

В дополнение к принятому ответу, моим следующим шагом было создание формы для обработки данных GameContent, что привело к дальнейшим изменениям и некоторой упрощенной логике.

Я теперь setGame() в Game::addContent(), и поэтому я удалил $game->addContent($this); в GameContent::setGame().

Игра

/**
 * @var ArrayCollection
 * @ORM\OneToMany(targetEntity="GameContent", mappedBy="game", cascade={"persist"})
 */
private $contents;

public function __construct()
{
    $this->contents = new ArrayCollection();
}

public function getContents()
{
    return $this->contents;
}

public function addContent(GameContent $content)
{
    $this->contents->add($content);
    $content->setGame($this);

    return $this;
}

public function removeContent(GameContent $content)
{
    $this->contents->removeElement($content);

    return $this;
}

GameContent

/**
 * @ORM\ManyToOne(targetEntity="Game", inversedBy="contents")
 */
private $game;

public function setGame(Game $game)
{
    $this->game = $game;

    return $this;
}

/**
 * @return Game
 */
public function getGame()
{
    return $this->game;
}

Логика обработки форм в реальном времени будет выглядеть так:

$game = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($game);
$em->flush();

Дополнительную информацию можно найти по адресу: http://symfony.com/doc/2.8/form/form_collections.html (см. Доктрина: Каскадные отношения и сохранение "Обратная").

Ещё вопросы

Сообщество Overcoder
Наверх
Меню