你是對的,這個標籤(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
不要重新發明輪子。您可以將其配置爲僅使用您需要的東西。