Symfony表单 - 具有2个电话唯一验证的客户端

时间:2018-04-15 06:37:17

标签: php symfony

我想同时验证表的唯一2列。我在2个独立的列上每个客户端有2个电话,如下所示:

/**
 * @ORM\Entity(repositoryClass="App\Repository\ClientRepository")
 * @ORM\Table(name="client", 
 *    uniqueConstraints={
 *        @UniqueConstraint(name="phone_second_phone_constraint", 
 *            columns={"phone", "second_phone"})
 *    })
 * @UniqueEntity("email")
 * @UniqueEntity("phone")
 * @UniqueEntity("second_phone")
 */
 class Client {

     /**
      * @ORM\Column(name="phone", type="phone_number", length=50, unique=true, nullable=true)
      * @AssertPhoneNumber(type="any")
      */
     protected $phone = null;

     /**
      * @ORM\Column(name="second_phone", type="phone_number", length=50, unique=true, nullable=true)
      * @AssertPhoneNumber(type="any")
      */
     protected $second_phone = null;
 }

我不想在任何专栏或任何客户端重复使用手机。

有关如何实现这一目标的任何想法吗?

谢谢和亲切的问候, 大卫M。

1 个答案:

答案 0 :(得分:1)

因此,如果我理解正确,您需要在phonesecond_phone中使用电话号码时无法重复使用。

因此,结合这两个字段的唯一键无法帮助您,因为当相同的电话号码出现在相同的确切字段中时,它只会违反唯一约束,例如phone = X和second_phone = Y you将能够保存phone = Y和second_phone = X。

为避免这种情况,您必须创建一个自定义约束,以检查数据库中是否已存在电话号码。

Here是有关如何在symfony中创建和使用约束的文档。

所以你的代码看起来像这样

您的自定义约束

use Symfony\Component\Validator\Constraint;

/**
* @Annotation
*/
class UniquePhoneNumber extends Constraint
{
    public $message = 'The phone number "{{ phoneNumber }}" is already in use.';
}

您的约束验证程序

use Doctrine\ORM\EntityManager;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UniquePhoneNumberValidator extends ConstraintValidator
{
    private $entityManager;

    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }        

    public function validate($phoneNumber, Constraint $constraint)
    {
        $client = $this->entityManager->getRepository(Client::class)->findByPhoneNumber($phoneNumber);

        if (!is_null($client)) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('{{ phoneNumber }}',$phoneNumber)
                ->addViolation();
        }
    }
}

您的客户端存储库中的某个地方

public function findByPhoneNumber(string $phoneNumber): ?Client
{
    $qb = $this->getEntityManager()->createQueryBuilder('c');
    $qb->select('c')
        ->where('c.phone = :phone OR c.second_phone = :phone')
        ->setParameter('phone',$phoneNumber)
        ->setMaxResults(1);

    return $qb->getQuery()->getOneOrNullResult();
}

然后在手机和validator上使用新的second_phone,关于如何执行此操作here是一个链接,这取决于您放置约束类的位置,但一般来说,必须这样做

  • 导入约束use App\Validator\Constraints as CustomAssert;
  • 如果您使用注释,请在字段@CustomAssert\UniquePhoneNumber
  • 上方添加注释

请注意,您必须为约束和验证器添加命名空间,如果将约束放在App \ Validator \ Constraints的其他文件夹中,则必须在实体文件中调整use语句