ASCII码 ASCII码

MVC架构之模型/视图/控制器/容器/门面(静态化容器里面的方法)

发布于:2022-02-27 10:38:35  栏目:技术文档

这里算详解了MVC架构的构建思路,mvc通称模型视图控制器,但是详解后一般为模型,视图,控制器,容器门面,他们的相应关系是模型是后端接收视图层的命令,控制器为模型跟视图层的交换数据,而容器呢,是将控制器中的方法盛放到容器中,让方法稳定一下来,而门面呢,是进一步将容器中的方法静态化,方便更好的调佣,画了一个流程图:

贴全部代码:

模型文件:

  1. <?php
  2. namespace chloe\app;
  3. use pdo;
  4. class Model
  5. {
  6. public function getData()
  7. {
  8. return (new PDO('mysql:host=localhost;charset=utf8;dbname=phpcn', 'root', '123456', [PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING]))->query('SELECT `cou_id`,`title`,`pic`,`info`,`add_time`FROM `mj_course_lists` ORDER BY `cou_id` DESC LIMIT 6')->fetchAll();
  9. }
  10. public function editData()
  11. {
  12. }
  13. }
  14. // 模型文件
  15. // 获取模型数据
  16. // var_dump((new Model)->getData());

视图文件:

  1. <?php
  2. namespace chloe\app;
  3. // require 'Model.php';
  4. class View
  5. {
  6. public function fetch($data)
  7. {
  8. // .= shi 组合相加
  9. $table = '<table border="1" cellspacing="0" cellpadding="5" align="center">';
  10. $table .= '<caption>课程信息表</caption>';
  11. $table .= '
  12. <tr align="center">
  13. <td>编号</td>
  14. <td>名称</td>
  15. <td>封面</td>
  16. <td>课程简介</td>
  17. <td>创建时间</td>
  18. <td>操作</td>
  19. </tr>
  20. ';
  21. foreach ($data as $list) {
  22. // foreach遍历data的数据
  23. $table .= '<tr>';
  24. $table .= '<td>' . $list['cou_id'] . '</td>';
  25. $table .= '<td>' . $list['title'] . '</td>';
  26. $table .= "<td><img style='width:100px' src='{$list['pic']}' alt='课程封面' ></td>";
  27. $table .= '<td>' . $list['info'] . '</td>';
  28. $table .= '<td>' . date("Y-m-d H:m:s", $list['add_time']) . '</td>';
  29. $table .= '<td><button>删除</button>&nbsp;<button>编辑</button> </td>';
  30. $table .= '</tr>';
  31. }
  32. $table .= '</table>';
  33. return $table;
  34. }
  35. }
  36. // $data = (new Model)->getData();
  37. // echo (new View)->fetch($data);

控制器文件:控制器文件是视图层跟模型层的数据交换层:

  1. <?php
  2. namespace chloe\app;
  3. // 类的自动加载
  4. require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
  5. // 控制器引入静态模型跟静态视图模型
  6. use chloe\facade\Facade;
  7. use chloe\facade\FacadeModel;
  8. use chloe\facade\FacadeView;
  9. class Controller3
  10. {
  11. public function __construct($container)
  12. {
  13. // 这里是第四版,第三版是将注入方法放到了构造器中,而第四版也是放到了构造器中,但是是一个静态调用方法
  14. // 容器的初始化赋值操作 将门面中的方法传值 调用Facade类里面的静态方法 传入值
  15. Facade::initialize($container);
  16. }
  17. public function index()
  18. {
  19. //获取数据
  20. // 传入值后调用容器中的make方法 也就是将实例化的new Model当做一个别名model
  21. $data = FacadeModel::getData();
  22. //渲染数据
  23. return FacadeView::fetch($data);
  24. }
  25. }
  26. // 客户端代码
  27. $container = new Container;
  28. // bind()方法中传入一个model值是实例化的 new model
  29. // 上面先实例化,实例化后再下面绑定到bind方法的数组中 也就是绑定的model类跟view类
  30. $container->bind('model', function () {
  31. return new Model;
  32. });
  33. $container->bind('view', function () {
  34. return new View;
  35. });
  36. // 上面将model跟view实例绑定到$container容器中,也就是传入到值的方法中
  37. $c3 = new Controller3($container);
  38. echo $c3->index();

容器层:将视图层的方法统一放到容器中管理:

  1. <?php
  2. /***
  3. * 如果当前类锁依赖的外部对象过多,名称很长,将依赖的所有外部对象放到一个容器中进行统一管理。并且可以起名
  4. *
  5. *
  6. *
  7. */
  8. namespace chloe\app;
  9. use Closure;
  10. //将容器里面的对象放到一个数组中,用于存放外部依赖的多个对象,把容器当做一个数组,数组的下键就是别名,值就是外部对象,依赖的对象
  11. //服务容器 一个产生对象的工厂 自动生产类,对象的工厂
  12. class Container
  13. {
  14. //对象容器
  15. protected $instances = [];
  16. /**
  17. * 绑定一个类标识、闭包、实例到容器
  18. * @access public
  19. * @param string|array $abstract 类标识或者接口的别名 alias
  20. * @param mixed $concrete 要绑定的类、闭包或者实例
  21. *
  22. */
  23. //往容器数组中绑定对象 $concrete是绑定的闭包 Closure闭包
  24. public function bind($abstract, Closure $concrete) //第一个参数是别名 第二个参数,是具体绑定的对象
  25. {
  26. // 将值赋值给数组, $abstract是数组的键, $concrete是数组的值
  27. $this->instances[$abstract] = $concrete;
  28. }
  29. //下面是取值
  30. public function make($abstract, $params = [])
  31. {
  32. // 刚刚在上面绑定了一个闭包函数方法,已经将闭包函数方法赋值给了 $instances
  33. // 第二个是传入的参数
  34. return call_user_func_array($this->instances[$abstract], $params);
  35. }
  36. }

门面:下面的门面是写一个静态化方法,赋值给静态化属性,将方法赋值给静态化属性,也就是将模型层跟视图层静态化

  1. <?php
  2. namespace chloe\facade;
  3. //引入容器
  4. use chloe\app\Container;
  5. // 类的自动加载
  6. require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
  7. // facade 门面是为容器中的动态类 提供一个静态调用接口,相比于传统的静态方法调用,带来更好的可测试性和扩展性,facade就是服务容器
  8. // 和控制器之间加一个中间层
  9. //引入容器
  10. //将容器方法静态化
  11. class Facade
  12. {
  13. //为容器中动态类提供静态调用接口
  14. // 在门面中将容器的方法静态化处理
  15. protected static $container;
  16. // 接收容器 return的值也就是一个数组
  17. public static function initialize(Container $container)
  18. { //门面将属性方法静态化 也就是将数组静态化调用
  19. static::$container = $container;
  20. }
  21. }

进一步将模型层静态化:

  1. <?php
  2. namespace chloe\facade;
  3. class FacadeModel extends Facade
  4. {
  5. //模型类成员方法 getData()的访问静态化
  6. public static function getData()
  7. {
  8. //使用门面静态方法链式调用 方法为getData make是继承过来的 Facade类中继承过来的chloe\app\Container方法
  9. return static::$container->make('model')->getData();
  10. }
  11. }

进一步将视图层静态化:

  1. <?php
  2. namespace chloe\facade;
  3. class FacadeView extends Facade
  4. {
  5. public static function fetch($data)
  6. {
  7. // 利用门面将容器中的方法静态化处理 方法为fetch fetch是继承过来的 Facade类中继承过来的chloe\app\Container类中的fetch方法
  8. return static::$container->make('view')->fetch($data);
  9. }
  10. }
相关推荐
阅读 +