一、类中静态成员
1. 声明静态成员
<?php
// 定义命名空间
namespace _1204;
// 为全局空间中的PDO类导入空间别名
use PDO;
// 1. 创建类
class Db1
{
// 2. 添加类成员
// 添加静态属性
protected static $pdo;
protected static $dsn = 'mysql:host=localhost;dbname=test';
protected static $username = 'root';
protected static $password = 'root';
// 添加静态方法
public static function connect()
{
// 在类中访问当前类的静态成员用 self::
self::$pdo = new PDO(self::$dsn, self::$username, self::$password);
}
// 测试方法
public static function select()
{
// 数据库连接
self::connect();
// 将查询结果以关联数组形式返回
return self::$pdo->query('SELECT * FROM `computer`', PDO::FETCH_ASSOC);
}
}
// 3. 访问类成员
// 在类的外部,访问类中的静态成员,直接用类名进行访问
$result = Db1::select();
foreach ($result as $row) {
echo '<pre>' . print_r($row, true) . '</pre>';
}
?>
2. 后期静态绑定
<?php
// 定义命名空间
namespace _1204;
// 后期静态绑定使用场景:静态继承的上下文环境中
// 后期静态绑定就是在类成员被调用的时候再动态的绑定,也叫:延迟绑定
use PDO;
// 1. 创建类
class Db2
{
// 2. 添加类成员
// 静态属性
protected static $pdo;
protected static $dsn = 'mysql:host=localhost;dbname=test';
protected static $username = 'root';
protected static $password = 'root';
// 静态方法
public static function connect()
{
// 后期静态绑定就是将需要绑定的静态成员的访问由 self:: ,改为 static::
static::$pdo = new PDO(static::$dsn, static::$username, static::$password);
}
public static function select()
{
// 数据库连接
static::connect();
// 将查询结果以关联数组形式返回
return self::$pdo->query('SELECT * FROM `computer`', PDO::FETCH_ASSOC);
}
}
class Sub extends Db2
{
protected static $username = 'root';
protected static $password = 'root';
// 重写父类中的connect()方法
public static function connect()
{
self::$pdo = new PDO(self::$dsn, self::$username, self::$password);
}
}
// 3. 访问类成员
// 在类的外部,访问类中的静态成员, 直接用类名
// 由于在父类中的select()方法中调用connect()方法时使用了后期静态绑定,
//又由于子类对connect()方法进行了重写,所以这时,用的就是子类中的 connect() 方法
$result = Sub::select();
foreach ($result as $row) {
echo '<pre>' . print_r($row, true) . '</pre>';
}
?>
二、MVC
1. 模型类 Model.php
<?php
namespace mvc;
// 模型类:用于数据表的操作
class Model
{
public function getData()
{
// 用二维数组来模拟从表中获取到的商品数据
return [
[
'id' => 1,
'name' => '苹果电脑',
'model' => 'MacBook Pro',
'price' => 25800
],
[
'id' => 2,
'name' => '华为手机',
'model' => 'P30 Pro',
'price' => 4988
],
[
'id' => 3,
'name' => '小爱同学',
'model' => 'AI音箱',
'price' => 299
]
];
}
}
2. 视图类 View.php
<?php
namespace mvc;
// 视图类:渲染数据
class View
{
public function fetch($data)
{
$table = '<table>';
$table .= '<caption>商品信息表</caption>';
$table .= '<tr><th>ID</th><th>品名</th><th>型号</th><th>价格</th></tr>';
foreach ($data as $product) {
$table .= '<tr>';
$table .= '<td>' . $product['id'] . '</td>';
$table .= '<td>' . $product['name'] . '</td>';
$table .= '<td>' . $product['model'] . '</td>';
$table .= '<td>' . $product['price'] . '</td>';
$table .= '</tr>';
}
$table .= '</table>';
return $table;
}
}
echo '<style>
table {border-collapse: collapse; border: 1px solid; width: 500px;height: 150px}
caption {font-size: 1.2rem; margin-bottom: 10px;}
tr:first-of-type { background-color:lightblue;}
td,th {border: 1px solid}
td:first-of-type {text-align: center}
</style>';
3. MVC简单实现
<?php
namespace mvc;
// 1. 加载模型
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制器
// 控制器:将商品信息表展示出来
class Controller1
{
public function index()
{
// 3.1 获取数据
$model = new Model();
$data = $model->getData();
// 3.2 渲染模板
$view = new View();
return $view->fetch($data);
}
}
// 4. 通过客户端来访问类成员
$controller = new Controller1();
echo $controller->index();
?>
4. 通过依赖注入,降低耦合度
a. 将注入点改到控制器的普通方法中
<?php
// 依赖注入
// 将类中对其它类的实例化,分离出来, 降低耦合度
//例如:下面将模型/视图类的实例化分离出来
namespace mvc;
// 1. 加载模型
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制器
class Controller2
{
public function index(Model $model, View $view)
{
// 获取数据
$data = $model->getData();
// 渲染模板
return $view->fetch($data);
}
}
// 4.客户端访问类成员
// 将模型与视图的实例化从控制器分离出来,放到客户端
$model = new Model();
$view = new View();
// 将模型对象与视图对象,以参数的形式再次注入到控制器的方法中
$controller = new Controller2();
echo $controller->index($model, $view);
b. 将注入点改到控制器的构造方法中
<?php
// 依赖注入:将注入点改到控制器的构造方法中
namespace mvc;
// 1. 加载模型
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制器
class Controller3
{
protected $model;
protected $view;
// 将注入点改到构造方法中,实现了模型与视图对象的共享
public function __construct(Model $model, View $view)
{
$this->model = $model;
$this->view = $view;
}
public function index()
{
// 获取数据
$data = $this->model->getData();
// 渲染模板
return $this->view->fetch($data);
}
}
// 4. 客户端访问类成员
// 将模型与视图的实例化从控制器分离出来,放到客户端
$model = new Model();
$view = new View();
// 将模型对象和视图对象,以参数的形式注入到控制器的构造方法
$controller = new Controller3($model,$view);
echo $controller->index();
?>
5. 添加服务容器层
<?php
namespace mvc;
// 1. 加载模型
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 添加服务容器层
class Container
{
// 容器属性,就是一个数组,保存着创建对象的方法
protected $instance = [];
// 1. 放进去:将类的实例化过程绑定到容器中
// 就是将类实例化的方法存入到容器属性$instance数组中
// $alias: 类实例的别名,Closure 闭包类
public function bind($alias, \Closure $process)
{
// 将类实例化的方法绑定/存储到服务容器中
$this->instance[$alias] = $process;
}
// 2. 取出来:执行容器中的实例化方法
public function make($alias, $params = [])
{
// 调用回调函数,本实例即返回实例化方法的结果
return call_user_func_array($this->instance[$alias], []);
}
}
// 实例化容器
$container = new Container();
// 将模型对象和视图对象绑定到容器中
$container->bind('model', function () {
return new Model();
});
$container->bind('view', function () {
return new View();
});
// 3. 创建控制器
class Controller4
{
public function index(Container $container)
{
// 获取数据
$data = $container->make('model')->getData();
// 渲染模板
return $container->make('view')->fetch($data);
}
}
// 4. 客户端调用
$controller = new Controller4();
echo $controller->index($container);
?>
6. Facade门面
<?php
namespace mvc;
// 1. 加载模型
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 添加服务容器层
class Container1
{
// 容器属性,就是一个数组,保存着创建对象的方法
protected $instance = [];
// 1. 放进去:将类的实例化过程绑定到容器中
// 就是将类实例化的方法存入到容器属性$instance数组中
// $alias: 类实例的别名,Closure 闭包类
public function bind($alias, \Closure $process)
{
// 将类实例化的方法绑定/存储到服务容器中
$this->instance[$alias] = $process;
}
// 2. 取出来:执行容器中的实例化方法
public function make($alias, $params = [])
{
// 调用回调函数,本实例即返回实例化方法的结果
return call_user_func_array($this->instance[$alias], []);
}
}
// 实例化容器
$container = new Container1();
// 将模型对象和视图对象绑定到容器中
$container->bind('model', function () {
return new Model();
});
$container->bind('view', function () {
return new View();
});
// 添加Facade门面类
class Facade
{
protected static $container = null;
protected static $data = [];
// 用服务容器将静态属性初始化
public static function initialize(Container1 $container)
{
static::$container = $container;
}
// 用静态代理方式将模型类中的getData()静态化
public static function getData()
{
static::$data = static::$container->make('model')->getData();
}
// 用静态代理方式将视图类中的fetch()静态化
public static function fetch()
{
return static::$container->make('view')->fetch(static::$data);
}
}
// 声明一个学生类继承门面类
class Student extends Facade
{
}
// 3. 创建控制器
class Controller5
{
// 使用构造方法,自动调用Facade里面的初始化方法
public function __construct(Container1 $container)
{
Student::initialize($container);
}
public function index()
{
// 获取数据
Student::getData();
// 渲染模板
return Student::fetch();
}
}
// 4. 客户端调用
$controller = new Controller5($container);
echo $controller->index();
?>
三、总结
后期静态绑定是在类成员被调用的时候动态的绑定。
MVC就是控制器接受请求后,调用模型中的数据,通过视图将页面渲染出来。
通过依赖注入可以降低耦合度。
服务容器就是将类的实例化给包装到一个类中,即通过调用类中的方法,将类的实例化方法存进来,再取出去调用。
Facade门面就是通过静态代理方式将要实例化的类中的方法静态化,大大降低了耦合度。