2017-05-26 80 views
2

我需要驗證用戶通過電子郵件:使用UniqueEntity外部實體的,沒有形式

private function validate($value): bool 
{ 
    $violations = $this->validator->validate($value, [ 
     new Assert\NotBlank(), 
     new Assert\Email(), 
     new UniqueEntity([ 
      'entityClass' => User::class, 
      'fields' => 'email', 
     ]) 
    ]); 

    return count($violations) === 0; 
} 

UniqueEntity約束拋出一個異常:

警告:get_class()預計參數1是對象,給出的字符串

看起來像ValidatorInterface::validate()方法的第一個參數等待實體與getEmail()方法對象,但它看起來很醜。

是否有任何優雅的方式來驗證字段的唯一性,只傳遞標量值到ValidatorInterface::validate()方法?

+1

您將需要您自己的自定義約束類。 –

回答

3

好像沒有內置Symfony的解決方案,做我想做的,所以我創建定製約束作爲Jakub Matczak建議。

UPD:當您發送表單來編輯實體時,此解決方案會引發驗證錯誤。爲了避免這種行爲,你需要手動改進這個約束。

約束:

namespace AppBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 

class UniqueValueInEntity extends Constraint 
{ 
    public $message = 'This value is already used.'; 
    public $entityClass; 
    public $field; 

    public function getRequiredOptions() 
    { 
     return ['entityClass', 'field']; 
    } 

    public function getTargets() 
    { 
     return self::PROPERTY_CONSTRAINT; 
    } 

    public function validatedBy() 
    { 
     return get_class($this).'Validator'; 
    } 
} 

驗證:

namespace AppBundle\Validator\Constraints; 

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

class UniqueValueInEntityValidator extends ConstraintValidator 
{ 
    /** 
    * @var EntityManager 
    */ 
    private $em; 

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

    public function validate($value, Constraint $constraint) 
    { 
     $entityRepository = $this->em->getRepository($constraint->entityClass); 

     if (!is_scalar($constraint->field)) { 
      throw new InvalidArgumentException('"field" parameter should be any scalar type'); 
     } 

     $searchResults = $entityRepository->findBy([ 
      $constraint->field => $value 
     ]); 

     if (count($searchResults) > 0) { 
      $this->context->buildViolation($constraint->message) 
       ->addViolation(); 
     } 
    } 
} 

服務:

services: 
    app.validator.unique_value_in_entity: 
     class: AppBundle\Validator\Constraints\UniqueValueInEntityValidator 
     arguments: ['@doctrine.orm.entity_manager'] 
     tags: 
      - { name: validator.constraint_validator } 

用例:

private function validate($value): bool 
{ 
    $violations = $this->validator->validate($value, [ 
     new Assert\NotBlank(), 
     new Assert\Email(), 
     new UniqueValueInEntity([ 
      'entityClass' => User::class, 
      'field' => 'email', 
     ]) 
    ]); 

    return count($violations) === 0; 
} 
0

對於此用途,我將在用戶類註釋中使用@UniqueEntity(fields = {「email」})。這種方式的種類:

/** 
* @ORM\Entity() 
* @ORM\Table(name="user") 
* @UniqueEntity(fields={"email"}) 
*/ 
+0

我正在使用實體內部沒有窗體和註釋的手動驗證。 – terron