Комбинированные ограничения и преобразователи данных

Я хотел бы сделать что-то похожее на то, что сделано в Как использовать Data Transformers. Но я хотел бы добавить процесс, и я не могу найти никакого примера.

В учебнике symfony преобразование данных связано с изменением номера проблемы на объект Issue. Это выполняется в reverseTransform() функции IssueToNumberTransformer

public function reverseTransform($number)
{
    if (!$number) {
        return null;
    }

    $issue = $this->om
        ->getRepository('AcmeTaskBundle:Issue')
        ->findOneBy(array('number' => $number))
    ;

    if (null === $issue) {
        throw new TransformationFailedException(sprintf(
            'An issue with number "%s" does not exist!',
            $number
        ));
    }

    return $issue;
}

Мы можем видеть, что если указан недопустимый номер проблемы, преобразование завершится неудачно, а функция выкинет a TransformationFailedException. В результате форма как ошибка с сообщением "Это значение недействительно". Было бы здорово персонализировать это сообщение.

Процесс преобразования данных выполняется до любой проверки (с ограничениями, применяемыми к полю), поэтому я не могу найти способ проверить номер проблемы перед тем, как ее преобразовать.

В качестве другого примера того, почему я должен проверять перед преобразованием, я использую MongoDB Document Manager для преобразования "Issue mongo id" в проблему (форма используется сервером REST API, поэтому я получаю идентификатор), Итак:

public function reverseTransform($id)
{
    if (!$number) {
        return null;
    }

    $issue = $this->dm
        ->getRepository('AcmeTaskBundle:Issue')
        ->find(new \MongoId($id))
    ;

    if (null === $issue) {
        throw new TransformationFailedException(sprintf(
            'An issue with number "%s" does not exist!',
            $number
        ));
    }

    return $issue;
}

Здесь, если идентификатор, который я получаю в моей форме API, не сформирован как правильный MongoID, клиент получит 500. Поэтому я хочу проверить, перед преобразованием, если полученный идентификатор верен, потому что если это не так, фатальная ошибка. И если я управляю всеми случаями в моем преобразовании, например, проверяя, является ли $id правильным, это похоже на то, что я делаю валидацию в трансформаторе, и это неверно.

Мой вопрос: есть ли способ применить ограничения перед преобразованием данных? или есть ли способ добавить ограничение сложения в форму при неудачной трансформации?

Ответ 1

Это похоже на обходной путь, однако я предлагаю написать класс, который представляет "недопустимую проблему", чтобы персонализировать ошибку.

class InvalidIssue extends Issue
{
    public $message = 'This issue is invalid';

    public function __construct($message = null)
    {
        if (null !== $message) {
            $this->message = $message;
        }
    }
}

и в преобразователе, если данное значение недопустимо, вместо объекта исключения возвращается объект InvalidIssue.

public function reverseTransform($id)
{
    if (!$number) {
        return null;
    }

    $issue = $this->dm
        ->getRepository('AcmeTaskBundle:Issue')
        ->find(new \MongoId($id))
    ;

    if (null === $issue) {
        return new InvalidIssue(sprintf(
            'An issue with number "%s" does not exist!',
            $number
        ));
    }

    return $issue;
}

Затем добавьте валидатор на вашу модель.

/** Assert\Callback("callback"="validateIssueIsValid") */
class YourModel
{
    protected $issue;

    public function setIssue(Issue $issue)
    {
        $this->issue = $issue;
    }

    public function validateIssueIsValid(ExecutionContextInterface $context)
    {
        if ($this->issue instanceof InvalidIssue) {
            $context->addViolationAt('issue', $this->issue->message, array());
        }
    }
}