Passing data from controllers to models

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Passing data from controllers to models

Post 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?
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: Passing data from controllers to models

Post 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);
             }
      }
}
User avatar
inghamn
Forum Contributor
Posts: 174
Joined: Mon Apr 16, 2007 10:33 am
Location: Bloomington, IN, USA

Re: Passing data from controllers to models

Post 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();
 
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: Passing data from controllers to models

Post 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.
Post Reply