获取实体列表,然后将它们设置为多对多关系

Fetch list of entities then set them in many to many relation

我在项目中使用了学说。

我得到了一个classCard

class Card implements \JsonSerializable
    {

    /**
     * @ORM\Id
     * @ORM\Column(type="string")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $sign;

    /**
     * @ORM\Column(type="string", length=10)
     */
    private $number;

   /**
     * Card constructor.
     *
     * @param $sign
     * @param $number
     */
    public function __construct($sign, $number)
    {
        $this->sign = $sign;
        $this->number = $number;

        $this->id = \sprintf('%s_%s', $sign, $number);
    }
}

以及包含 Card

的 class CardPicker
class CardPicker
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * Card that could be picked.
     *
     * Many CardPicker have Many Card.
     *
     * @ManyToMany(targetEntity="Card", cascade={"persist", "remove"})
     * @JoinTable(name="available_picker_cards",
     *     joinColumns={@JoinColumn(name="card_picker_id", referencedColumnName="id")},
     *     inverseJoinColumns={@JoinColumn(name="card_id", referencedColumnName="id")}
     * )
     */
    private $availableCards;

public function setCards(array $cards): void
    {
        $this->availableCards = new ArrayCollection($cards);
    }
}

我在我的数据库中保存了一些卡片。我想初始化我的 CardPicker。所以我写了这个方法:

 public function initCardPicker(): CardPicker
    {
        // fetch all wanted cards and put them in CardPicker
        $cards = $this->cardRepository->findAll();

        $cardPicker = new CardPicker();

        $cardPicker->setCards($cards);

        return $this->repository->save($cardPicker);
    }

但我收到此错误消息:SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: card.id (500 Internal Server

似乎当我保存 CardPicker 时,它会尝试 re-persist 我的卡片,这在我的系统中应该是唯一的。

我是不是做错了什么映射?

编辑

存储库:

/**
 * @method CardPicker|null find($id, $lockMode = null, $lockVersion = null)
 * @method CardPicker|null findOneBy(array $criteria, array $orderBy = null)
 * @method CardPicker[]    findAll()
 * @method CardPicker[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CardPickerRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, CardPicker::class);
    }

    /**
     * Save cardPicker and return it.
     *
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function save(CardPicker $picker): CardPicker
    {
        $this->_em->persist($picker);
        $this->_em->flush();
        $this->_em->clear();

        return $picker;
    }
}

@grenierj 我创建了 类,他们为我工作。

创建实体后执行

php bin/console doctrine:migration:diff
php bin/console doctrine:migration:migrate

config/services.yaml

    App\Repository\CardRepository:
        arguments:
            - '@doctrine'

    App\Entity\CardPicker:
        arguments:
            - '@doctrine'
            - 'App\Repository\CardRepository'

App/Entity/Card.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CardRepository")
 */
class Card
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="string")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $sign;

    /**
     * @ORM\Column(type="string", length=10)
     */
    private $number;

    /**
     * Card constructor.
     *
     * @param $sign
     * @param $number
     */
    public function __construct($sign, $number)
    {
        $this->sign = $sign;
        $this->number = $number;

        $this->id = \sprintf('%s_%s', $sign, $number);
    }

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @param string $id
     * @return Card
     */
    public function setId(string $id): Card
    {
        $this->id = $id;
        return $this;
    }
}

App/Entity/CardPicker.php

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CardPickerRepository")
 */
class CardPicker
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * Card that could be picked.
     *
     * Many CardPicker have Many Card.
     *
     * @ORM\ManyToMany(targetEntity="Card", cascade={"persist", "remove"})
     * @ORM\JoinTable(name="available_picker_cards",
     *     joinColumns={@ORM\JoinColumn(name="card_picker_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="card_id", referencedColumnName="id")}
     * )
     */
    private $availableCards;

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

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param mixed $id
     * @return CardPicker
     */
    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getAvailableCards()
    {
        return $this->availableCards;
    }

    /**
     * @param mixed $availableCards
     * @return CardPicker
     */
    public function setAvailableCards(array $availableCards)
    {
        $this->availableCards = $availableCards;
        return $this;
    }

    public function addAvailableCard(Card $card)
    {
        if (!$this->availableCards->contains($card)) {
            $this->availableCards->add($card);
        }
    }

    public function removeAvailableCard(Card $card)
    {
        $this->availableCards->removeElement($card);
    }
}

App/Repository/CardPickerRepository.php

<?php

namespace App\Repository;

use App\Entity\CardPicker;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;

/**
 * @method CardPicker|null find($id, $lockMode = null, $lockVersion = null)
 * @method CardPicker|null findOneBy(array $criteria, array $orderBy = null)
 * @method CardPicker[]    findAll()
 * @method CardPicker[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CardPickerRepository extends ServiceEntityRepository
{
    protected $cardRepository;

    public function __construct(ManagerRegistry $registry, CardRepository $cardRepository)
    {
        $this->cardRepository = $cardRepository;
        parent::__construct($registry, CardPicker::class);
    }

    public function initCardPicker(): CardPicker
    {
        $em = $this->getEntityManager();
        $cards = $this->cardRepository->findAll();

        $picker = new CardPicker();
        $picker->setAvailableCards($cards);

        $em->persist($picker);
        $em->flush();

        return $picker;
    }
}

App/Repository/CardRepository.php

<?php

namespace App\Repository;

use App\Entity\Card;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;

/**
 * @method Card|null find($id, $lockMode = null, $lockVersion = null)
 * @method Card|null findOneBy(array $criteria, array $orderBy = null)
 * @method Card[]    findAll()
 * @method Card[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CardRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Card::class);
    }
}