Я новичок в Symfony 4 и Doctrine, так что, возможно, я слишком многого ожидаю от Domrine ORM, но тот факт, что я не могу найти подходящую документацию, чтобы сообщить мне в любом случае, сводит меня с ума!
Ошибка
SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: skill.id
Сводка Я создал отношения ManyToMany между моим игроком и сущностями навыков.Каждый из этих объектов имеет свой идентификатор, установленный вручную, потому что они поступают из внешнего API.Я собираю данные в PlayerController, который очищает сторонний API для локального кэширования данных в моей БД.
Код, который я написал, позволяет сохранять (кэшировать) сторонние данные в моей базе данных.если умение, которое я добавляю, еще не было добавлено в базу данных.Однако, если я пытаюсь добавить другого игрока, который делится этим навыком, вся транзакция завершится неудачей, потому что он не сможет добавить навык снова из-за ограничения уникального идентификатора.Я полностью понимаю это, но я думал, что Doctrine ORM был достаточно умен, чтобы просто создать запись в соединительной таблице и игнорировать уже существующий навык.
Ожидаю ли я слишком много от Doctrine, и если да, то есть ли какие-либо услуги или помощники?чтобы вытащить меня из этой ситуации, не написав кучу кода.
PlayerController выполняет это действие для сохранения данных:
private function persistPlayer($data){
$player = new Player($data); //Player __construct entity extracts + assigns data
foreach ($data->skills as $rawSkill) {
$skill = new Skill($rawSkill);
$player->addSkill($skill);
}
}
$this->entityManager->persist($player);
try {
$this->entityManager->flush();
} catch (\Exception $e) {
error_log($e->getMessage());
}
return $player;
}
Мои аннотации Entities выглядят так (и были созданы с использованиемкоманда bin/console make:entity
:
class Player
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Skill", inversedBy="skill",cascade={"persist"})
*/
private $skill;
public function __construct($data)
{
$this->ability = new ArrayCollection();
$this->setId($data->id);
}
public function addSkill(Skill $skill): self
{
if (!$this->skill->contains($skill)) {
$this->skill[] = $skill;
}
return $this;
}
//.... more code
}
И мой объект Skill:
/**
* @ORM\Entity(repositoryClass="App\Repository\SkillRepository")
*/
class Skill
{
/**
* @var integer $id
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\Player", mappedBy="skill" ,cascade={"persist"})
*/
private $skill;
public function __construct($data)
{
$this->ability = new ArrayCollection();
$this->setId($data->id);
}
public function setId($id)
{
return $this->id = $id;
}
//...more code
}
Моя таблица соединений создается с использованием следующего синтаксиса:
CREATE TABLE player_skill (player_id INTEGER NOT NULL, skill_id
INTEGER NOT NULL, PRIMARY KEY(player_id, skill_id))