views:

369

answers:

5

I want to add a user in users table via link like '/index/adduser/id/7' .

Question

Should I validate user input inside 'adduserAction' function inside controller or somewhere inside model file? I've put files containing database related functions inside 'models' directory. Suppose a user is added to a table via 'id'. This id is sent via 'get'. And finally its added to table by 'AddUser' function (inside model file). Then I should validate this 'id' inside 'adduserAction' or 'AddUser'.? Scalability-wise, would it be better to do it inside 'AddUser'?

A: 

I'd do it in the Controller, not the Model. IMHO that's the better place because then the sanitized data is secure to use in the controller already. That's a good thing for comparing things, etc., even before the data is actually saved.

DaDaDom
@DaDaDom: If I want to re-use my database model files with another application then I've to do these validations again in new controllers. Afterall my database function knows what kind of input it wants, so wouldn't it make sense to validate over there?
understack
@DaDaDom: I respectfully have to disagree with this. Please see my answer as to why.
fireeyedboy
+1  A: 

the ideal solution is to use validation inside your forms - i.e. appending it to your zend_form_elements - see http://framework.zend.com/manual/en/zend.form.elements.html

roman
@roman: yes, but not everything comes from 'Forms'. Some get variables might be in url and if somebody saves that url or later tries to change it in url itself, these vars have to be validated otherways.
understack
in that case +1 for inside the model
roman
+4  A: 

I would say put the validation in your model. You can then keep your validation rules in a central location. How should your controller know the exact length of a valid user name? That is model territory. Your controller can ask the model if a user name length is correct or not sure, but the rule itself needs to be in your model. In my controller I would do something like this:

$model = new Model; $model->loadFromArray(something to get post); if (!$model->isValid()) { forward back to form } $model->save();

Eric Butera
"You can then keep your validation rules in a central location." That's the point I made in a comment in 'DaDaDom' answer. Your answer sounds good.
understack
+4  A: 

There's a popular believe / paradigm that states:

Thin controllers, fat models.

What this means, is that your controller should only be responsible for doing the bare minimum to make sure actions change the state of models and serve the right view in return. With this in mind, the validation should occur in your models. But... hold on for a minute. Models aren't necceseraly 1 tiered layers.

I believe among .NET programmers the following setup (or something similar) is a pretty common practice (if the scale of the project validates it):

Controller
  -> ServiceLayer
     -> Repository
        -> DataObject

And I'm starting too like this setup more and more. Moreover, I believe this setup is very doable in a Zend Framework environment too.

The term Model is somewhat of a vague term. In the above you could consider the three last layers as your Model layer. What the three layers represent is the following:

  • ServiceLayer:
    Responsible for business logic. In other words: retrieving Dataobjects (Models) from the repository, tying Models together, AND validating Models before storing them, mailing a user, etc..
  • Repository:
    Some type of persistence mechanism (like a Database), that serves DataObjects to the service layer, and stores DataObjects back in the persistence mechanism (after the service layer validated them)
  • DataObject:
    You might consider this the actual Models. Preferably DataObjects have common interfaces (independant of the Repository that is), so that Repositories are interchangeable. In other words, when the repository changes from a database to an XML file from some webservice, the DataObject still has the same interface the service layer and ultimately the view can work with.

Hope this makes sense. This is basically my understanding of a more layered MVC setup right now. If anybody feels I have things mixed up please feel free to correct me.

Please keep in mind though, that not all projects dignify such a layered setup. In smaller projects you could perhaps do with just a 1 layered Model layer. In that case, validating should still be the Model's responsiblity. The controller should be thin (just for tying Model state and Views together through actions).

fireeyedboy
+1 for good explanation!
understack
great note.........
St.Woland
A: 

I know it's already answered, but I remember the "younger me" combing the web for some choice resources on sites like this and would like to share my research and what I do here. I do the following:

  • I use forms to do input validation and filtering Do my validation inside models

  • I have a validation method which proxies the form validation method.

  • This validation method can called upon internally by model methods or externally by the controller or view.

Here's a quick example:

//UserModel
class Default_Model_User
{

    protected $_form;

    public function getForm()
    {
        if(!isset($this->_form)) {
            $this->_form = new Default_Model_Form_User();
        }
    }

    public function validate($data)
    {
        if($result = $this->getForm()->isValid($data)) {
        // if you have custom validation conditions outside of the form, then you 
        // can do the validation here also.
            if($data['controller_entered'] == 'some value') {
                $result = false;
            }
        }
    return $result;
    }

    public function saveUser($data)
    {
        if($result = $this->validate($data)) {
            // do something.
        }
    return $result;
    }
}

If you haven't read it already, be sure to check out the Surviving The Deepend book freely available on the following URL:

http://www.survivethedeepend.com/zendframeworkbook/en/1.0

This chapter is specific to your dilema: http://www.survivethedeepend.com/zendframeworkbook/en/1.0/implementing.the.domain.model.entries.and.authors#id1491270

You will no doubt run into other issues as you progress through... It may help to check out the comments on my blog post regarding the model layer where I cover this issue: http://www.rvdavid.net/my-zend-framework-model-layer-part-service-part-orm/

Hope this helps someone out.

rvdavid