我的路由配置提供了两个选项:模板和选项。我想验证用户的配置必须只提供一个选项,而不是两个,但我不知道如何做到这一点:
routes:
hello:
title: Hello world
template: %my_module/templates/hello.html.twig
hello/%name:
title: Hello again
content: 'Hello {{name}}!'
默认情况下,ArrayNode不提供此功能,但我们可以扩展此功能。
<?php
namespace AndyTruongConfigDefinition;
use SymfonyComponentConfigDefinitionBuilderArrayNodeDefinition;
use SymfonyComponentConfigDefinitionExceptionInvalidConfigurationException;
class RadioArrayNodeDefinition extends ArrayNodeDefinition
{
private $radioOptions = [];
public function mustFillOnlyOneOfTheseKeys(array $keys)
{
$this->radioOptions[] = $keys;
}
protected function createNode()
{
$node = parent::createNode();
$node->setFinalValidationClosures([
[$this, 'validateRadioOptions']
]);
return $node;
}
public function validateRadioOptions($value)
{
foreach ($this->radioOptions as $radioOptions) {
$count = 0;
foreach ($radioOptions as $radioKey) {
if (!is_null($value[$radioKey])) {
$count++;
}
}
switch ($count) {
case 1:
return $value;
case 0:
throw new InvalidConfigurationException('One of these keys is required but none given: ' . implode(', ', $radioOptions));
default:
throw new InvalidConfigurationException('Only one of these keys is allowed: ' . implode(', ', $radioOptions));
}
}
}
}
那么,我们可以使用新的定义如下:
<?php
use SymfonyComponentConfigDefinitionBuilderNodeBuilder;
use SymfonyComponentConfigDefinitionBuilderTreeBuilder;
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('routing');
/* @var $route_item NodeBuilder */
$route_item = $rootNode->children()
->setNodeClass('radioArray', 'AndyTruongConfigDefinitionRadioArrayNodeDefinition')
->arrayNode('routes')
->prototype('radioArray');
$route_item->mustFillOnlyOneOfTheseKeys(['content', 'template']);