Page 1 of 1

Passing data from controllers to models

Posted: Fri Jan 16, 2009 10:14 am
by matthijs
Models have to be passed the data they need. But how?

You can have properties for each model field and together with setters and getters arrange the access to those properties. But the drawback with that approach is that it gets tedious very fast. The more properties, the more tedious it gets. And I'm not talking about the model classes them selves, but the classes using those models.

So a controller would for example:

Code: Select all

class somecontroller {
 
public function saveUser(){
  $model = $this->load()->model('user');
  $model->name = $somevalue;
  $model->email = $someothervalue;
  /* etc etc */
  $model->save();
}
}
Also, as soon as you make a change in your model, you know have to change the code in 100 places, not good. Would seem a lot easier to pass an array of data to either the constructor or the save method of the user model. Or use some sort of datacontainer object.

What are your strategies?

Re: Passing data from controllers to models

Posted: Fri Jan 16, 2009 10:52 am
by Eran
As you suggest, I usually pass the entire data set as an array and let model sort it out. This array can come from any source - POST/GET data, some web service, a database query, another model, you name it. The model knows how to get the information it needs from it, and the controller is merely the mediator between the data and the model.

For example, for form submissions I usually do:

Code: Select all

public function newuserAction() {
      $users = new Users();
      $result = $users -> add($_POST);
}
The same method can be used for importing users from a web service:

Code: Select all

public function importAction() {
      $gmailService = new GmailService();
      $data = $gmailService -> getAccounts($this -> getParam('email'),$this -> getParam('password'));
      if(is_array($data) && !empty($data) ) {
             $users = new Users();
             foreach( $data as $user) {
                   $users -> add($user);
             }
      }
}

Re: Passing data from controllers to models

Posted: Fri Jan 16, 2009 11:14 am
by inghamn
I use a naming scheme to make the controller code much easier. Form inputs are named name="model[fieldname]". That way, I can have the controller loop over all the POST[model] and call the appropriate setter. So, for adding users I would name all the fields like:

Code: Select all

 
<input name="user[username]" id="user-username" />
<input name="user[firstname]" id="user-firstname" />
 
Here's my controller code:

Code: Select all

 
if (isset($_POST['user'])) {
    $user = new User();
    foreach($_POST['user'] as $field=>$value) {
        $set = 'set'.ucfirst($field);
        $user->$set($value);
    }
 
    try {
        $user->save();
        header('Location: home.php');
        exit();
    }
    catch (Exception $e) {
        $_SESSION['errorMessages'][] = $e;
    }
}
 
$template = new Template();
$template->blocks[] = new Block('users/addUserForm.inc');
echo $template->render();
 

Re: Passing data from controllers to models

Posted: Fri Jan 16, 2009 11:29 am
by matthijs
Those seem both like better solutions then my current manual setSomething() (x10) method :)

I tend to go for the array method. But I'd also be interested in how common libraries and frameworks deal with this as well. Maybe pass around value objects or datacontainer objects?

In the skeleton framework you'd pass around a request object, which has get/set methods for each value, internally holding the data as an array as well.