博客列表 >PHP中的MVC原理与实现及服务容器

PHP中的MVC原理与实现及服务容器

蔚蓝世纪
蔚蓝世纪原创
2020年05月18日 13:49:14599浏览

一、什么是MVC

MVC,Model-View-Controller的简写,是软件工程中是一种软件的架构模式。它是一种编程思想,是一种设计模式。这种模式可以使网站的目录结构更加清晰,网站更易维护与扩展。

二、MVC的作用和目的

MVC的主要作用是为了将代码分层、分类。主要目的是为了解决Web开发中分离开发与设计工作,使其工作相对独立,便于后续对程序的修改和扩展简化,并且可以实现模块的复用。

三、MVC各部分的职能

  1. Model(模型M):管理大部分的业务逻辑和所有的数据库逻辑。模型提供了连接和操作数据库的抽象层。在PHP中负责数据管理,数据生成。
  2. View(视图V):图形界面逻辑。在PHP中负责输出,处理如何调用模板、需要的资源文件。通俗的说,就是负责渲染数据,通过HTML方式呈现给用户。
  3. Controller(控制器C):负责响应用户请求、准备数据,以及决定如何展示数据。

四、MVC的实现

建立Model模型
代码演示:
  1. <?php
  2. namespace mvc_demo;
  3. class Model
  4. {
  5. public function getData()
  6. {
  7. return (new \PDO('mysql:host=localhost;dbname=phpedu', 'root','root'))
  8. ->query('SELECT * FROM `staffs` LIMIT 10')
  9. ->fetchAll(\PDO::FETCH_ASSOC);
  10. }
  11. }
  12. // print_r((new Model)->getData());//打印测试数据
建立View视图
代码演示:
  1. <?php
  2. namespace mvc_demo;
  3. class View
  4. {
  5. public function fetch($data)
  6. {
  7. $table = '<table>';
  8. $table .= '<caption>员工信息表</caption>';
  9. $table .= '<tr><th>ID</th><th>姓名</th><th>性别</th><th>职务</th><th>手机号</th><th>入职时间</th></tr>';
  10. // 将数据循环遍历出来
  11. foreach ($data as $staff) {
  12. $table .= '<tr>';
  13. $table .= '<td>' . $staff['id'] . '</td>';
  14. $table .= '<td>' . $staff['name'] . '</td>';
  15. $table .= '<td>' . ($staff['sex'] ? '男' : '女') . '</td>';
  16. $table .= '<td>' . $staff['position'] . '</td>';
  17. $table .= '<td>' . $staff['mobile'] . '</td>';
  18. $table .= '<td>' . date('Y年m月d日', $staff['hiredate']) . '</td>';
  19. $table .= '</tr>';
  20. }
  21. $table .= '</table>';
  22. return $table;
  23. }
  24. }
  25. echo '<style>
  26. table {border-collapse: collapse; border: 1px solid;text-align: center; width: 500px;height: 150px;width: 600px;}
  27. caption {font-size: 1.2rem; margin-bottom: 10px;}
  28. tr:first-of-type { background-color:wheat;}
  29. td,th {border: 1px solid; padding:5px}
  30. </style>';
  31. // require 'Model.php';
  32. // echo (new View)->fetch((new Model)->getData());//打印测试数据
建立Controller控制器
代码演示:
  1. <?php
  2. namespace mvc_demo;
  3. // 1. 加载模型类
  4. require 'Model.php';
  5. // 2. 加载视图
  6. require 'View.php';
  7. // 3. 创建控制
  8. class Controller1
  9. {
  10. public function index()
  11. {
  12. // 1. 获取数据
  13. $model = new Model;
  14. $data = $model->getData();
  15. // 2. 渲染模板/视图
  16. $view = new View;
  17. return $view->fetch($data);
  18. }
  19. }
  20. // 客户端
  21. // 实例化控制器类
  22. $controller = new Controller1;
  23. echo $controller->index();
输出效果:

五、MVC中的控制器对外部对象的两种依赖注入方式

上例中,虽然我们实现了控制器对模型和视图的关联,但是这种关联方式使得控制器对模型和视图两个类的过分依赖。而为了避免控制器过度依赖外部对象的问题,MVC中的控制器对外部对象提供了两种依赖注入方式:方法的依赖注入和构造函数的依赖注入。
1. 方法依赖注入
代码演示:
  1. <?php
  2. namespace mvc_demo;
  3. // 控制器1
  4. // 1. 加载模型类
  5. require 'Model.php';
  6. // 2. 加载视图
  7. require 'View.php';
  8. // 3. 创建控制
  9. class Controller2
  10. {
  11. public function index(Model $model, View $view)//通过参数的方式注入到index方法中
  12. {
  13. // 1. 获取数据
  14. $data = $model->getData();
  15. // 2. 渲染模板/视图
  16. return $view->fetch($data);
  17. }
  18. public function index2(Model $model, View $view)
  19. {
  20. }
  21. }
  22. // 客户端//
  23. $model = new Model;
  24. $view = new View;
  25. // 实例化控制器类
  26. $controller = new Controller2;
  27. echo $controller->index($model, $view);
2. 构造函数的依赖注入
代码演示:
  1. <?php
  2. namespace mvc_demo;
  3. // 1. 加载模型类
  4. require 'Model.php';
  5. // 2. 加载视图
  6. require 'View.php';
  7. // 3. 创建控制
  8. class Controller3
  9. {
  10. // 依赖对象属性
  11. private $model;
  12. private $view;
  13. //构造方法
  14. public function __construct(Model $model,View $view)
  15. {
  16. $this->model = $model;
  17. $this ->view = $view;
  18. }
  19. public function index()
  20. {
  21. // 1. 获取数据
  22. $data = $this->model-> getData();
  23. // 2. 渲染模板/视图
  24. return $this->view -> fetch($data);
  25. }
  26. public function index2()
  27. {
  28. // 1. 获取数据
  29. $data = $this->model-> getData();
  30. // 2. 渲染模板/视图
  31. return $this->view -> fetch($data);
  32. }
  33. }
  34. // 客户端
  35. $model = new Model;
  36. $view = new View;
  37. // 实例化控制器类
  38. $controller = new Controller3($model,$view);
  39. echo $controller->index($model,$view);
输出效果:

六、MVC与服务容器

虽然上面两种注入方式都可以解除控制器的耦合度问题,但是随着项目的扩大,代码量的增加,其缺点也会突显出来:一是需要修改大量代码,二是对程序员的知识储备要求很高,他需要看很多其他类文档,一个个的创建类,才有可能创建出程序员需要的变量。那么有没有一种方法,既可以简化代码,又可以在整个程序运行期间,随时可以调用,且程序员不用知道这个类太多的细节,甚至可以用一个字符串的别名来创建这样一个对象。答案是有的,它就是container服务容器,我们可以把容器简单的看成一个全局变量,并用关联数组把字符串和构造函数做绑定,轻松解决控制器的耦合度的相关问题。

代码演示:
  1. <?php
  2. namespace mvc_demo;
  3. require 'Model.php';
  4. require 'View.php';
  5. // 创建服务容器
  6. class Container1
  7. {
  8. // 创建对象容器
  9. protected $instances = [];
  10. // 绑定: 向对象容器中添加一个类实例(类实例的别名alias)
  11. public function bind($alias, \Closure $process)
  12. {
  13. $this->instances[$alias] = $process;
  14. }
  15. // 取出: 从容器中取出一个类实例 (new)
  16. public function make($alias, $params = [])
  17. {
  18. return call_user_func_array($this->instances[$alias], []);
  19. }
  20. }
  21. $container = new Container1;
  22. // 绑定
  23. $container->bind('model', function () {return new Model;});
  24. $container->bind('view', function () {return new View;});
  25. //创建控制器
  26. class Controller4
  27. {
  28. public function index(Container1 $container)
  29. {
  30. // 1. 获取数据
  31. $data = $container->make('model')->getData();
  32. // 2. 渲染模板/视图
  33. return $container->make('view')->fetch($data);
  34. }
  35. }
  36. // 客户端
  37. // 实例化控制器类
  38. $controller = new Controller4();
  39. echo $controller->index($container);
  40. //追加销毁
  41. unset($controller);
  42. echo '销毁了';
  43. echo '<hr>';

总结:

1.MVC模式通过对复杂程序的简化,使程序结构更加直观。但是,对于像个人博客等轻量级的网站,使用MVC则会将简单的问题复杂化。所以在实际工作中,是否需要使用MVC模式,需要根据情况而定。
2.通过MVC模式自制框架,每个人都可以完全控制自己的框架,将自己的想法融入到自制的框架中。自己掌握主动权当然是好的。
3.解决问题的方法是没有绝对好的工具,只有相对优秀的解决方案,我们不能说服务容器是完美无缺的,每一种工具都有它的优缺点,而我们所要做的便是在实际使用中扬长避短。

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议