2016-11-15 48 views
0

我正在使用Symfony驗證程序Symfony服務容器在一個項目中,但不是完整的Symfony框架。如何使用Symfony組件配置自定義驗證器的依賴關係?

我寫了一個自定義驗證器,需要一些依賴項作爲構造函數參數提供。

Symfony Documentation描述了一種將驗證器配置爲服務的方法,該方法已成功完成。但是,這使得使用validator.constraint_validator服務標籤,我懷疑它們粘在一起。

此服務標籤似乎是具體的使用完整的Symfony框架時 - (意料之中)的Symfony驗證是不是神奇加載我自定義的驗證,當我加入這個標籤

所以,我怎麼可以鏈接驗證和服務容器組件?或者是否有任何其他策略讓Symfony驗證器加載我的客戶驗證器的依賴關係?

回答

1

你是對的,這個標籤(validator.constraint_validator)由編譯器處理 - 從Symfony/FrameworkBundle傳遞。 如果你不想使用這個包,但你想鏈接DI容器和驗證器,你應該重新實現這個過程。

首先,我們需要一個ConstraintValidatorFactoryInterface的實例。 Default implementation只是尋找一個類,其名稱由validatedBy()方法的約束返回。 Implementation from FrameworkBundle將validatedBy()的結果視爲服務標識符/或標籤別名,並從容器中獲取此服務。我們的實現應該做這樣的事情:

use Symfony\Component\DependencyInjection\ContainerInterface; 

use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; 
use Symfony\Component\Validator\Constraint; 

class ContainerConstraintValidatorFactory implements ConstraintValidatorFactoryInterface 
{ 
    private $container; 

    public function __construct(ContainerInterface $container) 
    { 
     $this->container = $container; 
    } 

    public function getInstance(Constraint $constraint) 
    { 
     // Simplified implementation, just for example: 
     return $this->container->get($constraint->validatedBy()); 
    } 
} 

例如,假設我們有一些依賴一些自定義的驗證約束和驗證器類:

use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\ConstraintValidator; 

class CustomConstraint extends Constraint 
{ 
    public $message = 'Oops!'; 

    public function validatedBy() 
    { 
     return 'validator.custom'; 
    } 
} 

class CustomConstraintValidator extends ConstraintValidator 
{ 
    private $dependency; 

    public function __construct($dependency) 
    { 
     $this->dependency = $dependency; 
    } 

    public function validate($value, Constraint $constraint) 
    { 
     if (rand() % 2 === 0) { 
      $this->context 
       ->buildViolation($constraint->message) 
       ->addViolation(); 
     } 
    } 
} 

接下來我們登記約束驗證爲服務與ID相同來自相關約束對象的validatedBy()方法的結果。我們通過這個工廠創建與容器相關的驗證器服務的實例。所有的約束驗證器都以相同的方式註冊。

use Symfony\Component\DependencyInjection\ContainerBuilder; 
use Symfony\Component\Validator\Validation; 

$container = new ContainerBuilder(); 
$container->register(
    'validator.custom', 
    new CustomConstraintValidator('Some dependency value') 
); 

$validatorBuilder = Validation::createValidatorBuilder(); 
$validatorBuilder->setConstraintValidatorFactory(
    new ContainerConstraintValidatorFactory($container) 
); 
$validator = $validatorBuilder->getValidator(); 

$violations = $validator->validate('test value', [ 
    new CustomConstraint() 
]); 

它的工作原理,但我建議考慮使用FrameworkBundle不要重新發明輪子。您可以將其配置爲僅使用您需要的東西。