16

Our development team is debating a general best practice: Is it better to access a session variable directly from a function in a model class or pass the session variable from the controller as an argument to a function in the model class. Look at the two examples below:

Accessing session variable directly from the model class to use in a query:

class MyModel {
    public function getUserPrefs($userID) {
        $this->query("SELECT * FROM my_table WHERE id=$_SESSION['userID']");
    }
}

Or pass the session variable from the controller to a function in the model class as a function argument:

class MyController {
    public function displayUsers() {
        $this->model->getUserPrefs($_SESSION['userID']);
    }
}

class MyModel {
    public function getUserPrefs($userID) {
        $this->query("SELECT * FROM my_table WHERE id=$userID");
    }
}

The reasoning for passing it to the model from the controller is so all data that is referenced is coming from one point of entry, that being the controller.

What is recognized as a better practice?

4 Answers 4

15

The second version (passing $_SESSION['userId'] as an argument to the method) results in a more decoupled class, and therefore more flexible. Go with it.

Sign up to request clarification or add additional context in comments.

3 Comments

Yea, Hence controller its the main object which decides what should be fetch from models and sent to the views. +1
+1 A controller is called a controller for a reason. Its job is to control input (a session variable in that case) and pass it to the appropriate handler (view, model, library, etc.).
An additional note is that I think you should be using a "wrapper" class called something like "Session" which embodies all of the functionality of getting/setting session variables. That way you can switch over to using something like memcache with little effort by changing it in one file/class.
6

You NEVER want to have session variables in your model. You should always pass these variables as parameters to the function in the model. This also makes your code more expandable and flexible. Consider a model that gets a user by their id. You may write a function like:

function find_by_id() {
  // SELECT * FROM Users WHERE user_id = $_SESSION['user_id'];
}

However, what if you now what to build an admin functionality with a user lookup feature? Your model is hardcoded to use the session's user_id, but you want to be able to pass your own id. You would be better off:

function find_by_id($id) {
  // SELECT * FROM Users WHERE user_id = $id
}

and in your controller

$user = Model::find_by_id(1);
//or
$user = Model::find_by_id($_SESSION['user_id']);
//etc

In this case, however, I would really consider making your code even MORE flexible:

function find($ids) {
  // this is pseudo code, but you get the idea
  if(is_array($ids))
    $ids = implode(',', $ids); // if an array of ids was passed, implode them with commas
  SELECT * FROM Users WHERE user_id IN ($ids);
}

This allows you to get multiple users in ONE query! Which is way more efficient. Then, in your view:

foreach($users as $user){
  // iterate over each user and do stuff
}

You should also consider using a singelton class for a User to limit database load. Create a non-changing instance class called CurrentUser (for example) like:

class CurrentUser {

  private static $user;

  // we never instantiate it -its singleton
  private function __construct() {}

  public function user() {
    return self::$user;
  }

}

This is a really basic example of a singleton class and is missing a lot of stuff. If you want to know more about singleton classes, post another question.

Comments

1

Keep in mind that "session" is just yet another model. However first approach is unacceptable - what if you would like to fetch another users preferences just to compare them with something? Use the second approach.

Comments

0

I agree with Seth re. "You should also consider using a singelton class for a User to limit database load. Create a non-changing instance class called CurrentUser".

In my pseudo-MVC app I have class User (meaning current user) with methods for session, getting user info, roles etc., and class Member (meaning any given user) with methods for registering new users, getting/updating their properties etc but nothing to do with sessions, for example. Also, it is a singleton scenario, so current user is static and does not require much interaction with the DB.

So in my case, my controller and views make calls to User methods, e.g.

User::getId() or User::getGroups().

3 Comments

I'm confused why a singleton has less interaction with the db? You still have to create this object on page load, correct?
It doesn't change how often it interacts with DB. Advantage of singleton is you don't have to __construct it every time. So it works for objects that have to be created only once in the application, e.g. CurrentUser. It won't work for making a list of many users though as you'd have to create instance of the class for each of them.
@mvblfst Using a caching dependency injector container might be even better,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.