2009年7月19日星期日

RE: [fw-mvc] breakChainOnFailure

I appreciate the help here, but I think both of you are missing the
point a little bit, or I haven't explained the problem well. I don't
want to validate one element at a time, and yes I DO use the $context in
my isValid function. Context gives you the full form input, I wouldn't
even be asking this question if I didn't know how to pass the context
and verify one field against the other. Context, to the best of my
knowledge does not tell you the validation status of other elements, it
just tells you what the user inputted for those elements, bogus or not.

Let me ask it this way. If I were to submit country asdf and state
gffdds, how the heck are you going to verify if the zip code is of the
right format for a bogus country/state submission. Any error you present
next to the zipcode field is going to be meaningless. You haven't helped
the user at all by providing that extra "info" and you haven't decreased
the likelihood one bit of them not having to resubmit the form a couple
more times to get all the fields correct.

If I assume that the country is a real country and the state a real
state, then sure, all the tools I need are $context and serial
validation of all elements. But when it comes to security of a website,
preventing injection attacks and things of that nature, "assuming"
things like this is a pretty poor practice. I'm not trusting in the
honorability of the user to only select what I have in the select boxes
when I know how easy it is to fabricate POST data to a website.

The real situation I face is not a zip code, but that was an easier
example to use than to describe how I have several joins and where
clauses to make to pull together a data set that contains the data
needed for form creation and validation. Now, I could simply remove the
where clauses so it retrieves all records so it is all available to
verify the dependent fields based on other fields and possible choices.
Not real efficient. Or I could live with an extremely inefficient use of
the database, with multiple queries to retrieve the same data: once to
generate the form, once for EACH validator to validate the form based on
it's own view of context, and once to write the form data back to
database. Or I minimize the database querying by not validating what
can't be validated if other fields are not correct. I'm trying to
optimize and there are a number of cases where validation of an element
is meaningless based on other elements and their validation. This is
what I am trying to avoid.

All the arguments presented against why I would find this feature useful
can be used to argue against breakChainOnFailure at the element level
too. Why not show all the things wrong with an entry? Why make the user
fix one mistake at a time on an entry? The fact is, there are times when
it is actually useful to suspend the remaining validation checks on an
element once one check fails, JUST LIKE this is also sometimes useful
behavior at the form level.


--Seth

-----Original Message-----
From: Matthew Weier O'Phinney [mailto:matthew@zend.com]
Sent: Saturday, July 18, 2009 5:01 PM
To: fw-mvc@lists.zend.com
Subject: Re: [fw-mvc] breakChainOnFailure

-- Seth Atkins <satkins@nortel.com> wrote (on Friday, 17 July 2009,
01:19 PM -0500):
> Then how does one validate dependent input? If certain fields need
> certain validation criteria depending on a previous field containing
> valid data, you can't properly validate the other fields.

This has been covered many times before: add a second argument to your
validator's isValid() declaration for $context:

public function isValid($value, $context = null)
{
}

Zend_Form passes the entire array as a second argument to isValid(). If
you need to use it, it's available.

This is well documented in the manual:


http://framework.zend.com/manual/en/zend.form.elements.html#zend.form.el
ements.validators

and search for the heading, "Validation Context."

This feature has been available since the initial stable release of
Zend_Form in 1.5.0.

This *is* different than having a "breakChainOnFailure" feature for
Zend_Form itself, however, as this latter functionality changes the
behavior of Zend_Form substantially. The current behavior is to run
validation on *all* elements in order to return as much information
about invalid entries as possible.

> For example
> suppose you wanted to check for valid zip codes based on the entered
> state (so someone couldn't enter a NY zip code with state AZ. If
> someone entered an invalid state and that failed its check, the
> remaining check on the zip code would give a bogus "invalid" message.
> I'd rather it simply suspend the rest of the form validation since the

> rest cannot be validated properly.
>
> This may fall into the needed feature bucket for future releases,
> unless there is an easy workaround. I managed to find a clunky way of
> doing this by sort of "pre-validating" the input of the field that the

> others depend on so I can put in a conditional to addValidator for the

> affected elements. That way if the pre-validation fails, no validators

> are added at all. If the pre-validation passes, then the others are
validated.
>
> The way I implemented pre-validation was to pass the field input to
> the form constructor. The form constructor has to gather some data
> from the database anyway, so I simply compare that field input to this

> data to ensure it is a valid selection. Hence it is pre-validated.
>
> I looked through the code for isValid methods and it seems that this
> would be a fairly easy feature to implement if there was a mechanism
> in Zend_Form::isValid similar to breakChainOnFailure to tell it to
> stop looping through the element validators once one comes back false.

> I could even do that myself, but I'm reluctant to start tinkering
> around changing the code base of ZF.
>
>
>
> --Seth
>
> -----Original Message-----
> From: Matthew Weier O'Phinney [mailto:matthew@zend.com]
> Sent: Thursday, July 16, 2009 4:56 PM
> To: fw-mvc@lists.zend.com
> Subject: Re: [fw-mvc] breakChainOnFailure
>
> -- Seth Atkins <satkins@nortel.com> wrote (on Thursday, 16 July 2009,
> 02:47 PM -0500):
> > I believe this feature works only within the scope of a single
> > element
>
> > validation. I may be misunderstanding how it works, but I believe it

> > means that if the first validation fails, it stops validating and
> > outputs only the first validation error message.
>
> It means that if the given validator fails, it will not process any
> validators occurring after it in the chain.
>
> > What I am looking for is a way to break out of all form validation
> > if an element fails. If several fields have validators set, and the
> > first
>
> > field fails its check, then I'd like the $form->isValid($data) to
> > exit
>
> > the validation loop that takes it through the remaining elements. I
> > don't see a way to do this within the functions provided in ZF
> > unless I am missing something. Am I missing something?
>
> Zend_Form does not allow for this; it attempts to validate all
> elements, so that you can return all possible validation errors for
> all elements back to the user.
>
> You could likely write a validator that you insert at the top of each
> element that checks the parent form for any failed element validations

> and skips validation -- but it would mark that element as failed in
> validation as well.
>
> --
> Matthew Weier O'Phinney
> Project Lead | matthew@zend.com
> Zend Framework | http://framework.zend.com/
>

--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/

没有评论: