Issue 1:
@stof @weaverryan @fabpot @totophe @genexp @rquadling @nud I am wondering if Symfony 3 has fixed the problem with unique constraints on super- and subclasses since it does not work for me...

For example, I have 2 sub-entities that are derived from an abstract parent entity and I gave the parent 2 unique constraints like this:

/**
* User
*
* @ORM\Table(
* name="user",
* indexes={
* @ORM\Index(name="user_fn_ix", columns={"first_name"}),
* @ORM\Index(name="user_ln_ix", columns={"last_name"}),
* @ORM\Index(name="user_phone_ix", columns={"phone_number"}),
* }
* )
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({
* "courier": "AppBundle\Entity\User\Courier",
* "client": "AppBundle\Entity\User\Client",
* })
* @ORM\Entity(repositoryClass="AppBundle\Repository\User\UserRepository")
* @UniqueEntity(fields={"email"})
* @UniqueEntity(fields={"phoneNumber"})
* @Serializer\ExclusionPolicy("all")
* @Serializer\Discriminator(field="type", map={
* "courier": "AppBundle\Entity\User\Courier",
* "client": "AppBundle\Entity\User\Client",
* })
* @Vich\Uploadable()
*/
abstract class AbstractUser implements UserInterface { ... }
*/

There are 2 subclasses that are derived from the superclass:

/**
* Client
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\User\ClientRepository")
* @Serializer\ExclusionPolicy("all")
*/
class Client extends AbstractUser {...}

/**
* Courier
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\User\CourierRepository")
* @UniqueEntity(fields={"email"}, groups={"registration", "profile"})
* @UniqueEntity(fields={"phoneNumber"}, groups={"registration", "profile"})
* @Serializer\ExclusionPolicy("all")
*/
class Courier extends AbstractUser { ... }

I created a form type for Courier

class CourierType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('avatarFile', FileType::class, ['required' => true])
->add('firstName', TextType::class, ['required' => true])
->add('lastName', TextType::class, ['required' => true])
->add('email', EmailType::class, ['required' => true])
->add('password', PasswordType::class, ['required' => true])
->add('phoneNumber', PhoneNumberType::class, [
'widget' => PhoneNumberType::WIDGET_COUNTRY_CHOICE,
'country_choices' => ['US'],
'preferred_country_choices' => ['US'],
'default_region' => 'US',
'required' => true,
])
->add('address', TextType::class, ['required' => true])
->add('zipCode', TextType::class, ['required' => true])
->add('biography', TextareaType::class, ['required' => true])
->add('vehicleType', TextType::class, ['required' => true])
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Courier::class,
'validation_groups' => ['Default', 'registration'],
]);
}

public function getName()
{
return 'courier';
}
}

Validation Code:

class AppController extends Controller
{
public function indexAction(Request $request)
{
$form = $this->createForm(CourierType::class, new Courier());
$form->handleRequest($request);

if ($form->isValid()) {
echo 'yes';
} else {
echo 'invalid';
}
}
}

Running the controller always gives me 'yes' even if I pass a duplicate email or phone number. This means the @UniqueConstraint constraints are not working.

I thought this should be fixed now as this issue has been raised by many.

What's wrong with the code?

Issue 2:
Currently, the UniqueEntity constraint can fail when used on an inherited Entity, depending on where the validated field was declared in the Inheritance chain. Let me give you an example, suppose we have defined the following classes, where both Student and Teacher extend Person and we have used Doctrine's Class Table Inheritance:

<?php

Class Person
{
/**
* @UniqueEntity("name")
*/
private $name;
}

Class Student extends Person { }

Class Teacher extends Person { }

Now let's insert a new Teacher named "Fabien", the validator kicks in, see that no Teacher with that name exists and "Fabien" is happily inserted on the database (inside the person table).

Trying to insert another Teacher with the same name works as expected, stating that our unique constraint was violated.

Now, if we try to insert a new Student whose name is "Fabien" as well the validator fails to do its work, letting this violation pass unseen and then when Doctrine tries to persist the new Student (assuming your name is a unique field, which probably should) the database will yell back at you saying that another record with the same name already exists in the person table.

This happens because the validator uses the repository of the entity in which the validation was triggered, not the repository in which the field was defined. So a SQL similar to this is generated:

SELECT * FROM student INNER JOIN person ON student.id = person.id WHERE person.name = 'Fabien'

And because of the fact that no Student with the name "Fabien" exists (we have added a Teacher with the name "Fabien") the validation will not work properly.

I'm currently working on a fix for this issue so a PR will follow shortly.