一、MVC设计模式概述
1.什么是MVC设计模式 2. MVC设计模式的优势和缺点
二、 MVC典型实现
1.模型 数据库操作类 模型类 2.控制器 模块 控制器类 3.视图 4.前端控制器(入口文件)
一、MVC设计模式概述
1.什么是MVC设计模式
MVC是Xerox PRAC(施乐帕克研究中心)在80年代为编程语言 Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。MVC设计模式强制性的使应用程序中的输入、处理和输出分开,将软件系统分成了三个核心部件:模型(Model)、视图(View)、控制器(Controller) 它们各自处理自己的任务。MVC是一种开发设计规范,使代码组织更加合理、流程更加清晰ThinkPHP框架是基于MVC模式来做为基本运行流程,因此,MVC部分一定要理解掌握,以便于后续的框架学习。
##### 2. MVC设计模式的优势和缺点 1)优点: 各司其职、互不干涉; 有利于开发中的分工; 有利于组建的重用;
2)缺点: 系统结构和实现复杂; 视图与控制器过于紧密; 不适用于小型甚至中型应用程序;
二、 MVC典型实现
创建模型,生成并返回数据创建控制器,将模型和视图整合创建视图,展示模型生成并返回的数据创建入口文件,调用控制器完成操作
1.创建模型,生成并返回数据
在面对复杂问题时,面向对象编程可以更好的描述现实中的业务逻辑,所以MVC的程序也是通过面向对象的方式实现的m模型是处理数据的,而数据是存储在数据库里的。在项目中,所有对数据库的直接操作,都应该封装到一个数据库操作类中。 运用学过的面向对象、单例模式、PDO等相关知识,就可以封装一个PDO的数据库操作类。
1)封装一个PDO数据库操作类(Db.php)
/**
* PDO-MySQL数据库操作类
*/
class MySQLPDO{
//数据库默认连接信息
private $dbConfig = array(
'db' => 'mysql', //数据库类型
'host' => 'localhost', //服务器地址
'port' => '3306', //端口
'user' => 'root', //用户名
'pass' => 'weicunbin123', //密码
'charset' => 'utf8', //字符集
'dbname' => 'testguest', //默认数据库
);
//单例模式 本类对象引用
private static $instance;
//PDO实例
private $db;
/**
* 私有构造方法
* @param $params array 数据库连接信息
*/
private function __construct($params){
//初始化属性
$this->dbConfig = array_merge($this->dbConfig,$params);
//连接服务器
$this->connect();
}
/**
* 获得单例对象
* @param $params array 数据库连接信息
* @return object 单例的对象
*/
public static function getInstance($params = array()){
if(!self::$instance instanceof self){
self::$instance = new self($params);
}
return self::$instance; //返回对象
}
/**
* 私有克隆
*/
private function __clone() {}
/**
* 连接目标服务器
*/
private function connect(){
try{
//连接信息
$dsn = "{$this->dbConfig['db']}:host={$this->dbConfig['host']};port={$this->dbConfig['host']};dbname={$this->dbConfig['dbname']};charset={$this->dbConfig['charset']}";
//实例化PDO
$this->db = new PDO($dsn,$this->dbConfig['user'],$this->dbConfig['pass']);
//设定字符集
$this->db->query("set names {$this->dbConfig['charset']}");
echo 1;
}catch (PDOException $e){
//错误提示
die("数据库操作失败:{$e->getMessage()}");
}
}
/**
* 执行SQL
* @param $sql string 执行的SQL语句
* @return object PDOStatement
*/
public function query($sql){
$rst = $this->db->query($sql);
if($rst===false){
$error = $this->db->errorInfo();
die("数据库操作失败:ERROR {$error[1]}({$error[0]}): {$error[2]}");
}
return $rst;
}
/**
* 取得一行结果
* @param $sql string 执行的SQL语句
* @return array 关联数组结果
*/
public function fetchRow($sql){
return $this->query($sql)->fetch(PDO::FETCH_ASSOC);
}
/**
* 取得所有结果
* @param $sql string 执行的SQL语句
* @return array 关联数组结果
*/
public function fetchAll($sql){
return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
public function demo(){
echo '测试内容';
}
}
// // 调用方式
// // 连接数据库
// $pdo = MySQLPDO::getInstance();
// // 调用方法
// $pdo -> demo()
2)模型类 在实际项目中,通常是在一个数据库中建立多个表来管理数据,如下图。MVC中的模型,其实就是为项目中的每个表建立一个模型。如果用面向对象的思想,那么每个模型都是一个模型类,对表的所有操作,都要放到模型类中完成。
前面学习了数据库操作类,实例化数据库操作类是所有模型类都要经历的一步,因此需要一个基础模型类来完成这个任务。
例:
创建基础模型类:创建Student模型类
/**
* 基础模型类
*/
class model {
protected $db; //保存数据库对象
public function __construct(){
$this->initDB(); // 初始化数据库
}
private function initDB(){
//配置数据库连接信息
$dbConfig = array('dbname'=>'mvc_study');
//实例化数据库操作类
$this->db = MySQLPDO::getInstance($dbConfig);
}
}
/**
* student表的操作类,继承基础模型类
*/
class studentModel extends model{
/* 查询所有学生 */
public function getAll(){
$data = $this->db->fetchAll('select * from `student`');
return $data;
}
/* 查询指定id的学生 */
public function getByID($id){
$data = $this->db->fetchRow("select * from `student` where id={$id}");
return $data;
}
}
3、创建控制器,将模型和视图整合
控制器是MVC应用程序中的指挥官,它接收用户的请求,并决定需要调用哪些模型进行处理,再用相应的视图显示从模型返回的数据,最后通过浏览器呈现给用户。 1)模块 如果用面向对象的方式实现控制器,就需要先理解模块(Module)的概念。一个成熟的项目是由多个模块组成的,每个模块又是一系列相关功能的集合。接下来通过一个图例来演示项目中的模块,如图所示: 2)控制器类 控制器是根据模块创建的,即每个模块对应一个控制器类 创建StudentController.class.php控制器类,实现的功能:
查看所有学生信息查看指定学生信息
/*
* @Descripttion:
* @version:
* @Author: wei
* @Date: 2020-04-09 10:23:14
* @LastEditors: wei
* @LastEditTime: 2020-04-17 16:23:37
*/
/**
* 学生模块控制器类
*/
class studentController{
/**
* 学生列表
*/
public function listAction(){
//实例化模型,取出数据
$stu = new studentModel();
$data = $stu->getAll();
//载入视图文件
require 'student_list.html';
}
/**
* 查看指定学生信息
*/
public function infoAction(){
//接收请求参数
$id = $_GET['id'];
//实例化模型,取出数据
$stu = new studentModel();
$data = $stu->getById($id);
//载入视图文件
require 'student_info.html';
}
}
3)视图文件 根据控制器类要实现的功能方法,创建视图文件,这里没有创建,直接打印出数据代替了
查看所有学生信息视图文件:student_list.html查看指定学生信息视图文件:student_info.htmlstudent_list.html
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
table{border-collapse:collapse;text-align:center;}
a{text-decoration:none;}
学生列表
| ID | 姓名 | 操作 |
|---|---|---|
| 查看 |
student_info.html
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
table{border-collapse:collapse;text-align:center;}
a{text-decoration:none;}
查看学生信息
| ID | |
|---|---|
| 姓名 | |
| 性别 | |
| 年龄 |
5、前端控制器(入口文件index.php)
前端控制器也称为请求分发器(dispather),通过URL参数判断用户请求了哪个功能,然后完成相关控制器的加载、实例化、方法调用等操作。 使用MVC开发的是一种单一入口的应用程序,传统的Web程序是多入口的,即通过访问不同的文件来完成用户请求。 例如教务管理系统,管理学生时访问student.php,管理教师时访问teacher.php。 单入口程序只有一个index.php提供用户访问。
/**
* 前端控制器
*/
header('Content-Type:text/html; charset=utf8');
//载入数据库操作类
require('MySQLPDO.class.php');
//载入模型文件
require 'model.class.php';
require 'studentModel.class.php';
//得到控制器名
$c = isset($_GET['c']) ? $_GET['c'] : 'student';
//载入控制器文件
require './'.$c.'Controller.class.php';
//实例化控制器(可变变量)
$controller_name = $c.'Controller';
$controller = new $controller_name;
//得到方法名
$action = isset($_GET['a']) ? $_GET['a'] : 'list';
//调用方法(可变方法)
$action_name = $action.'Action';
$controller->$action_name();
效果展示