Bads123
Bads123

Reputation: 919

Symfony2 Unique Validation for multiple fields

I have two fields and want a unique validation on both of them combined. Meaning name and city combination should be unique. But validation is triggering only for name

Entity\Location:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: 
            fields: [name, city]
            message: "Location for given City Already Exists"

Upvotes: 0

Views: 1513

Answers (1)

Praveesh
Praveesh

Reputation: 1327

You will have to write a call back validation to accomplish this.The call back method will check whether there are any existing locations for the given combination of city and name and, if there exist any location, it will throw a form error. In this example. you will have to call the entity manager within the entity. So, the service container is passed along with the bundle and is then called.

In security.yml

Venom\ExampleBundle\Entity\Location:
constraints:
    - Callback:
        methods:   [isUniqueCityAndNameCombination]

In entity

use Symfony\Component\Validator\ExecutionContext;
use Venom\ExampleBundle;

public function isUniqueCityAndNameCombination(ExecutionContext $context)
{
    $city = $this->getCity();
    $name = $this->getName();
    //you will have to call the Entity repository within the entity
    $em = ExampleBundle::getContainer()->get('doctrine')->getEntityManager();
    $location = $em->getRepository('ExampleBundle:Location')->findByNameAndCity(
                                                               $city, $name);

   if($location) {
        $propertyPath = $context->getPropertyPath() . '.name';
        $context->setPropertyPath($propertyPath);
        $context->addViolation("Location for given City Already Exists", array(), null);
    }

    return;
}

In the repository

  public function dindByNameAndCity($city, $name)
 {
    $qb = $this->getEntityManager()->createQueryBuilder();
    $em = $this->getEntityManager();
    $qb->select('a')
            ->from('ExampleBundle:Location', 'a')
            ->andWhere('a.city = :city')
            ->andWhere('a.name = :name')
            ->setParameter('city', $city)
            ->setParameter('name', $name)
    ;
    $q = $qb->getQuery();
    $entity = $q->getOneOrNullResult();
return $entity;

}

In the bundle file, in this case ExampleBundle.php

 namespace Venom\ExampleBundle;

 use Symfony\Component\HttpKernel\Bundle\Bundle;
 use \Symfony\Component\DependencyInjection\ContainerInterface;

 class ExampleBundle extends Bundle
{
private static $containerInstance = null; 

public function setContainer(ContainerInterface $container = null) 
{ 
    parent::setContainer($container); 
    self::$containerInstance = $container; 
}

public static function getContainer() 
{ 
    return self::$containerInstance; 
}

}

Upvotes: 1

Related Questions