Bryce -
I think that it should be the job of the Zend_Validate_Builder to
understand required and optional fields. Again, I go back to my point
that it doesn't make sense for an integer validator to return true for
an empty string. An empty string is not an integer, so the correct
response should be false. Maybe a change needs to occur with the
Zend_Validate_Builder. What if by default, all fields are optional and
the developer only declares those fields that are required.
Lets use your example of the optional mailing address and add a required
name field. Notice that instead of flagging the optional fields
'address2' and 'address3', I've lumped them in with 'address1' and
'city' (optional fields). I can then rely on the
Zend_Validate_AllOrNone to signal an error if some but not all of the
address fields are filled in.
<?php
$fields = array('address1', 'city', 'state', 'zip')
$reqd = array_intersect_key($post, array_flip($fields));
$string100 = new Zend_Validate_StringLength(100);
// This form has an optional mailing address where address1, city, state,
// and zip are all required if any are present. Otherwise, they must all be
// blank. address2 and address3 are always optional.
$validate = new Zend_Validate_Builder;
$validate->addValidator('name', $string100,
Zend_Validate_Builder::REQUIRED);
$validate->addValidator($fields, new Zend_Validate_AllOrNone($reqd));
$validate->addValidator(array('address1', 'address2', 'address3',
'city'), $string100);
// Assume $states is a valid array of US states
$validate->addValidator('state', new Zend_Validate_InArray($states));
// Another custom validator for Zip codes
$validate->addValidator('zip', new My_Zipcode_Valiadator);
if ($validate->isValid($post)) {
...
}
?>
In your reply you stated "If the higher-level class made the decision
not to pass a field to a validator (because it was empty), then the
validators never get a chance to make more intelligent decisions.". Can
you elaborate more on this item? If the field is supplied, then it
should be validated. If it is not supplied (empty string), then what
would be the purpose of validating it against the list of validators? I
believe that its the responsibility of Zend_Validate_Builder to signal
an error if a required field is not supplied. After all, its the one
that understands the difference between optional and required fields.
As for your error message callback functionality. I love it. I think
it's a great approach to a difficult problem of separating business and
view logic.
Dale
Bryce Lohr wrote:
Hi all,
Thank you for all of the replies! That feedback is very valuable to me
in trying to figure out what to do with this stuff. I appreciate that
you took your time to share some of your input.
Allow me to elaborate on some the rationale behind the proposed
changes, for your kind consideration.
Passing empty strings:
I've actually removed this from the current version of the proposal,
but I still feel the idea has some merit. I certainly understand that
it doesn't make much sense at first to pass an empty string to
Zend_Validate_Int, and it return true. But if the validators are
solely responsible for passing or failing all values, it would be
possible to write validators with complex rules for whether or not a
field is required, and yet still work with other validators on the
same field. If the higher-level class made the decision not to pass a
field to a validator (because it was empty), then the validators never
get a chance to make more intelligent decisions. And if all validators
always failed empty strings, you would not be able to combine
validators on optional fields.
Consider the hypothetical validator, Zend_Validate_AllOrNone. This
passes a field if it's not empty, and all the fields passed to the
constructor are not empty, or if the field is empty and all the fields
passed to the constructor are empty. Here's an example:
<?php
$fields = array('address1', 'city', 'state', 'zip')
$reqd = array_intersect_key($post, array_flip($fields));
$string100 = new Zend_Validate_StringLength(100);
// This form has an optional mailing address where address1, city, state,
// and zip are all required if any are present. Otherwise, they must
all be
// blank. address2 and address3 are always optional.
$validate = new Zend_Validate_Builder;
$validate->addValidator($fields, new Zend_Validate_AllOrNone($reqd));
$validate->addValidator(array('address1', 'city'), $string100);
$validate->addValidator(array('address2', 'address3'), $string100,
Zend_Validate_Builder::OPTIONAL);
// Assume $states is a valid array of US states
$validate->addValidator('state', new Zend_Validate_InArray($states));
// Another custom validator for Zip codes
$validate->addValidator('zip', new My_Zipcode_Valiadator);
if ($validate->isValid($post)) {
...
}
?>
Conditionally required fields, such as in this form, are rather common
in real-world applications. I don't consider this an edge case. This
example will only work under two conditions:
* The validators pass the empty string. If the $string100 validator
doesn't pass the empty string, then that validator will not allow the
case where all four main address fields are omitted.
* The higher-level isn't involved in the decision. If I put the
OPTIONAL flag on the four main address fields, then there's nothing
that forces, for example, the city field to be populated if the
address1 field is populated.
So, in summary, if the validators pass the empty string, it allows
more collaboration between the validators, and complex validation can
be done much more easily. Of course, the biggest drawback is the fact
you have to use at least two validators to validate a required field.
This is way I tried to make doing this as painless as possible in the
Zend_Validate_Builder proposal. However, I do understand the burden
this puts on those already using the validators, as is. So, basically,
I need you guys to tell me if the benefit is worth the cost. I hope
that I've made the benefits clear enough so you can see the potential
it would allow.
External validation errors:
When I started the Zend_Validate_Builder proposal, I was thinking I
would see if I could get all the current validators to start using
some kind of Error Manager class to generate and raise their errors.
This class would be could be set by the user to their own class, if
they wanted to. I as I thought about it, I realized that I could push
basically the same API that would be used against the Error Manager
out to an arbitrary callback function. If one were to treat the
callback function as a sort of user-defined extension of the validator
function, and put code in there to invoke some kind of Error Manager
class, then you could get same results, only easier. The Framework
could still provide a default Error Manager class, but there would be
no implicit dependency this way. It's loose coupling at it's best,
IMHO. The validators would impose absolutely no policy of their own on
how you handle error messages. That said, the "best practice" way to
handle validation errors could still be designed, recommended, and
documented by the Zend Framework authors. Example "best practice"
usage could be shown in the documents and tutorials. It's just that
one specific policy wouldn't be hard-coded into the system.
I hope this clarifies for you guys why I proposed some of the things I
did. I'm certainly not adverse to other solutions, however, so please,
suggest alternatives. :)
Many thanks,
Bryce Lohr
--
------------------------------------------------------------------------
Dale McNeill |
Alchemy Systems | phone: (512) 532-8050
http://www.alchemysystems.com | email: [EMAIL PROTECTED]
------------------------------------------------------------------------