基于PHP MVC实现单视图调用双模型及动态JOIN查询
MVC架构下多模型动态关联查询实现方案
按照MVC规范,模型负责数据逻辑、控制器协调数据流转、视图仅做展示,要在单个视图中使用两个模型的关联数据,核心是在控制器中调用模型的关联查询方法,将处理好的数据传递给视图,而不是直接在视图中操作模型。以下是基于你需求的具体实现:
1. 完善两个基础模型
给每个模型封装通用条件查询方法,同时在其中一个模型中实现动态JOIN关联逻辑(这里选择JoinClassModel承载关联逻辑,因为它是用户和班级的中间关联表):
UserModel(用户模型)
class UserModel { protected $table = 'users'; protected $db; // 数据库连接实例(PDO/MySQLi等) public function __construct($db) { $this->db = $db; } // 通用单表条件查询 public function getWithConditions($conditions = []) { $query = "SELECT * FROM {$this->table}"; if (!empty($conditions)) { $query .= " WHERE "; $clauses = []; foreach ($conditions as $key => $value) { $clauses[] = "{$key} = :{$key}"; } $query .= implode(" AND ", $clauses); } $query .= " ORDER BY id"; $stmt = $this->db->prepare($query); $stmt->execute($conditions); return $stmt->fetchAll(PDO::FETCH_ASSOC); } }
JoinClassModel(用户班级关联模型)
class JoinClassModel { protected $table = 'join_class'; protected $db; public function __construct($db) { $this->db = $db; } // 通用单表条件查询 public function getWithConditions($conditions = []) { $query = "SELECT * FROM {$this->table}"; if (!empty($conditions)) { $query .= " WHERE "; $clauses = []; foreach ($conditions as $key => $value) { $clauses[] = "{$key} = :{$key}"; } $query .= implode(" AND ", $clauses); } $query .= " ORDER BY id"; $stmt = $this->db->prepare($query); $stmt->execute($conditions); return $stmt->fetchAll(PDO::FETCH_ASSOC); } // 动态关联User的查询方法,支持自定义关联条件和过滤条件 public function getJoinedWithUsers($joinConditions = [], $filterConditions = [], $joinType = 'JOIN') { // 初始化JOIN语句 $query = "SELECT u.*, j.class_id, j.id AS join_id FROM {$this->table} j {$joinType} users u ON "; // 拼接关联条件(比如j.user_id = u.id) $joinClauses = []; foreach ($joinConditions as $leftKey => $rightKey) { $joinClauses[] = "{$leftKey} = {$rightKey}"; } $query .= implode(" AND ", $joinClauses); // 拼接过滤条件(比如指定class_id或user_id) if (!empty($filterConditions)) { $query .= " WHERE "; $filterClauses = []; foreach ($filterConditions as $key => $value) { $filterClauses[] = "{$key} = :{$key}"; } $query .= implode(" AND ", $filterClauses); } $query .= " ORDER BY u.id, j.class_id"; $stmt = $this->db->prepare($query); $stmt->execute($filterConditions); return $stmt->fetchAll(PDO::FETCH_ASSOC); } }
2. 控制器协调数据,传递给视图
控制器负责实例化模型、调用关联查询方法,将最终数据传递给视图:
class UserClassController { protected $userModel; protected $joinClassModel; public function __construct($db) { $this->userModel = new UserModel($db); $this->joinClassModel = new JoinClassModel($db); } // 示例:获取ID为19的用户关联的所有班级 public function getUserAssignedClasses() { // 定义关联条件(关联join_class的user_id和users的id) $joinConditions = [ 'j.user_id' => 'u.id' ]; // 定义过滤条件(筛选user_id=19的记录) $filterConditions = [ 'j.user_id' => 19 ]; // 调用动态关联查询方法 $userClassData = $this->joinClassModel->getJoinedWithUsers($joinConditions, $filterConditions); // 将数据传递给视图 require './views/user_classes_view.php'; } }
3. 视图展示数据
视图仅负责渲染控制器传递过来的数据,不做任何数据逻辑处理:
<h3>用户关联班级列表</h3> <table border="1"> <thead> <tr> <th>用户ID</th> <th>姓名</th> <th>班级ID</th> </tr> </thead> <tbody> <?php foreach ($userClassData as $item): ?> <tr> <td><?= htmlspecialchars($item['id']) ?></td> <td><?= htmlspecialchars($item['firstname'] . ' ' . $item['lastname']) ?></td> <td><?= htmlspecialchars($item['class_id']) ?></td> </tr> <?php endforeach; ?> </tbody> </table>
关键说明
- SQL注入防护:所有过滤条件都使用参数绑定(
:key),避免直接拼接变量导致注入风险,符合安全规范。 - 灵活性:通过传递不同的
joinConditions和filterConditions,可以实现任意场景的关联查询,比如筛选特定班级的用户、左关联获取未分配班级的用户等。 - MVC合规性:模型专注数据逻辑,控制器做协调,视图只负责展示,完全符合MVC架构的职责划分。
内容的提问来源于stack exchange,提问作者Sizwe
相关产品推荐
相关产品推荐

