Another idea for using models with forms

January 7, 2009 – 5:36 pm Tags: ,

Matthew Weier O’Phinney wrote about using Zend_Form with models. His approach puts a form inside a model, which then uses the form to validate itself.

While this idea is not bad, I find it being upside down – I think the form should use the model to validate itself, not the other way around.

But how would you utilize a model class to validate a form? I think there are two feasible ways to do so: A global model for a form, and a model-based validator class…

A global model for a form

This approach would basically tell a form “use this model to validate yourself”, or…

$form = new SomeForm();
$model = new SomeModel();
$form->setModel($model);
if($form->isValid($_POST))
{
  //something happens here
}

So in other words, you would set a model to a form, and when you call isValid, the form uses the model to validate itself.

This would depend on the model’s being built in a certain way, though: The model’s fields should be writable using setSomething(value) methods, and those methods should throw exceptions if the value passed to them was invalid. This is so that the form can collect the exceptions’ messages, and display them to the user, in a similar way as validator error messages are displayed – this time the validator just was the model.

You may notice a similarity between this and the modelform stuff I’ve been working on before. Indeed, the modelform class could be adapted for this, but this isn’t the same – the modelform generates a whole form based on the metadata for a model, but this would simply attempt to validate the form.

Finally, since this approach would use setters on the model instance we pass, the instance would get automatically filled with the values from the form for you if the form is valid.

A model based validator

This approach is basically the first but chopped into smaller pieces. Instead of assigning a model to the form, we’d assign a model to a validator, and tell it which method it should validate against.

$model = new SomeModel();
$validator = new CU_Validate_Model($model, 'foo');

then, you could assign the validator to a form field like any other validator, or use it as a stand-alone one. When the isValid method gets called, it would try to use setFoo method of the model, and catch any messages from an exception the model might throw.

This approach would require a bit more code when implementing a form, as you would need to define each field’s validator separately. However, it would also be more flexible, as you could have fields in your form that don’t get validated using the model, or you could even mix multiple models into the same form’s validation logic.

With this approach, you would also get model instances with the data from the form in case it’s valid.

In closing

I think both of these methods could be useful depending on the case. One might consider a minor flaw that they both require the model to perform in a specific way for it to work: use setSomething, and throw exceptions with invalid values. I don’t think that’s a flaw, though, since I think we can say that that kind of behavior is actually good for a model to have.

Both of these also add no additional dependencies to the model itself. They could also be used without zend_form, or zend framework – you would just need to implement it in a bit different way.

Since these are just ideas, there’s no code for you to consume. I may implement some of this later, or if you decide to go for it, feel free to share your code.

More on models:
The problems faced by a common model interface in frameworks
Food for thought: utilizing models in MVC
Decoupling models from the database: Data Access Object pattern in PHP

Share this:
  1. 13 Responses to “Another idea for using models with forms”

  2. setModel() method passes form data to form or what? it’s strange, because $model is an abstract class, not the $_POST data
    please, explain, what does “set a model to a form” mean

    By Anonymous on Jan 7, 2009

  3. Umm, I’m a bit lost here… That snippet was just an example on how you could make the validation stuff work (if it existed)

    By Jani Hartikainen on Jan 7, 2009

  4. How about a real solution in a zend framework proposal, or there is no good solution to solve form validation with the model logic ?

    By The Sorrow on Jan 7, 2009

  5. I know, but, it looks like a non-sense. I don’t see there any relationship between model and form

    The Sorrow, only and old (last revision 1 year ago) draft http://framework.zend.com/wiki/display/ZFPROP/Zend_Form_Generator

    I don’t understand, why Zend developers are closing eyes on this problem. Framework would grow up near Django with its auto-admin system

    By Anonymous on Jan 7, 2009

  6. What I described here is a “real” solution. It’s just not an implementation yet. I will probably do some coding regarding to this sometime in the future, and I will be posting about it if I do.

    Lastly, regarding Django-style admin generation, there is my proposal here:
    http://framework.zend.com/wiki/display/ZFPROP/Zend_Form+generation+from+models+-+Jani+Hartikainen

    The prop works with Doctrine, and the Zend_Db_Table based adapter has some basic features.

    By Jani Hartikainen on Jan 8, 2009

  7. Wow, that’s nice, thx, Jani. If there were some voting stuff about proposals, i would vote for yours =)

    By Anonymous on Jan 8, 2009

  8. i found the first solution better (global model for a form) i think it makes more sence, at least for me.
    I have made a small class based on this solution, but its a bit custom, not verry adaptive.

    By solomongaby on Jan 8, 2009

  9. I think Matthew’s main point is thin controllers and fat models. Your approach requires more business logic to be put in the controller (set form, set the validators..), does it ?

    By Stoyan on Jan 9, 2009

  10. You may wish to have a form factory class or something like that, but I don’t think they go into the model.

    Also, I think setting the form and such isn’t necessarily “bad” in the controller – if you think about it, it’s related to the application’s “flow”, things that are supposed to happen in specific actions, so I think it’s something that’s relevant in controller code.

    By Jani Hartikainen on Jan 9, 2009

  11. I have written a follow up on this if anyone is interested:

    http://www.whitewashing.de/blog/articles/109

    By beberlei on Jan 23, 2009

  1. 3 Trackback(s)

  2. Jan 18, 2009: Decoupling models from the database: Data Access Object pattern in PHP | CodeUtopia
  3. Feb 5, 2009: Complex custom elements in Zend_Form | CodeUtopia
  4. May 7, 2009: Validating Zend_Forms using model objects | CodeUtopia

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)