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门面技术: 就是将服务容器中的对象的访问进行静态接管。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值