IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> php MVC+依赖注入+服务容器+Facade门面技术示例 -> 正文阅读

[开发测试]php MVC+依赖注入+服务容器+Facade门面技术示例

MVC传统方式

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写;

// MVC简单示例理解: 传统的调用方式

模型类: 数据库操作

class Model
{
    protected $db;
    // 连接数据库获取ID为1999的信息
    public function getData()
    {
        $this->db = new PDO('mysql:host=localhost;dbname=php_pro', 'root', 'root');
        return  $this->db->query('select * from users where id=1999')->fetchAll(PDO::FETCH_ASSOC);
    }
}

视图: 数据展示(相当于HTML输出的模板)

class View
{
    public function fetch($data)
    {
        $res='hello,我叫:'.$data[0]['username'].',我今年'.$data[0]['age'].'岁了!';
        return $res;
    }
}

控制器:通常是在获取模型(Model)中数据并交给视图(View)去显示

class Controller
{
        public function index()
        {
            // 1. 获取数据
            $model = new Model();
            $data = $model->getData();
            // 2. 渲染模板
            $view = new View();
            return $view->fetch($data);
        }
}

客户端调用(测试)

// 创建控制器实例/对象

$controller = new Controller();
echo $controller->index();

结果

输出:hello,我叫:老周,我今年36岁了!

**结论:**通过简单示例,可以理解MVC各自的作用,就是用控制器(Controller)获取模型(Model)中数据并交给视图(View)去显示; 耦合性高,比如上面 的MVC方案,控制器(Controller)中直接new()模型(Model)与视图(View)类,这种方法是最不可取的,控制器严重依赖外部的某些对象,这种现象就是大家常常听说过的: 代码的耦合度过高。

依赖注入

依赖注入就是用来处理类与类之间的依赖关系

改进方法

控制器:通常是在获取模型(Model)中数据并交给视图(View)去显示

class Controller
{
    //使用变量方式,以依赖注入方式解决代码的耦合度过高问题
    public function index($model, $view) 
    {
        // 1. 获取数据
        $data = $model->getData();
        // 2. 渲染模板
        return $view->fetch($data);
    }
}
// 客户端调用(测试)
// 创建控制器实例/对象
$model = new Model();
$view = new View();
$controller = new Controller();
//index方法传参方式(对象)->依赖注入
echo $controller->index($model, $view);

上面的代码,虽然比第一个好,但是还是问题多多,就是如果有众多方法,这用每一个都实例化,传参,繁琐也容易出问题,改动起来也不容易,

依赖注入改进

可以使用构造方法实现外部对象在当前类的共享/复用

// 控制器:通常是在获取模型(Model)中数据并交给视图(View)去显示
class Controller
{
    // 外部依赖的对象
    protected $model = null;
    protected $view = null;
    // 通过构造方法将外部对象初始化,实现了外部对象在当前类的共享/复用
    public function __construct($model, $view)
    {
        $this->model = $model;
        $this->view = $view;
    }
    //使用变量方式,以依赖注入方式解决代码的耦合度过高问题
    public function index() 
    {
        // 1. 获取数据
        $data = $this->model->getData();
        // 2. 渲染模板
        return $this->view->fetch($data);
    }
}
// 客户端调用(测试)
// 创建控制器实例/对象
$model = new Model();
$view = new View();
$controller = new Controller($model, $view);
echo $controller->index();

总结,上面的改进比第一个好了很多,但是还是不完美,如果更好的,更灵活的依赖注入呢

MVC+依赖注入+服务容器

Container.php | 服务容器(Container)

将依赖的外部对象,放到一个”服务容器”中进行统一管理;

使用4个文件分开进行示例:
| No |文件名称 |说明
|1|Container.php|服务容器(Container)
|2| Model.php |模型(Model)
|3|View.php|视图(View)
|4|Controller.php|控制器(Controller)

namespace mvc_demo;
class UsersContainer
{
     // 1. 对象容器
     protected $instances = [];
    // 2. 绑定一个类、闭包、实例、接口实现到容器
    // 参数1: 是外部对象在当前对象容器数组中的键名/别名
    // 参数2: 是当前需要绑定到容器的对象的实例化过程(函数)    
    public function bind($abstract, $concrete=null)
    {
        return $this->instances[$abstract] = $concrete;
    }
    // 3. 从对象容器中取出对象, 调用它
    public function make($abstract, $params=[] ) {
        return call_user_func_array($this->instances[$abstract], []);
    }
}
// 1、将外部对象: Model, View的实例绑定到服务容器中
$container = new UsersContainer;
// 绑定模型类实例绑定到服务容器中
$container->bind('model', function(){
    return new Model();
});
// 绑定视图类实例绑定到服务容器中
$container->bind('view', function(){
    return new View();
});

Model.php |模型(Model)

namespace mvc_demo;
use PDO;
// 模型类: 数据库操作
class Model
{
    protected $db;
    // 获取数据
    public function getData()
    {
        $this->db = new PDO('mysql:host=localhost;dbname=php_pro', 'root', 'root');
        return  $this->db->query('select * from users limit 10')->fetchAll(PDO::FETCH_ASSOC);
    }
}

View.php | 视图(View)

namespace mvc_demo;
// 视图: 数据展示
class View
{
    // 数据展示
    public function fetch($data)
    {
        // 表格方式展示,使用字符串拼接实现table的html代码
        $table = '<table>';
        $table .= '<caption>用户信息表</caption>';
        $table .= '<tr><th>ID</th><th>用户名</th><th>邮箱</th></tr>';
        // 遍历用户表
        foreach ($data as $user){
            $table .= '<tr>';
            $table .= '<td>'.$user['id'].'</td>';
            $table .= '<td>'.$user['name'].'</td>';
            $table .= '<td>'.$user['email'].'</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:yellow;}
td,th {border: 1px solid; padding:5px}
</style>';

Controller.php | 控制器(Controller)

namespace mvc_demo;
//加载容器
require 'Container.php';
require 'Model.php';
require 'View.php';
class UsersController
{    
    // 获取数据,并展示出来
    public function index(UsersContainer $container)
    {
        // 1. 获取数据
        $data = $container->make('model')->getData();
        // 2. 渲染模板
        return $container->make('view')->fetch($data);
    }
}
// 客户端调用(测试)
$controller = new UsersController();
echo $controller->index($container);

这里可以模仿laravel 或thinkphp 的容器思想来解决

例如在控制器中,更加灵活实例化 $container->make('view',function(){...})->fetch($data);

MVC+依赖注入+服务容器+Facade门面技术示例

Facade门面技术: 就是将服务容器中的对象的访问进行静态接管
只需要在上面的例子中增加一个门面 facede.php及对控制器进行静态接管修改。

使用4个文件分开进行示例:
| No |文件名称 |说明
|1|Container.php|服务容器(Container)
|2| Model.php |模型(Model)
|3|View.php|视图(View)
|4|Controller.php|控制器(Controller)
|5|Facede.php|门面(Controller)

// Facade门面技术, 静态接管服务容器中的成员的访问
namespace mvc_demo;
// 在服务容器与工作的控制器之间再添加一个中间层: Facade
class Facade
{
    // 服务容器
    protected static $container = null;
    // 初始化方法: 就是给当前的Facade类扣$container属性赋值
    // 理解为Facade的构造方法(但不是)
    // 将外部的服务容器注入到当前的facade中
    public static function initialize(UsersContainer $container) 
    {
        static::$container = $container;
    }
}
// 模型类成员访问静态化(给成员套一个静态访问的马甲)
class UserModel extends Facade
{
    public static function getData()
    {
        return static::$container->make('model')->getData();
    }
}
// 视图类成员访问静态化(给成员套一个静态访问的马甲)
class UserView extends Facade
{
    public static function fetch($data)
    {
        return static::$container->make('view')->fetch($data);
    }
}

contorller.php

namespace mvc_demo;
//加载容器
require 'Container.php';
require 'Model.php';
require 'View.php';
require 'Facede.php';
class UsersController
{
    // 构造方法,初始化facade
    public function __construct(UsersContainer $container)
    {
        Facade::initialize($container);
    }
    // 用Facade方式类成员
    public function index()
    {
        // 1. 获取数据
        $data = UserModel::getData();
        // 2. 渲染模板
        return UserView::fetch($data);
    }
}
// 客户端调用(测试)
$controller = new UsersController($container);
echo $controller->index();

总结

  1. MVC : 就是用控制器(Controller)获取模型(Model)中数据并交给视图(View)去显示;
  2. 依赖注入:就是为了解耦,降低程序的复杂度,便于开发和维护,依赖注入就是用来处理类与类之间的依赖关系,使用变量方式,以依赖注入方式解决代码的耦合度过高问题;
  3. 服务容器:将依赖的外部对象,放到一个”服务容器”中进行统一管理;
  4. Facade门面技术: 就是将服务容器中的对象的访问进行静态接管。
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 11:07:03  更:2021-07-23 11:07:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 2:57:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码