I have a patner, a buyer and an admin class that inherit a user class
When I want to add a partner, the validator do not work
* @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"})
If I choose a username to a "partner" that is already in database, it shows me the right validation error. But if I choose the username of a "buyer" which is already in the database, there is no verification, and have a unique field error in my databases.
Class User
<?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 ...
}
Class Partner
<?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 ...
}
Class Buyer
<?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 ...
}
This is an old unanswered question, however people still might face this issue. And this might help and save their time.
The problem is that UniqueEntityValidator by default takes only current (the one which is checking) entity's repository. In other words, if you submit Partner, it checks only Partner entries. It doesn't take into account other entites, such as Buyer or User in your "single_table" inheritance mapping.
To solve your problem, you can just add to your annotation entityClass
attribute with your parent class name:
@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")
This part entityClass="Antho\Test\CoreBundle\Entity\User" actually solves your problem.
In this case validator will go through all your user entries (including its child entries too).
My two cents. Not pretend to be the right answer.
Remove all unneeded @Table
from the subclasses and make fields visible (protected
). I did quite the same (with Symfony 2.0.x) and it works like a charm.
It's slightly different from your code, here a tag (or a keyword) name is unique for each user. But you can test it anyways:
/**
* @ORM\Entity
* @ORM\Table(
* name="meta",
* uniqueConstraints={
* @ORM\UniqueConstraint(columns={"name", "user_id", "type"})
* },
* indexes={
* @ORM\index(columns={"description"}),
* @ORM\index(columns={"type"})
* }
* )
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({"tag" = "Tag", "keyword" = "Keyword"})
* @UniqueEntity(fields={"name", "user"})
*/
abstract class Meta
{
protected $name;
protected $user;
}
Child classes:
/**
* @ORM\Entity
*/
class Tag extends Meta { }
/**
* @ORM\Entity
*/
class Keyword extends Meta { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With