我有一个Doctrine的实体Cart
,其中包含以下两列:
$user
(引用用户实体的ManyToOne列)$status
(包含两个可能值的字符串字段:pending
和completed
)...和我必须阻止同一用户的两个“待处理”购物车。
我怎么能这样做?
UniqueConstraint不是解决方案,因为用户必须能够拥有两个或更多已完成的购物车,但只有一个购物车。
另一方面,我可以实现一个prePersist侦听器并在插入之前检查重复值,但我不喜欢这个解决方案,因为我不想对数据库进行额外的查询
任何解决方案?
答案 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...
}