使用@UnityEntity注释对两个唯一字段进行约束?

huangapple go评论89阅读模式
英文:

Constraint on two unique fields using @UnityEntity annotation?

问题

我有一个名为Supplier的实体,看起来像这样。

/**
* @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;
}

在这里,我想要检查$siretNumber是否是唯一的,但仅当$perimeter已经与此siretNumber关联了Supplier时才是如此。这意味着两个perimeter可以有相同siretNumber的相同Supplier,但一个Perimeter只能为其每个供应商拥有一个唯一的siretNumber。

我尝试使用repositoryMethod,如下所示:

/**
* @UniqueEntity("siretNumber",repositoryMethod="getSupplierByPerimeter", message="Le numéro de SIRET est déjà utilisé.")
*/

方法:

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;

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;
   }

   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();
   }
}

问题是UniqueEntity似乎仍然在整个Supplier表中检查,而不是在getSupplierByPerimeter()返回的数组中检查,所以我仍然会得到验证错误,即使siretNumber与另一个Perimeter相关联而不是当前Perimeter在创建新供应商时。

也许我没有正确使用repositoryMethod,但我不知道其他如何实现我的需求。

有人有什么想法吗?

英文:

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:

  • @UniqueEntity("siretNumber",repositoryMethod="getSupplierByPerimeter", message="Le numéro de SIRET est déjà utilisé.")

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 ?

答案1

得分: 0

可以在多个字段上使用UniqueEntity约束

/**
* @ORM\Entity(repositoryClass=SupplierRepository::class)
* @UniqueEntity(
*     fields={"siretNumber", "perimeter"},
*     errorPath="siretNumber",
*     message="Le numéro de SIRET est déjà utilisé."
* )
*/
class Supplier
{

}

该约束将强制组合值(siretNumber和perimeter)是唯一的。如果我正确理解您的问题,您不需要在存储库中创建自定义方法。

如果您需要要求两个字段分别是唯一的(例如,唯一的siretNumber和唯一的perimeter),您可以使用两个UniqueEntity条目,每个条目只包含一个字段。

英文:

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.

huangapple
  • 本文由 发表于 2023年8月10日 16:17:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76873837.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定