【问题标题】:Combine constraints and data transformers结合约束和数据转换器
【发布时间】:2014-02-04 02:06:36
【问题描述】:

我想做一些类似于How to use Data Transformers 教程中所做的事情。但是我想添加一个过程,我找不到任何例子。

在 symfony 教程中,数据转换是关于将问题编号更改为 Issue 对象。这是在IssueToNumberTransformerreverseTransform() 函数中完成的

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;
}

我们可以看到,如果提供了无效的问题编号,则转换将失败并且函数会抛出 TransformationFailedException。结果,表单作为错误消息“此值无效”。个性化这条消息会很棒。

数据转换过程在任何验证之前执行(对字段应用约束),因此我无法在尝试转换之前找到验证问题编号的方法。

另一个为什么我必须在转换之前进行验证的例子是我使用 MongoDB 文档管理器将“问题 mongo id”转换为问题(该表单由 REST API 服务器使用,这就是我收到 id 的原因) .所以:

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 表单中收到的 id 格式不正确,客户端将收到 500。所以我想在转换之前检查收到的 id 是否正确,因为如果不是,转换会抛出一个致命错误。如果我在转换中管理所有情况,例如检查 $id 是否正确,这就像我在转换器中进行验证并且它不正确。

我的问题是:有没有办法在数据转换之前应用约束?或者有没有办法在转换失败时在表单上添加摘要约束?

【问题讨论】:

  • 在执行$form->handleRequest 时,您是否尝试过使用 try/catch 块包围?
  • try/catch 不起作用,因为表单组件会吞下任何 DataTransformer 错误。检查代码。问题是,转换是为了转换而不是验证。所以不要在转换操作期间尝试验证。您需要在验证中检查 null 问题。
  • 我错误地告诉我我的响应是 500。我有一个表单错误只是告诉“这个值无效”。 “您需要在验证中检查空问题”是什么意思?
  • 我编辑了问题,添加了第二个示例来说明为什么我必须在转换之前验证数据

标签: forms validation symfony transformation


【解决方案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());
        }
    }
}

【讨论】:

  • 我验证了答案,这是个好主意...希望 symfony 有一天会升级其验证系统以支持这种情况。谢谢
  • 不错的解决方案!我不明白 symfony 是如何忽略这一点的。
猜你喜欢
  • 2020-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
相关资源
最近更新 更多