2014-01-15 31 views
11

我想做一些看起来像How to use Data Transformers教程中所做的事情。但我想添加一个流程,但我找不到任何示例。组合约束和数据变换器

在symfony教程中,数据转换是关于将问题编号更改为Issue对象。这是在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; 
} 

我们可以看到,如果提供了一个无效的发行数量,改造将失败,该函数抛出一个TransformationFailedExceptionreverseTransform()函数来完成。因此,该表单与消息“此值无效”的错误。将此信息个性化将是一件好事。

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

作为转换之前我必须验证的另一个示例,我使用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没有被格式化为正确MongoID,客户会收到一个500所以我要检查,改造前,如果收到的ID是正确的,因为如果它的不是,转型会带来致命的错误。如果我在我的转换中管理所有的情况,比如检查$ id是否正确,就好像我在变压器中进行验证,这是不正确的。

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

+0

你有没有试过用try/catch块做''form-> handleRequest'? – saamorim

+0

try/catch将不起作用,因为表单组件会吞噬任何DataTransformer错误。检查代码。事情是,转型是转型而不是验证。所以不要在变换操作中进行验证。您需要在验证中检查null问题。 – Cerad

+0

我错了,说我的回复是500.我有一个表单错误,只是告诉“这个值是无效的”。 “你需要在你的验证中检查一个空问题”是什么意思? – maphe

回答

9

这就像一个解决方法,但是我建议编写代表“无效问题”的类来个性化错误。

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

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

并且在变换器中,如果给定值无效,则返回InvalidIssue对象而不是抛出Exception。

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()); 
     } 
    } 
} 
+0

我验证了答案,这是一个很好的主意......希望symfony有一天会升级它的验证系统来支持这种情况。谢谢 – maphe

+0

好的解决方案!我不明白这是如何被symfony忽视的。 – shapeshifter