【问题标题】:Use Symfony UniqueEntity with Doctrine将 Symfony UniqueEntity 与 Doctrine 一起使用
【发布时间】:2015-02-21 17:49:23
【问题描述】:

我正在尝试让 Symfony 的 UniqueEntity 验证器为我的 Doctrine 实体工作。 Symfony 验证器已经连接并工作,但是来自 Symfony\Bridge 的 UniqueEntity 更具挑战性,显示此错误:

PHP Fatal error:  Class 'doctrine.orm.validator.unique' not found in /app/vendor/symfony/validator/Symfony/Component/Validator/ConstraintValidatorFactory.php on line 46

看起来 ValidatorFactory 正在从 Symfony 容器请求 UniqueEntity 验证器,而我没有,因为我没有使用全栈 symfony。

我的实体如下所示:

<?php
namespace App\Model;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as AssertDoctrine;

/**
 * User
 *
 * @ORM\Table(name="users", uniqueConstraints={@ORM\UniqueConstraint(name="id_UNIQUE", columns={"id"}), @ORM\UniqueConstraint(name="username_UNIQUE", columns={"username"})})
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @AssertDoctrine\UniqueEntity("username")
 */
class User extends AbstractEntity
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="username", type="string", length=45, unique=true, nullable=false)
     * @Assert\Length(min=3, max=45)
     */
    protected $username;

    /** ... */
}

其中 AbstractEntity 是一个映射超类,包括为所有实体提供验证功能的 Trait:

<?php
namespace App\Model\Traits;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Validation;
use App\Utility\Exception\ConstraintViolationException;

/**
 * A trait enabling validation of Doctrine entities to ensure invalid entities
 * don't reach the persistence layer.
 */
trait ValidatorAwareTrait
{
    public function validate()
    {
        $validator = Validation::createValidatorBuilder()
            ->enableAnnotationMapping()
            ->getValidator();

        $violations = $validator->validate($this);

        // Count is used as this is not an array but a ConstraintViolationList
        if (count($violations) !== 0) {
            $message = $violations[0]->getPropertyPath() . ': ' . $violations[0]->getMessage();
            throw new ConstraintViolationException($message);
        }
        return true;
    }
}

【问题讨论】:

    标签: validation symfony doctrine unique


    【解决方案1】:

    参考:

    1. DoctrineBridge\Validator\Constraints\UniqueEntity
    2. Symfony\Component\Validator\Constraint

    几个月前我也遇到过同样的问题。

    简短回答:如果不使用某种类型的 DI,您将无法使用 UniqueEntity 验证器,该 DI 列出了 doctrine.orm.validator.unique 的服务并将其转换为 Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator

    长答案:您看到的错误消息是DoctrineBridge\Validator\Constraints\UniqueEntity 重新实现Symfony\Component\Validator\Constraint::validatedBy() 的结果。事实上,如果您查看DoctrineBridge\Validator\Constraints\UniqueEntity::validatedBy() 上面的评论,您会看到它声明“验证器必须定义为具有此名称的服务”,这导致该验证器预计将与 Symfony @987654329 一起使用@组件。

    不明显的是,错误消息中显示的服务名称实际上是在 Doctrine\DoctrineBundle\Resources\Config\Orm.xml 中定义的

    很抱歉没有提供orm.xmldbal.xml 配置文件的链接。我的声誉目前不允许这样做。

    【讨论】:

      【解决方案2】:
       $validator = Validation::createValidatorBuilder()
              ->setConstraintValidatorFactory($this->validatorFactory)
              ->enableAnnotationMapping()
              ->getValidator();
      
          $violations = $validator->validate($user);
      
          if (count($violations) !== 0) {
              $message = $violations[0]->getPropertyPath() . ': ' . $violations[0]->getMessage();
              throw new \Exception($message);
          }
      
          $this->entityManager->persist($user);
          $this->entityManager->flush();
      

      其中 $this->validatorFactory 是服务 '@validator.validator_factory'

      【讨论】:

      • 您能提供更多细节吗?你的答案主要是代码
      【解决方案3】:

      首先你应该检查你的 config.yml 中是否启用了验证:

      framework:
          validation:      { enable_annotations: true }
      

      接下来,确保在您的唯一注释中提供必需的属性 fields

      @AssertDoctrine\UniqueEntity(fields={"username"})
      

      最后,如果前面的步骤仍然失败,您可以在注解中提供自己独特的验证器服务(参见original service for reference),如下所示:

      @AssertDoctrine\UniqueEntity(fields={"username"}, 
      service="use.my.unique.validator.service") 
      

      您甚至可以通过此注释中的 em-选项提供实体管理器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        • 2021-10-01
        • 2016-07-16
        • 1970-01-01
        • 2018-03-26
        相关资源
        最近更新 更多