Symfony 4.1: проверка UniqueEntity на ArrayCollection

У меня есть родительский продукт, как можно во многих семьях.

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

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

An exception occurred while executing 'INSERT INTO family (name, max_product, required, created_at, updated_at, promotion_id) VALUES (?, ?, ?, ?, ?, ?)' with params ["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;
}

Любые идеи ?

использование UniqueEntity в 2-х полях делает его уникальным, но в двух полях, а не в одном, поэтому, если вы введете продукт A, назовете B, продукт A, имя C, ограничение не сработает. Разве это не твоя проблема?

Robert 08.01.2019 12:00

Но это не ошибка uniqueEntity. Сообщение об ошибке уникального объекта должно иметь вид SQLSTATE [23000]: Нарушение ограничения целостности: 1062 Повторяющаяся запись

hous 08.01.2019 12:04

@hous Действительно, я забыл часть сообщения, я тоже получил это сообщение: SQLSTATE [23000]: Нарушение ограничения целостности: 1062 Повторяющаяся запись «7-test» для ключа «UNIQ_E346EBFE139DF1945E237E06»

benjy80 09.01.2019 14:01

@Robert Проблема возникла, когда я добавлял сразу две или более семьи (это форма CollectionType). Цель состоит в том, чтобы у продукта не было одинакового названия семейства. Когда я добавлял их по одному, все в порядке; но не тогда, когда я пробую все сразу.

benjy80 09.01.2019 14:05

тогда вы можете использовать проверку формы, не так ли? :)

Robert 09.01.2019 16:00

@Robert, я попробую с помощью настраиваемого обратного вызова проверки, чтобы проверить дважды в коллекции массивов. Но моей целью было использовать инструменты, предоставляемые фреймворком.

benjy80 10.01.2019 17:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
6
342
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для этого я просто создаю функцию обратного вызова 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();
    }
}

Другие вопросы по теме