Validation in form or model?

I have a form object which handles all the controls. Quite often, I simply need to create a record form the data in the form.

Heres an example: adding a job to a recruitment (cut down, simplified code)


$form = new JobForm()->populate($_POST); //using $_POST for example only
if ($form->isSubmitted() && $form->isValid()) {
     $job = $this->mapper->job->create();
     $job->fill($_POST);
     $this->mapper->job->save($job);
}
else {
$errors = $form->getErrors(); //gets a simple array of error text using the forms labels
}

My question is, is it right that the validation is being done in the form?

I could put the validation in the model… however, in the model it would just be “is the current set of data valid”. The form also handles “is the username available” type checks.

I usually check for blanks and invalid characters and stuff on the form and then check the layout and lengths and stuff in the model like you suggest.

HTML5 has individual value validation as part of the form, with new input types (email, url, color and various date/time) and attributes (required, pattern, min, and max etc).

So Im thinking the model should tell the form what it should expect.

My question is, is it right that the validation is being done in the form?

I would say, absolutely, because it’s definetely business logic. However I can understand the urge to put it into the Form object as well. This is part of the reason I avoid using Form objects, they remind me of full blown ORM solutions where I encounter the point of deminishing returns sooner than later.

A forms builder, for me, would be a simple View object that simply accepted arguments (either from GPC or other) and generated the form based on template overrides which I may or may nor provide.

Easier said than done to build something useful, though.

For the sake of consistency (which I favour over almost 99% of the time ot other best practices) I keep validation out of ORM, data mappers, etc and strictly in the model layer.

Cheers,
Alex

From a design/best practice perspective i’d say that keeping all validation in the model is the best way, as the moment you create a job from another method (via an API, as a batch process etc) you have to re-create the validation for each of these.

In a real world situation however, I stick the validation inside the form object. It’s easier to map errors back to form fields (as opposed to returning errors from the model to the form/data source whilst keeping loose coupling) and 90% of the time my model inserts,edits etc are handled via forms anyway. For the remaining 10% I can always flag the form as invalid if there is a case for it.

Guess a lot of it depends on what you class is business logic, for me things like blanks and invalid characters are not ‘high level’ enough to warrant the model handling them.

I do this, but the problem I get is that now my models know of each other, and I can’t just take them from one project and add them in another, without moving over all dependencies.

Ex: “job” must be linked to a “user” with a preset set of “privileges”.
So when you insert the “job”, it will validate the “user”, and in turn the user’s “privileges”.

That is business logic, tied to the model, but it’s easier done in the form/page controller. But if you do this, your “job” functionality won’t always be in one place, so you will have to scan the entire project for every bug fix.

Do you guys have any suggestions on that?

I was thinking of passing an empty instance of the model to the form, having the form populate the instance and then run the model’s validation function…

This should help, but it causes 2 issues that I can see:

  1. The form has no knowledge of the validation rules, therefore cannot generate a matching JavaScript validation function, which is something I’m doing at the moment.

  2. How do you do “Sorry that Username is taken” type checks. Correct me if I’m wrong but I’ve always found it cleaner for a $model->validate(); function simply check the values currently assigned to it are valid, not look through other records (because then the model starts becoming overly complex and needs to know about external objects)… of course there are plenty of other types of errors which require checking of existing data. At the moment handling them in the form works, but it also means it’s possible for (in my example) 2 users to have the same name, if there are multiple forms for user creation and only one has the proper validation.

Perhaps validation should be done in the mapper and the mapper passed to the form? The mapper has to be able to access all data. Still doesn’t fix 1) though, and seems messy passing the mapper to the form just for validation.

I suppose it depends on the degree of validation you perform. I validate everything as much as I can, than means checking for duplicates (which occasionally requires other models), contacting third party services, etc.

Validation cannot always be addressed with trivial regex, it’s a fact of life when building robust, enterprise applications and an assumption many form builders/etc make.

The best solution I have experienced is to use dedicated validation objects. It means more work as a developer, but it’s definetely most robust. Look at Zend and how it implements validation.

A single validate() method seems so CodeIgnitor-ish. A quick solution which ironically quickly falls apart. The number and variance of parameters which can potentially be passed to a model and it’s methods is arbitrary so relying on a single validate() seems to me you’d quickly be validating data that doesn’t exist or need to be validated under all contexts.

Cheers,
Alex