PHP MVC 最佳实践 - 将会话变量从控制器传递到模型类或直接在模型中访问

我们的开发团队正在讨论一个一般的最佳实践:直接从模型类中的函数访问会话变量,还是将会话变量作为参数从控制器传递给模型类中的函数更好。请看下面的两个示例:

直接从模型类访问会话变量以在查询中使用:

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

或者将会话变量从控制器传递到模型类中的函数作为函数参数:

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");
    }
}

将其从控制器传递到模型的原因是,引用的所有数据都来自一个入口点,即控制器。

什么是公认的更好的做法?


答案 1

第二个版本(将 $_SESSION['userId'] 作为参数传递给方法)会导致类更加解耦,因此更加灵活。随它去吧。


答案 2

您永远不希望在模型中包含会话变量。应始终将这些变量作为参数传递给模型中的函数。这也使您的代码更具可扩展性和灵活性。考虑一个通过 id 获取用户的模型。你可以写一个函数,比如:

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

但是,如果您现在使用用户查找功能构建管理功能,该怎么办?您的模型已硬编码为使用会话的user_id,但您希望能够传递自己的 ID。你最好:

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

和控制器中

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

但是,在这种情况下,我真的会考虑使您的代码更加灵活:

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);
}

这允许您在一个查询中获取多个用户!这是更有效的。然后,在您看来:

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

您还应考虑对 User 使用 singelton 类来限制数据库负载。创建一个名为 CurrentUser 的不可更改的实例类(例如),如下所示:

class CurrentUser {

  private static $user;

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

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

}

这是一个非常基本的单例类示例,缺少很多东西。如果您想了解有关单例类的更多信息,请发布另一个问题。


推荐