Ошибка проверки Symfony2 UniqueEntity с наследованием сущности

У меня есть патнер, покупатель и класс администратора, которые наследуют класс пользователя

Когда я хочу добавить партнера, валидатор не работает

 * @DoctrineAssert\UniqueEntity(fields="username", message="Ce nom d'utilisateur est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
 * @DoctrineAssert\UniqueEntity(fields="mail", message="Cette adresse mail est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})

Если я выберу имя пользователя для «партнера», который уже есть в базе данных, он покажет мне правильную ошибку проверки. Но если я выберу имя пользователя «покупателя», который уже есть в базе данных нет проверки и в моих базах данных есть уникальная ошибка поля.

Пользователь класса

<?php

namespace Antho\Test\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;

/**
 * Antho\Test\CoreBundle\Entity\User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="Antho\Test\CoreBundle\Entity\UserRepository")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({"user" = "User", "partner" = "Partner", "buyer" = "Buyer", "admin" = "Admin"})
 * @ORM\HasLifecycleCallbacks()
 * @DoctrineAssert\UniqueEntity(fields="username", message="Ce nom d'utilisateur est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
 * @DoctrineAssert\UniqueEntity(fields="mail", message="Cette adresse mail est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
 */
class User implements UserInterface
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $username
     *
     * @ORM\Column(name="username", type="string", length=255, unique=true)
     */
    private $username;

    /**
     * @var string $lastName
     *
     * @ORM\Column(name="last_name", type="string", length=255)
     */
    private $lastName;

    /**
     * @var string $firstName
     *
     * @ORM\Column(name="first_name", type="string", length=255)
     */
    private $firstName;

    /**
     * @var string $mail
     *
     * @ORM\Column(name="mail", type="string", length=255, unique=true)
     */
    private $mail;

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


    public function __construct()
    {
        if ($this->createdAt === null) {
            $this->createdAt = new \DateTime('now');
        }
        $this->isEnabled = true;
    }

    public function __toString()
    {
        return $this->username;
    }

    GETTER and SETTER ...
}

Партнер класса

<?php

namespace Antho\Test\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;

/**
 * Antho\Test\CoreBundle\Entity\Partner
 *
 * @ORM\Table(name="partner")
 * @ORM\Entity(repositoryClass="Antho\Test\CoreBundle\Entity\PartnerRepository")
 */
class Partner extends User
{
    /**
     * @ORM\OneToMany(targetEntity="Restaurant", mappedBy="partner", cascade={"remove", "persist"})
     */
    private $restaurants;

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


    public function __construct()
    {
        parent::__construct();
        $this->restaurants = new \Doctrine\Common\Collections\ArrayCollection();
        $this->isValid = false;
    }

    GETTER and SETTER ...
}

Покупатель класса

<?php

namespace Antho\Test\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;

/**
 * Antho\Test\CoreBundle\Entity\Buyer
 *
 * @ORM\Table(name="buyer")
 * @ORM\Entity(repositoryClass="Antho\Test\CoreBundle\Entity\BuyerRepository")
 */
class Buyer extends User
{
    /**
     * @var string $address
     *
     * @ORM\Column(name="address", type="string", length=255)
     */
    private $address;

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

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

    /**
     * @var boolean $newsletter
     *
     * @ORM\Column(name="newsletter", type="boolean")
     */
    private $newsletter;


    public function __construct()
    {
        parent::__construct();
        if ($this->newsletter === null) {
            $this->newsletter = false;
        }
    }

    GETTER and SETTER ...
}
13
задан anthofremion 8 February 2012 в 15:20
поделиться

1 ответ

Это - старый оставшийся без ответа вопрос, однако люди все еще могли бы столкнуться с этой проблемой. И это могло бы помочь и сэкономить их время.

проблема состоит в том, что UniqueEntityValidator по умолчанию берет только текущий (тот, который проверяет), репозиторий объекта. Другими словами, при представлении Партнера это проверяет только записи Партнера. Это не принимает во внимание другие объекты, такие как Покупатель или Пользователь в Вашем "single_table" отображении наследования.

Для решения проблемы можно просто добавить к аннотации entityClass атрибут с именем родительского класса:

@DoctrineAssert\UniqueEntity(fields="username", message="Ce nom d'utilisateur est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"}, entityClass="Antho\Test\CoreBundle\Entity\User")

Эта часть entityClass = "Antho\Test\CoreBundle\Entity\User" на самом деле решает Вашу проблему.

В этом блоке проверки допустимости случая пройдет все Ваши пользовательские записи (включая его дочерние элементы также).

0
ответ дан 2 December 2019 в 02:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: