Blogger Information
Blog 43
fans 1
comment 0
visits 33966
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP中的MVC原理与实现及服务容器
蔚蓝世纪
Original
606 people have browsed it

一、什么是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.解决问题的方法是没有绝对好的工具,只有相对优秀的解决方案,我们不能说服务容器是完美无缺的,每一种工具都有它的优缺点,而我们所要做的便是在实际使用中扬长避短。

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:编程模型也是与时俱进的
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post