Ошибка сохранения Entity с cascade в Doctrine в Symfony 5 — как избежать?
У меня есть сущность Game, она содержит коллекцию игроков Player - отношение OneToMany в ORM. Есть обратная связь от игрока к игре (поле $game). Каждому игроку соответствует один объект User - отношение ManyToOne, null=false, пользователь обязателен для каждого игрока. У одного пользователя может быть несколько игроков (по каждому игроку на сыгранную игру), обратной связи пока нет, не создал, так как нет необходимости.
Стоит задача сделать возможность в момент создания игры не только создавать игроков и пользователей, но и устанавливать пользователям контактные данные. Кроме того, если пользователь с заданным e-mail уже существует, требуется привязать существующего пользователя, а не создавать нового.
Сейчас я написал некоторый код, он работает, но только в случае новых e-mail адресов. Как только я пытаюсь подставить существующего игрока, код вылетает с одной из двух ошибок:
1. Ошибка Doctrine, "a new entity was found through the relationship App\Entity\Game#player that was not configured to cascade persist operations for entity App\Entity\Player". Действительно, для списка игроков в игре не установлена опция cascade. Если же добавить её, получаю ошибку номер 2
2. SQL Error: Duplicate unique identifier N (где N - целое число, равное id уже существующего пользователя в таблице users, которого я пытаюсь подставить в поле $user для нового игрока).
Если все пользователи создаются с нуля, ошибки нет. Ошибка вылетает в тот момент, когда я вызываю persist() для объекта $game после заполнения коллекции $players в отдельном методе и создания всех пользователей. Попытки вызывать persist() для объектов пользователей и игроков внутри того метода ничего в сущности не меняют.
Общий алгоритм моего кода:
1. Получить Symfony форму на вход, в форме есть две вложенных коллекции - lectures и players. Лекции не имеют вложенных сущностей, поэтому с ними куда как проще - к тому же, их нельзя переиспользовать повторно, всегда создаются новые.
2. Создать объект класса Game - это нужно для того, чтобы получить его числовой id, который затем будет использоваться в дефолтных логинах создаваемых пользователей
3. Очистить коллекцию $players, которая заполнена автоматически (предварительно сохранив её содержимое в массив) - если этого не сделать, получим ошибку, что поле $user равно null, а это запрещено constraint-ом.
4. В цикле пройтись по массиву ролей, создать игроков, для каждой роли получить контактные данные из специального аргумента метода (эти данные тоже есть в Symfony форме, но с атрибутом mapped =>false).
5. Для каждого игрока попытаться найти пользователя по переданному e-mail адресу. Если такого нет - создать, иначе получить из метода репозитория через QueryBuilder. Установить контактные данные пользователю, установить пользователя в поле $user у игрока.
6. Выйдя из этого метода, вызвать persist и flush для игры - тут происходит ошибка.
Что я делаю не так? Возможность переиспользовать пользователей - бизнес-требование. Я могу попробовать удалять пользователя, заново его создавать и ставить прежний id - но мне не нравится такое количество лишних операций.
Каждому игроку соответствует один объект User - отношение OneToOne, null=false, пользователь обязателен для каждого игрока. У одного пользователя может быть несколько игроков (по каждому игроку на сыгранную игру)