Доктрина запрещает одну и ту же конкретную пару значений в двух столбцах

0

У меня есть Doctrine сущности Cart с этими двумя столбцами:

  • $user (столбец ManyToOne, ссылающийся на объект пользователя)
  • $status (поле строки с двумя возможными значениями: pending и completed)

... и я должен предотвратить две "отложенные" тележки для одного и того же пользователя.

Как я могу это сделать?

UniqueConstraint не является решением, поскольку пользователь должен иметь две или более завершенных тележки, но одну только ожидающую корзину.

С другой стороны, я мог бы реализовать прослушиватель prePersist и проверять дубликаты значений перед вставками, но мне не нравится это решение, потому что я не хочу делать дополнительные запросы к базе данных.

Любое решение?

  • 1
    Не проще ли проверить, есть ли у пользователя ожидающая корзина, прежде чем создавать новую?
  • 1
    также подумайте так, добавьте метод hasPending (), который проверяет это, и если (! $ e-> hasPending ()) {add ()}
Показать ещё 2 комментария
Теги:
doctrine2

1 ответ

1

Наконец, следуя рекомендациям и документации Symfony, я выбрал это решение:

Класс ограничений

<?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 = // my cart

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

if (0 !== count($errors)) {
    // ops, exception...
}
  • 0
    Вот что я имел в виду в своем комментарии: p Это требует небольших усилий, но гораздо более гибко. Это также уважает цель сущностей :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню