Symfony 4.1: проверка уникальности на ArrayCollection - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть родительская сущность Product, как может быть во многих Family.

Свойство Family отображается как CollectionType.Цель состоит в том, чтобы создать столько семейств, сколько мы хотим, но имя каждой семьи должно быть уникальным для продукта.

Это прекрасно работает, когда у меня есть данные в таблице семейства;но когда он пуст и я добавляю два семейства для своего продукта сразу, с тем же именем, @UniqueEntity не срабатывает;в противном случае реагирует ORM uniqueConstraints.

Возникла исключительная ситуация при выполнении 'INSERT INTO family (name, max_product, обязательный, create_at, updated_at, Promotion_id) VALUES (?,?,?,?,?,?) 'с параметрами ["toto", 1, 0, "2018-12-06 14:54:13", "2018-12-06 14:54:13", 1]:

Ниже приведен образец моих потребностей:

/**
 * @var Family[]|ArrayCollection
 *
 * @ORM\OneToMany(targetEntity=Family::class, mappedBy="product", fetch="LAZY", cascade={"persist", "remove"}, orphanRemoval=true)
 * @ORM\OrderBy({"id" = "ASC"})
 * @Assert\Valid
 */
private $families;

И

/**
 * @ORM\Entity(repositoryClass=ProductCollectionFamilyRepository::class)
 * @ORM\Table(name="product_collection_family",
 *     indexes={@ORM\Index(name="IDX_FAMILY_NAME", columns={"name"})},
 *     uniqueConstraints={
 *        @ORM\UniqueConstraint(columns={"promotion_id", "name"})
 *    }
 * )
 *
 * 2.5.4.5RG02
 *
 * @UniqueEntity(
 *     fields={"product", "name"},
 *     errorPath="name",
 *     message="backend.error.label.family.unique_entity"
 * )
 */
class Family
{
    use TimestampableEntity;
    use ProductCollectionTrait;

    /**
     * @var int
     *
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=100)
     * @Assert\NotBlank
     * @Assert\Length(min="1", max="100", minMessage="backend.error.label.short", maxMessage="backend.error.label.long")
     */
    private $name;

   /**
    * @var Product
    *
    * @ORM\ManyToOne(targetEntity=Product::class, inversedBy="families", fetch="LAZY")
    * @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=true)
    * @Assert\NotBlank
    */
   private $product;
}

Есть идеи?

1 Ответ

0 голосов
/ 17 января 2019

Для этого я просто создаю функцию обратного вызова assert, которая проверяет элементы в коллекции массивов, а затем создает нарушение.

/**
 * @Assert\Callback
 *
 * @param ExecutionContextInterface $context
 * @param $payload
 */
public function validate(ExecutionContextInterface $context, $payload)
{
    $productFamilies = clone $this->getProductFamilies();
    $productFamiliesFiltered = $this->getProductFamilies()->filter(function ($currentProductFamily) use ($productFamilies) {
        // Remove current family from original collection
        $productFamilies->removeElement($currentProductFamily);
        foreach ($productFamilies as $data) {
            //we have same name ?
            if ($currentProductFamily->getName() === $data->getName()) {
                return true;
            }
        }

        return false;
    });

    if (0 !== $productCollectionFiltered->count()) {
        $context->buildViolation('backend.error.label.product_family.unique_entity')
            ->atPath('productFamilies')
            ->addViolation();
    }
}
...