一、什么是MVC
MVC,Model-View-Controller的简写,是软件工程中是一种软件的架构模式。它是一种编程思想,是一种设计模式。这种模式可以使网站的目录结构更加清晰,网站更易维护与扩展。
二、MVC的作用和目的
MVC的主要作用是为了将代码分层、分类。主要目的是为了解决Web开发中分离开发与设计工作,使其工作相对独立,便于后续对程序的修改和扩展简化,并且可以实现模块的复用。
三、MVC各部分的职能
Model(模型M):管理大部分的业务逻辑和所有的数据库逻辑。模型提供了连接和操作数据库的抽象层。在PHP中负责数据管理,数据生成。
View(视图V):图形界面逻辑。在PHP中负责输出,处理如何调用模板、需要的资源文件。通俗的说,就是负责渲染数据,通过HTML方式呈现给用户。
Controller(控制器C):负责响应用户请求、准备数据,以及决定如何展示数据。
四、MVC的实现
建立Model模型
代码演示:
<?php
namespace mvc_demo;
class Model
{
public function getData()
{
return (new \PDO('mysql:host=localhost;dbname=phpedu', 'root','root'))
->query('SELECT * FROM `staffs` LIMIT 10')
->fetchAll(\PDO::FETCH_ASSOC);
}
}
// print_r((new Model)->getData());//打印测试数据
建立View视图
代码演示:
<?php
namespace mvc_demo;
class View
{
public function fetch($data)
{
$table = '<table>';
$table .= '<caption>员工信息表</caption>';
$table .= '<tr><th>ID</th><th>姓名</th><th>性别</th><th>职务</th><th>手机号</th><th>入职时间</th></tr>';
// 将数据循环遍历出来
foreach ($data as $staff) {
$table .= '<tr>';
$table .= '<td>' . $staff['id'] . '</td>';
$table .= '<td>' . $staff['name'] . '</td>';
$table .= '<td>' . ($staff['sex'] ? '男' : '女') . '</td>';
$table .= '<td>' . $staff['position'] . '</td>';
$table .= '<td>' . $staff['mobile'] . '</td>';
$table .= '<td>' . date('Y年m月d日', $staff['hiredate']) . '</td>';
$table .= '</tr>';
}
$table .= '</table>';
return $table;
}
}
echo '<style>
table {border-collapse: collapse; border: 1px solid;text-align: center; width: 500px;height: 150px;width: 600px;}
caption {font-size: 1.2rem; margin-bottom: 10px;}
tr:first-of-type { background-color:wheat;}
td,th {border: 1px solid; padding:5px}
</style>';
// require 'Model.php';
// echo (new View)->fetch((new Model)->getData());//打印测试数据
建立Controller控制器
代码演示:
<?php
namespace mvc_demo;
// 1. 加载模型类
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制
class Controller1
{
public function index()
{
// 1. 获取数据
$model = new Model;
$data = $model->getData();
// 2. 渲染模板/视图
$view = new View;
return $view->fetch($data);
}
}
// 客户端
// 实例化控制器类
$controller = new Controller1;
echo $controller->index();
输出效果:
五、MVC中的控制器对外部对象的两种依赖注入方式
上例中,虽然我们实现了控制器对模型和视图的关联,但是这种关联方式使得控制器对模型和视图两个类的过分依赖。而为了避免控制器过度依赖外部对象的问题,MVC中的控制器对外部对象提供了两种依赖注入方式:方法的依赖注入和构造函数的依赖注入。
1. 方法依赖注入
代码演示:
<?php
namespace mvc_demo;
// 控制器1
// 1. 加载模型类
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制
class Controller2
{
public function index(Model $model, View $view)//通过参数的方式注入到index方法中
{
// 1. 获取数据
$data = $model->getData();
// 2. 渲染模板/视图
return $view->fetch($data);
}
public function index2(Model $model, View $view)
{
}
}
// 客户端//
$model = new Model;
$view = new View;
// 实例化控制器类
$controller = new Controller2;
echo $controller->index($model, $view);
2. 构造函数的依赖注入
代码演示:
<?php
namespace mvc_demo;
// 1. 加载模型类
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制
class Controller3
{
// 依赖对象属性
private $model;
private $view;
//构造方法
public function __construct(Model $model,View $view)
{
$this->model = $model;
$this ->view = $view;
}
public function index()
{
// 1. 获取数据
$data = $this->model-> getData();
// 2. 渲染模板/视图
return $this->view -> fetch($data);
}
public function index2()
{
// 1. 获取数据
$data = $this->model-> getData();
// 2. 渲染模板/视图
return $this->view -> fetch($data);
}
}
// 客户端
$model = new Model;
$view = new View;
// 实例化控制器类
$controller = new Controller3($model,$view);
echo $controller->index($model,$view);
输出效果:
六、MVC与服务容器
虽然上面两种注入方式都可以解除控制器的耦合度问题,但是随着项目的扩大,代码量的增加,其缺点也会突显出来:一是需要修改大量代码,二是对程序员的知识储备要求很高,他需要看很多其他类文档,一个个的创建类,才有可能创建出程序员需要的变量。那么有没有一种方法,既可以简化代码,又可以在整个程序运行期间,随时可以调用,且程序员不用知道这个类太多的细节,甚至可以用一个字符串的别名来创建这样一个对象。答案是有的,它就是container服务容器,我们可以把容器简单的看成一个全局变量,并用关联数组把字符串和构造函数做绑定,轻松解决控制器的耦合度的相关问题。
代码演示:
<?php
namespace mvc_demo;
require 'Model.php';
require 'View.php';
// 创建服务容器
class Container1
{
// 创建对象容器
protected $instances = [];
// 绑定: 向对象容器中添加一个类实例(类实例的别名alias)
public function bind($alias, \Closure $process)
{
$this->instances[$alias] = $process;
}
// 取出: 从容器中取出一个类实例 (new)
public function make($alias, $params = [])
{
return call_user_func_array($this->instances[$alias], []);
}
}
$container = new Container1;
// 绑定
$container->bind('model', function () {return new Model;});
$container->bind('view', function () {return new View;});
//创建控制器
class Controller4
{
public function index(Container1 $container)
{
// 1. 获取数据
$data = $container->make('model')->getData();
// 2. 渲染模板/视图
return $container->make('view')->fetch($data);
}
}
// 客户端
// 实例化控制器类
$controller = new Controller4();
echo $controller->index($container);
//追加销毁
unset($controller);
echo '销毁了';
echo '<hr>';
总结:
1.MVC模式通过对复杂程序的简化,使程序结构更加直观。但是,对于像个人博客等轻量级的网站,使用MVC则会将简单的问题复杂化。所以在实际工作中,是否需要使用MVC模式,需要根据情况而定。
2.通过MVC模式自制框架,每个人都可以完全控制自己的框架,将自己的想法融入到自制的框架中。自己掌握主动权当然是好的。
3.解决问题的方法是没有绝对好的工具,只有相对优秀的解决方案,我们不能说服务容器是完美无缺的,每一种工具都有它的优缺点,而我们所要做的便是在实际使用中扬长避短。