Re: HTML_QuickForm2 / container rules
| From: | Alexey Borzov | Date: | Thu, 15 Jan 2009 14:04:52 +0000 |
| Subject: | Re: HTML_QuickForm2 / container rules | ||
| References: | 1 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-51433@lists.php.net to get a copy of this message | ||
Hi Christian,
Christian Weiske wrote:
As Alexey suggested subversively, we should discuss about rules in HTML_QuickForm2 containers. Currently, there is no really easy way to create rules that apply to multiple elements in an container/group. We solved a specific problem of ours by summing up all values in the container and applying the rule to it. This doesn't solve problems for non-numeric elements, nor for other rules. What we also try to achieve is setting the error message to the container, not to each of the single items involved. The current implementation of rules in QF2 uses $element->getValue() on the element the rule is associated to. This is something that hinders us to e.g. validate the sum of several elements.I'd like to clarify: there is currently no easy way to leverage *existing* rules to validate all the elements in a container / group. Since Container has getValue() implemented (it basically returns an associative array ('name' => 'value') for the contained elements), it is perfectly possible to write a *custom* rule that'll take that array, process it and set the error message for the Container. In HTML_QuickForm we had three ways of assigning rules for groups: 1) rule gets group's value as an array $form->addRule('group', 'error message', 'rule name'); 2) iterate over group's values $form->addGroupRule('group', 'error message', 'rule name', rule data, element count); 3) assign rules to separate elements within group $form->addGroupRule('group', array(
'child' => array(
array('error message', 'rule name')
)
));
Case (1) is possible in QuickForm2 now, case (3) is somewhat possible, since we can add rules to any elements (the difference being that error message is applied to the element itself rather than group, but we don't yet have groups in QF2). The only problem is case (2) when we apply some rule working on scalar values to the elements of the array that is group's value.
Note also that it's not limited to groups, we need to validate <select multiple>, too: http://pear.php.net/bugs/bug.php?id=12610
Validating a sum of several elements is, IMO, case (1): you need to get a whole array, process it (sum in your case) and validate the result (compare it to a given value). You'll need only to write a custom Rule for that, maybe based on Compare rule, where you'll hack validate() method to preprocess the array before calling checkValue().
A solution to this problem could be that the rule got a callback function that is executed to return the value. The callback would need at least one parameter: The element the rule is attached to. By iterating over the elements, one could calculate the exact value one desires.Callback is a bad idea: when client-side validation is implemented, you'll have to re-implement that callback in Javascript.
While this would be handy, it would require a new callback for each
setting/combination of elements. Passing an array of elements to be
taken into consideration would make it more flexible.
That way QF2 could provide some pre-defined oftenly needed functions.
An example:
I have three elements and want to make sure the sum of two of them is
lesser than 5.
I'd do that:
$form->addRule(
'lte',
'Sum may not be greater than 4',
4,
'valueCallbackFunctionSum',
array('number_1', 'number_3')
);
the callback 'valueCallbackFunction' would be called with the $form
element as first, and the array of elements to get values from as
second parameter.
It could look like this:
function valueCallbackFunctionSum($form, $arElements) {
$nSum = 0;
foreach ($arElements as $id) {
$nSum += $arElements[$id]->getValue();
}
return $nSum;
}
Thouhts on this?
I think that's a very special case: never needed such validation myself and never before had a feature request for such validation. Case (2) above, on the other hand, is much more common.
Anyway, I don't like the idea of adding callbacks, but maybe it is a good idea to change HTML_QuickForm2_Rule::validate() method to not directly call $this->owner->getValue() but rather call some proxy method, so that it'll be easier to mangle value somewhat in child class?.. Also $this->owner->getError() and $this->owner->setError() calls may be changed the same way...
Probably that'll help both your issue and case (2) above.