【发布时间】:2017-01-05 11:31:16
【问题描述】:
我正在写 a bundle to manage feature prices and plans,我有一个复杂的配置需要验证。
实际上我会区分CountableFeatures 和RechargeableFeatures。
这是两者的配置示例:
features:
the_name_of_features_set:
features:
a_rechargeable_feature:
type: rechargeable
# The free amount to recharge the first time (or when you like)
free_recharge: 10
cumulable: true
unitary_price:
EUR: 100
packs:
10:
EUR: 1000
50:
EUR: 5000
100:
EUR: 10000
500:
EUR: 50000
1000:
EUR: 100000
a_countable_feature:
type: countable
cumulable: true
unitary_price:
EUR:
monthly: 1000
yearly: 10000
packs:
10: ~ # <- This is free!
50:
EUR:
monthly: 500
yearly: 5000
100:
EUR:
monthly: 1000
yearly: 10000
500:
EUR:
monthly: 5000
yearly: 50000
1000:
EUR:
monthly: 50000
yearly: 500000
如您所见,这两种功能非常相似。
唯一的区别是价格结构:CountableFeatures 可以订阅,因此价格必须考虑订阅期(每月或每年)而RechargeableFeatures 会在用户请求时进行充值,因此在购买功能充值时他们只需支付 unatantum 价格。
但两者的配置非常相似,并且具有相同的值(cumulable、unitary_price、packs)。
因此,在验证价格配置时,我必须考虑到,如果验证路径是 ...a_COUNTABLE_FEATURE.UNITARY_PRICE,则价格结构必须预期为由年度和每月间隔组成,而如果验证路径为...a_RECHARGEABLE_FEATURE.UNITARY_PRICE 价格简单,没有订阅期。
特征类型在type 节点中定义,在...a_RECHARGEABLE_FEATURE.type 下,与unitary price 处于同一级别。
当我在 unitary_price 中进行验证时,如何读取 type 的值,以便对不同类型的功能进行不同的验证? 或者,我如何构建验证TreeBuilder 考虑到这一点?
- 我可以创建两个单独的方法:
validateUntantumPrice()和validateSubscribtionPrice(),但是如何根据type的值调用其中一个或另一个? - 或者我怎样才能让他们知道
type的值,以便我可以根据它的值进行验证,直接在方法中检查它? - 我还可以在
Configuration类本身的属性中设置type值,但是在验证type时如何设置它?
同样适用于packs 的配置值:如果是可充电功能包,价格很简单 (unatantum),而如果是可计数功能包,价格有订阅期。
这是我想出的配置。这一直有效,直到我引入了新的 CountableFeature 类型,现在我无法继续前进。
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('features');
$rootNode
->useAttributeAsKey('name')
->prototype('array')
->children()
->arrayNode('features')
->useAttributeAsKey('name')
->prototype('array')
->children()
->enumNode('type')->values(['boolean', 'countable', 'rechargeable'])->isRequired()->cannotBeEmpty()->end()
// @todo Only if type === Boolean
->scalarNode('enabled')->defaultFalse()->end()
// @todo Only if type === Rechargeable
->scalarNode('cumulable')->defaultFalse()->end()
// @todo Only if type === Rechargeable
->scalarNode('free_recharge')->defaultNull()->end()
// @todo Only if type === Rechargeable
->arrayNode('unitary_price')
// @todo Validate currency code
->useAttributeAsKey('name')
->prototype('integer')->end()
->end()
// @todo Only if type === Rechargeable
->arrayNode('packs')
->useAttributeAsKey('name')
->prototype('array')
// @todo Validate currency code
->useAttributeAsKey('name')
->prototype('integer')->end()
->end()
->end()
->arrayNode('prices')
// @todo Validate currency code
->useAttributeAsKey('name')
->prototype('array')
->children()
// @todo Set this as section
->scalarNode('monthly')->defaultNull()->end()
->scalarNode('yearly')->defaultNull()->end()
->end()
->end()
->end()
->end()
->end()
->end() // End features
->end()
->end();
return $treeBuilder;
}
}
【问题讨论】:
-
是的,我做到了,但我不知道如何上一级然后继续验证,因为... 尝试编写验证:你会明白我在说什么。 ..我必须先到达节点
... a_rechargeable_feature.type,然后根据它的值,验证同一级别上的以下节点... a_rechargeable_feature.unitary_price和... a_rechargeable_feature.packs。但是,一旦我到达... a_rechargeable_feature.type,我怎样才能上一层并继续验证? -
我应该创建两个单独的方法:
validateUntantumPrice()和validateSubscribtionPrice()但是如何根据type的值调用其中一个或另一个? -
您需要在
type级别分叉它。根据类型附加一种带参数的方法或不同的方法。 -
你能写一个例子吗?
标签: php validation symfony