Doctrine在两列中阻止相同的特定值对

时间:2015-02-23 11:22:31

标签: php symfony doctrine-orm

我有一个Doctrine的实体Cart,其中包含以下两列:

  • $user(引用用户实体的ManyToOne列)
  • $status(包含两个可能值的字符串字段:pendingcompleted

...和我必须阻止同一用户的两个“待处理”购物车

我怎么能这样做?

UniqueConstraint不是解决方案,因为用户必须能够拥有两个或更多已完成的购物车,但只有一个购物车。

另一方面,我可以实现一个prePersist侦听器并在插入之前检查重复值,但我不喜欢这个解决方案,因为我不想对数据库进行额外的查询

任何解决方案?

1 个答案:

答案 0 :(得分:1)

最后,按照建议和Symfony documentation我选择了这个解决方案:

约束类

<?php  
namespace MyBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 */
class UniquePendingCart extends Constraint
{
    public $message = 'Only one pending cart by user';

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

    public function validatedBy()
    {
        return 'my.validator.unique_pending_cart';
    }
}

验证程序服务 注入我的CartRepository服务:

my.validator:
    class: AppBundle\Validator\Constraints\UniquePendingCartValidator
    arguments:
       - @my.cart_repository
    tags:
        - name: validator.constraint_validator
        - alias: my.validator.unique_pending_cart

约束验证器

<?php
namespace MyBundle\Validator\Constraints;
use Doctrine\Common\Persistence\ObjectRepository;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

use Bshop\AppBundle\Model\Interfaces\OrderInterface;

class UniquePendingCartValidator extends ConstraintValidator
{
    protected $repository;

    public function __construct(ObjectRepository $repository)
    {
        $this->repository = $repository;
    }

    public function validate($value, Constraint $constraint)
    {
        if (!$constraint instanceof UniquePendingCart) {
            throw new UnexpectedTypeException($constraint, 
                __NAMESPACE__.'\UniquePendingCart');
        }

        $isValid = $this->isStatusValid($value);

        if (!$isValid) {
            $this->context->buildViolation($constraint->message)
                ->addViolation();
        }
    }

    protected function isStatusValid($cart)
    {
        // use repository to find another possible pending cart 
        return true;
    }
}

然后在我的Cart实体

中应用约束
<?php
use Doctrine\ORM\Mapping as ORM;
use MyBundle\Validator\Constraints as MyAssert;

/**
 * @ORM\Entity
 * @MyAssert\UniquePendingCart
 */
class Cart {
    // ...
}

现在,我可以验证$ cart并验证它是否有效......

$cart = // my cart

$validator = $this->get("validator");
$errors = $validator->validate($cart);

if (0 !== count($errors)) {
    // ops, exception...
}