一个实体上的多个@UniqueEntity注释


Multiple @UniqueEntity annotations at one entity

我有一个有两个唯一索引的实体。我喜欢向实体添加两个 UniqueEntity 约束以进行验证。

给定的实体:

/**
 * @ORM'Entity
 * @ORM'Table(name="sample", uniqueConstraints={
 *     @ORM'UniqueConstraint(columns={"user_id", "hash"}),
 *     @ORM'UniqueConstraint(columns={"user_id", "name"})
 * })
 * @UniqueEntity(fields={"user", "jobSearch"}, message="duplicate_hash")
 * @UniqueEntity(fields={"user", "name"}, message="duplicate_name")
 */
class SampleEntity
{
    // ...
}

问题是:只有最后@UniqueEntity才会得到尊重。因此,如果我切换 UniqueEntity 注释,则只有 username的重复键才能被识别,反之亦然,只有 userjobSearch

有没有解决方案可以用@UniqueEntity覆盖两个唯一的索引?

我通过使用自定义验证来解决这个问题。示例代码;
src/AppBundle/Validator/Constraint

<?php
// src/AppBundle/Validator/Constraints/UniqueCodeName.php
namespace AppBundle'Validator'Constraints;
use Symfony'Component'Validator'Constraint;
/**
 * @Annotation
 */
class UniqueCodeName extends Constraint
{
    public $message = "must have a unique code and name.";
    public function validatedBy()
    {
        return 'code_name';
    }
}

<?php
// src/AppBundle/Validator/Constraints/UniqueCodeName.php
namespace AppBundle'Validator'Constraints;
use Doctrine'ORM'EntityManager;
use Symfony'Component'Validator'Constraint,
    Symfony'Component'Validator'ConstraintValidator;
/**
 * @Annotation
 */
class UniqueCodeNameValidator extends ConstraintValidator
{
    private $entityManager;
    public function __construct(EntityManager $em) 
    {
        $this->entityManager = $em;
    }
    public function validate($value, Constraint $constraint)
    {
        $formCampaign = $this->context->getRoot()->getData();
        $code_name = $formCampaign->getClient()->getCode().$formCampaign->getCode();
        $campaigns = $this->entityManager->getRepository('AppBundle:Campaign')->findBy(
            [
                'code' => $code_name, 
                'name' => $formCampaign->getName()
            ]
        );
        if ($campaigns) {
            $this->context->buildViolation($constraint->message)
                ->addViolation();
        }
    }
}

约束的服务声明;

services:
    validator.unique.campaign_code_name:
            class: AppBundle'Validator'Constraints'UniqueCodeNameValidator
            tags:
                - { name: validator.constraint_validator, alias: code_name }
        arguments: ["@doctrine.orm.entity_manager"]

实体类示例;

<?php // src/AppBundle/Enitiy/Campaign.php
namespace AppBundle'Entity;
use AppBundle'Validator'Constraints as AppAssert;
use Doctrine'ORM'Mapping as ORM,
    Doctrine'Common'Collections'ArrayCollection;
use Symfony'Bridge'Doctrine'Validator'Constraints'UniqueEntity,
    Symfony'Component'Validator'Constraints as Assert;
use 'DateTime;
/**
 * Campaign
 *
 * @ORM'Table(name="campaign")
 * @ORM'Entity(repositoryClass="AppBundle'Entity'CampaignRepository")
 * @UniqueEntity(fields={"code", "name"})
 */
class Campaign 
{
    // other stuff
    /**
     * @var string
     *
     * @ORM'Column(name="code", type="string", length=255, unique=true)
     */
    private $code;
    /**
     * @var string
     *
     * @ORM'Column(name="name", type="string", length=255, unique=true)
     */
    private $name;
    /**
     * Get code
     *
     * @Assert'Length(min=2, max=11, groups={"create", "update"})
     * @Assert'Regex(pattern="/'d/", match=true, message="Code must be numeric", groups={"create", "update"})
     * @Assert'NotBlank(groups={"create", "update"})
     * @AppAssert'UniqueCodeName(groups={"create", "update"})
     * @return string
     */
    public function getCode()
    {
        return $this->code;
    }
}

我想创建一个可以容纳n个其他验证器的ChainValidator

/**
 * @ORM'Entity
 * @ORM'Table(name="sample", uniqueConstraints={
 *     @ORM'UniqueConstraint(columns={"user_id", "hash"}),
 *     @ORM'UniqueConstraint(columns={"user_id", "name"})
 * })
 * @Chain(constraints={
 *     @UniqueEntity(fields={"user", "hash"}, message="duplicate_hash"),
 *     @UniqueEntity(fields={"user", "name"}, message="duplicate_name")
 * })
 */
class SampleEntity
{
    // ...
}

这样就可以向一个实体添加 nUniqueEntity验证器。

当我用谷歌搜索它以了解其他人是否已经有了这个想法时。我找到了这个要点:https://gist.github.com/rybakit/4705749 基本上正是我所需要的,最终以非常相似的方式实现。