This question is mainly geared towards Zend in PHP, although it certainly applies to other languages and frameworks, so I welcome everyone's opinion.
I've only recently been using the Zend framework, and while it's not perfect, I have had a pretty good time with it. One thing that drives me crazy, however, is that most of the examples I see of people using Zend do the validation in special form objects, rather than in the model. I think this is bad practice because data can enter into the system in other ways beyond form input, which means that either validators have to be bent and twisted to validate other input, or validation must be done in a second place, and logic duplicated.
I've found some other posts and blogs out there with people who feel the same way I do, but the developers of Zend made this choice for a reason, and other people seem to use it without issue, so I wanted to get some feedback from the community here.
As I said, this mainly applies to Zend, although I think it's important to look at the issue as a whole, rather than working within the confines of the Zend framework, since Zend was designed so that you could use as much, or as little, as you wished.
Peter Bailey's password example is excellent. A user model can only validate, if a password was set (because it's not stored as plain text but as a hash) while input validation can ensure, that the original plain text password corresponds to the security requirements (number of characters,...). Therefore you need both: Model validation and form/input validation, ideally as separate, reusable component and not directly in bloated controller actions.
Think of input validation as whitelist validation (“accept known good”) and model validation as blacklist validation (“reject known bad”). Whitelist validation is more secure while blacklist validation prevents your model layer from being overly constrained to very specific use cases.
Invalid model data should always cause an exception to be thrown (otherwise the application can continue running without noticing the mistake) while invalid input values coming from external sources are not unexpected, but rather common (unless you got users that never make mistakes).
See also: https://lastzero.net/2015/11/form-validation-vs-model-validation/
User input should be validated when it is being inputted because it is specific to the form of entry (ie, do some form validation - make sure text boxes that should have numbers are numbers).
Business logic should probably be validated on the model because it is model specific (ie. make sure they have't already reserved that same room or something like that).
The problem with validating it at the model level is that the model might be used in different ways. Correct input for one scenario may not be correct input for another.
The other issue is that you usually want some context sensitive validation, such as displaying a red box around the form control that has the bad input.
The model or database might do some extra validation to make sure the user code isn't doing something completely wrong (constraints, etc).