I have an entity Supplier that looks like this.
<?php
**
* @ORM\Entity(repositoryClass=SupplierRepository::class)
* @UniqueEntity("siretNumber",repositoryMethod="getSupplierByPerimeter", message="Le numéro de SIRET est déjà utilisé.")
*/
class Supplier
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @Assert\NotBlank(allowNull=true)
* @Assert\Regex(pattern = "/^[0-9]*$/", message="Seul les chiffres sont autorisés.")
* @Assert\Length(
* min=14,
* max=14,
* exactMessage = "Le numéro de SIRET doit faire exactement 14 chiffres (SIREN (9) et NIC (5))"
* )
* @ORM\Column(type="string", length=14, nullable=true, unique=true)
*/
private $siretNumber;
* @ORM\ManyToOne(targetEntity=Perimeter::class, inversedBy="suppliers")
* @ORM\JoinColumn(nullable=false)
*/
private $perimeter;
}
Here I want to check if the $siretNumber is unique BUT ONLY if the $perimeter already have a Supplier associated with this siretNumber. Meaning that two perimeter can have the same Supplier with the same siretNumber but that one Perimeter can have only one unique siretNumber for each of its suppliers.
I tried to use the repositoryMethod like so:
The method:
<?php
namespace App\Repository;
use App\Entity\Supplier;
use App\Repository\PerimeterRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Security;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
/**
* @method Supplier|null find($id, $lockMode = null, $lockVersion = null)
* @method Supplier|null findOneBy(array $criteria, array $orderBy = null)
* @method Supplier[] findAll()
* @method Supplier[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SupplierRepository extends ServiceEntityRepository
{
private $security;
private $perimeterRepository;
public function __construct(ManagerRegistry $registry, Security $security,PerimeterRepository $perimeterRepository)
{
parent::__construct($registry, Supplier::class);
$this->security = $security;
$this->perimeterRepository = $perimeterRepository;
}
/**
* @return Supplier[] Returns an array of Supplier objects
*/
public function getSupplierByPerimeter()
{
$perimeter = $this->perimeterRepository->findOneBy(["label" => $this->security->getUser()->getOptions()["perimeter"]]);
return $this->createQueryBuilder('s')
->where('s.perimeter = :perimeter')
->setParameter('perimeter', $perimeter)
->getQuery()
->getResult()
;
}
The problem is that UniqueEntity seems to still check in all the Supplier table and not in the array return by getSupplierByPerimeter() so I'm still geting the validation error even if the siretNumber is associated with another Perimeter and not the current Perimeter while creating a new supplier.
Maybe I'm not using the repositoryMethod right but I don't know otherwise how to do what I want.
Does someone have an idea ?
You can use the UniqueEntity constraint on multiple fields.
**
* @ORM\Entity(repositoryClass=SupplierRepository::class)
* @UniqueEntity(
* fields={"siretNumber", "perimeter"},
* errorPath="siretNumber",
* message="Le numéro de SIRET est déjà utilisé."
* )
*/
class Supplier
{
}
This constraint will enforce that the combination value (siretNumber & perimeter) is unique. If I understand your issue properly you do not need to create a custom method in your repository.
If you need to require two fields to be individually unique (e.g. a unique siretNumber and a unique perimeter), you use two UniqueEntity entries, each with a single field.