2013-06-27 27 views
4

我正在創建一個自定義驗證器約束來驗證「聯繫人」,類似於「John Doe <[email protected]>」。繼Cookbook我創建了約束類:Symfony2 - 在自定義驗證程序中調用EmailValidator

<?php 

namespace MyCompany\MyBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 

/** 
* @Annotation 
*/ 
class Contact extends Constraint 
{ 
    public $message = 'The string "%string%" is not a valid Contact.'; 
} 

,也創造了驗證:

<?php 

namespace MyCompany\MyBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\ConstraintValidator; 
use Symfony\Component\Validator\Constraints\Email; 
use Symfony\Component\Validator\Constraints\EmailValidator; 

class ContactValidator extends ConstraintValidator 
{ 
    public function validate($value, Constraint $constraint) 
    { 
     if (!preg_match('#(.*)\s+<(.*)>#', $value, $matches)) { 
      $this->context->addViolation($constraint->message, array('%string%' => $value)); 
     } 

     $emailValidator = new EmailValidator(); 
     if (isset($matches[2]) && $emailValidator->validate($matches[2], new Email())) { 
      $this->context->addViolation($constraint->message, array('%string%' => $value));  
     } 
    } 
} 

的一點是,我想使用的Symfony的爲EmailValidator我的自定義驗證內部檢查該電子郵件是有效的。我不想重新發明輪子並使用我自己的正則表達式驗證電子郵件。當試圖驗證有效的接觸,但是,測試與無效的電子郵件聯繫人

一切都OK了(「加夫列爾·加西亞·<infoinv4l1d3mai1.com>」),它與一個PHP致命錯誤craches:

Fatal error: Call to a member function addViolation() on a non-object in /home/dev/myproject/vendor/symfony/symfony/src/Symfony/Component/Validator/Constraints/EmailValidator.php on line 58

挖掘到EmailValidator.php類,我已經意識到這個問題與$ context(ExecutionContext)有關。這裏是EmailValidator.php的第58行:

$this->context->addViolation($constraint->message, array('{{ value }}' => $value)); 

似乎該類的上下文屬性爲null。有人知道爲什麼我需要在某處注入它?

在此先感謝。

P.S .:我正在使用Symfony 2.3。不要關注正則表達式,我知道它可以更好。這只是爲了現在的測試。

回答

3

您可以直接使用約束

看到http://symfony.com/doc/current/book/validation.html

use Symfony\Component\Validator\Constraints\Email 

$emailConstraint = new Email(); 

// use the validator to validate the value 
$errorList = $this->get('validator')->validateValue(
    $email, 
    $emailConstraint 
); 

最佳方面

+0

如果我定義我的驗證作爲一項服務,我該如何注入EmailValidator?我已經做了一個應用程序/控制檯容器:調試,我看不到與它對應的服務... –

+0

我編輯我的帖子。您不需要僅通過電子郵件限制對象提供服務來驗證您的電子郵件。 –

+0

謝謝!最後,我將驗證器服務注入到自定義驗證器中,並用它來驗證「聯繫人」的電子郵件部分。 –

4

我認爲原來的問題是關於使用爲EmailValidator內自定義驗證,在這種情況下容器不可用,所以

$this->get('validator'); 

將無法​​工作。看起來海報的唯一問題是將EmailValidator的addViolation添加到正確的上下文中。這應該工作:

$emailValidator = new EmailValidator(); 
$emailValidator->initialize($this->context); 
$emailValidator->validate($matches[2], $constraint); 
1

有嘗試定製調用內定製後發現這個話題,我做了深入研究,我可能只是發現(據我簡單)的另一種更好的方式。

有效期:Sf2.6> =

$this->context->getValidator() 
    ->inContext($this->context) 
    ->atPath("time_on_point") 
    ->validate($timeOnPoint, new AssertCustom\DateTimeRange(array('min' => '+1 day'))); 

在這種情況下,我宣佈一個新的自定義驗證像class specific Validator,我可以通過它的名字直接去外地。 這樣做的好處是:我可以通過僅應用「new AssertCustom」來調用另一個自定義,如果此「AssertCustom」需要類似構造的服務,則不會有依賴項,因爲配置服務將透明地調用所有的東西。

要小心,如果你調用遞歸(深)字段,則需要按照此文件中的註釋,以適應上下文:Symfony的\分量\驗證\約束\ CollectionValidator