博客列表 >028-12月04日-PHP第18节-静态类、MVC框架、依赖注入等

028-12月04日-PHP第18节-静态类、MVC框架、依赖注入等

冇忉丼
冇忉丼原创
2019年12月09日 00:03:47625浏览

1. 将课堂源代码, 全部写一遍, 在编辑器中写就可, 必须全部运行正确, 并加上自己理解的注释,不用手写

1.静态类

所谓静态,指以static关键字修饰的,包括类,方法。
静态类访问方法:

1、静态方法不需要实例化对象,可以通过类名直接调用,操作符为双冒号::

2、外部访问公共属性或方法(与普通类一样):

  1. $car->speed;$car->speedUp();

3、内部访问公共属性和方法(与普通类一样):

  1. $this->speed;$this->speedUp();

4、外部访问静态属性或方法:

  1. Car::getName();Car::$price;

5、内部访问静态属性:(可用延迟调用—static代替self)

  1. self::$price;

6、继承类时,子类内部调用父类静态属性:

  1. parent::$price;
  2. class Controller_article extends Controller_basepage {
  3. function __construct() {
  4. parent::__construct();
  5. }
  6. }

静态类的需求:

  1. 静态的变量或者是函数是保存的静态内存中的,只有到程序结束时才会被释放,那他是什么时候赋值的呢:是在编译的时候,动态类是在程序运行的时候动态分配的。如果类中调用一次,静态类在编译的时候需要多做工作,动态类在执行的时候需要多做工作,然而php是动态语言,每一次这两步都不掉,所以对于只运行一次的类,无所谓谁快谁慢。
  2. 但是如果一个类在程序当中要**多次调用**就不一样了,静态类是编译的时候就赋值了,程序之后的运行都可以直接调用过来,而不用动态的分配内存了,就节约了时间,这就是为什么静态类比动态类快的原因(前提是调用多次)。
  1. <?php
  2. //demo1
  3. namespace _1204;
  4. use PDO; //静态类,全局
  5. class Db1{
  6. protected static $pdo;//static使方法属性等不用实例化就可用类调用,既然如此,一般声明为
  7. //protected
  8. protected static $dsn = 'mysql:host=localhost;dbname=anguoguo';
  9. protected static $username = 'root';
  10. protected static $password = 'root';
  11. //静态方法
  12. public static function connect(){
  13. //类中访问当前类的静态成员:self::
  14. self::$pdo = new PDO(self::$dsn,self::$username,self::$password);
  15. }
  16. //测试方法
  17. public static function select(){
  18. self::connect();
  19. return self::$pdo->query('select * from `users`',PDO::FETCH_ASSOC);
  20. }
  21. }
  22. $result = Db1::select();
  23. foreach($result as $r){
  24. echo '<pre>' . print_r($r,true) . '</pre>';
  25. }
  1. <?php
  2. //demo2延迟调用
  3. namespace _1204;
  4. use PDO;
  5. class Db2{
  6. protected static $pdo;
  7. protected static $dsn = 'mysql:host=localhost;dbname=anguoguo';
  8. protected static $username = 'root';
  9. protected static $password = 'root';
  10. public static function connect(){
  11. static ::$pdo = new PDO(static::$dsn,static::$username,static::$password);
  12. //延迟绑定,动态绑定
  13. }
  14. public static function select(){
  15. static ::connect();
  16. return self::$pdo->query('select * from `users`',PDO::FETCH_ASSOC);
  17. }
  18. }
  19. class Sub extends Db2{
  20. protected static $username = 'root';
  21. protected static $password = '123';
  22. public static function connect(){
  23. self ::$pdo = new PDO(self::$dsn,self::$username,self::$password);
  24. //alt+j选择所有后面相同的单词
  25. }
  26. }
  27. $result = Db1::select();
  28. foreach($result as $r){
  29. echo '<pre>' . print_r($r,true) . '</pre>';
  30. }

mvc框架

mvc是一种常见设计模式,包括:model(模型),view(视图),controller(控制器)
Model:数据表(此处直接用数组来模拟)

  1. <?php
  2. namespace mvc;
  3. // 模型类:用于数据表的操作
  4. class Model
  5. {
  6. public function getData()
  7. {
  8. // 用二维数组模拟数据表中信息
  9. return [
  10. ['id'=>1, 'name'=>'苹果电脑', 'model'=>'MacBook Pro', 'price'=>25800],
  11. ['id'=>2, 'name'=>'华为手机','model'=>'P30 Pro','price'=>4988],
  12. ['id'=>3, 'name'=>'小爱同学','model'=>'AI音箱','price'=>299],
  13. ];
  14. }
  15. }

View: 渲染数据,向用户显示模型的数据。视图知道如何访问模型的数据,但它不知道这些数据意味着什么,也不知道用户可以做什么来操作它。

  1. <?php
  2. namespace mvc;
  3. // 视图类:渲染数据
  4. class View
  5. {
  6. public function fetch($data)
  7. {
  8. //渲染为表格
  9. $table = '<table>';
  10. $table .= '<caption>商品信息表</caption>';
  11. $table .= '<tr><th>ID</th><th>品名</th><th>型号</th><th>价格</th></tr>';
  12. foreach ($data as $product) {
  13. $table .= '<tr>';
  14. $table .= '<td>' . $product['id'] . '</td>';
  15. $table .= '<td>' . $product['name'] . '</td>';
  16. $table .= '<td>' . $product['model'] . '</td>';
  17. $table .= '<td>' . $product['price'] . '</td>';
  18. $table .= '</tr>';
  19. }
  20. $table .= '</table>';
  21. return $table;
  22. }
  23. }
  24. echo '<style>
  25. table {border-collapse: collapse; border: 1px solid; width: 500px;height: 150px}
  26. caption {font-size: 1.2rem; margin-bottom: 10px;}
  27. tr:first-of-type { background-color:lightblue;}
  28. td,th {border: 1px solid}
  29. td:first-of-type {text-align: center}
  30. </style>';

Controller:存在于视图和模型之间。它侦听视图(或其他外部源)触发的事件,并对这些事件执行适当的响应,并调用模型上的方法。由于视图和模型是通过通知机制连接的,因此此操作的结果将自动反映在视图中。
demo1:

  1. <?php
  2. // 控制器: 将商品信息表展示出来
  3. namespace mvc;
  4. // 1. 加载模型
  5. require 'Model.php';
  6. // 2. 加载视图
  7. require 'View.php';
  8. // 3. 创建控制器
  9. class Controller1
  10. {
  11. public function index()
  12. {
  13. // 3.1 获取数据
  14. $model = new Model();
  15. $data = $model->getData();
  16. // 3.2 渲染模板
  17. $view = new View();
  18. return $view->fetch($data);
  19. }
  20. }
  21. // 4. 客户端调用/访问类成员
  22. $controller = new Controller1();
  23. echo $controller->index();

demo1类中实例化外部类,耦合度太高
所以以下demo2将模型与视图的实例化代码从控制器分离出来, 放到了客户端,使用依赖注入,外部实例化调用的类的实例,内部方法传入调用的实例为参数

  1. <?php
  2. // 控制器: 将商品信息表展示出来
  3. // 将类中对其它类的实例化, 模型/视图分离出来, 降低耦合度
  4. // 依赖注入
  5. namespace mvc;
  6. // 1. 加载模型
  7. use BaconQrCode\Common\Mode;
  8. require 'Model.php';
  9. // 2. 加载视图
  10. require 'View.php';
  11. // 3. 创建控制器
  12. class Controller2
  13. {
  14. public function index(Model $model, View $view)
  15. {
  16. // 3.1 获取数据
  17. $data = $model->getData();
  18. // 3.2 渲染模板
  19. return $view->fetch($data);
  20. }
  21. }
  22. // 4. 客户端调用/访问类成员
  23. // 将模型与视图的实例化代码从控制器分离出来, 放到了客户端
  24. $model = new Model();
  25. $view = new View();
  26. // 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
  27. $controller = new Controller2();
  28. echo $controller->index($model, $view);

demo3:将依赖注入点改在控制器的构造方法中,这样多个方法调用两个实例时就很方便了

  1. <?php
  2. // 控制器: 将商品信息表展示出来
  3. // 依赖注入: 将注入点改到了控制器的构造方法中
  4. namespace mvc;
  5. // 1. 加载模型
  6. use BaconQrCode\Common\Mode;
  7. require 'Model.php';
  8. // 2. 加载视图
  9. require 'View.php';
  10. // 3. 创建控制器
  11. class Controller3
  12. {
  13. protected $model;
  14. protected $view;
  15. // 构造方法, 注入点改到了构造方法中, 实现了模型与视图对象的共享
  16. public function __construct(Model $model, View $view)
  17. {
  18. $this->model = $model;
  19. $this->view = $view;
  20. }
  21. public function index()
  22. {
  23. // 3.1 获取数据
  24. $data = $this->model->getData();
  25. // 3.2 渲染模板
  26. return $this->view->fetch($data);
  27. }
  28. }
  29. // 4. 客户端调用/访问类成员
  30. // 将模型与视图的实例化代码从控制器分离出来, 放到了客户端
  31. $model = new Model();
  32. $view = new View();
  33. // 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
  34. $controller = new Controller3($model, $view);
  35. echo $controller->index();

demo4:创建一个容器类,分两步—1.将多个类实例绑定别名,多个类方法绑定到闭包,自然这些参数就需要放到数组里;2.取出来: 执行容器中的实例方法(使用了回调函数)

  1. <?php
  2. // 控制器: 将商品信息表展示出来
  3. // 依赖注入: 将注入点改到了控制器的构造方法中
  4. namespace mvc;
  5. // 1. 加载模型
  6. use BaconQrCode\Common\Mode;
  7. require 'Model.php';
  8. // 2. 加载视图
  9. require 'View.php';
  10. /**************************************************/
  11. //添加服务容器层
  12. class Container
  13. {
  14. // 容器属性, 就是一个数组,里面全是创建对象的方法
  15. protected $instance = [];
  16. // 1. 放进去: 将类的实例化过程绑定到容器中
  17. // $alias: 类实例的别名,
  18. public function bind($alias, \Closure $process)
  19. {
  20. // 将类实例化的方法绑定/ 存储到服务容器中
  21. $this->instance[$alias] = $process;
  22. }
  23. // 2. 取出来: 执行容器中的实例方法
  24. public function make($alias, $params=[])
  25. {
  26. return call_user_func_array($this->instance[$alias], []);
  27. }
  28. }
  29. // 实例化容器
  30. $container = new Container();
  31. // 用到模型对象, 视图对象,将它们绑定到容器中
  32. $container->bind('model', function () {return new Model();});
  33. $container->bind('view', function () {return new View();});
  34. /**************************************************/
  35. // 3. 创建控制器
  36. class Controller4
  37. {
  38. public function index(Container $container)
  39. {
  40. // 3.1 获取数据
  41. $data = $container->make('model')->getData();
  42. // 3.2 渲染模板
  43. return $container->make('view')->fetch($data);
  44. }
  45. }
  46. // 4. 客户端调用/访问类成员
  47. // 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
  48. $controller = new Controller4();
  49. echo $controller->index($container);

demo5: 此例使用了Facade技术,其规范/统一了对外部对象的调用方式, 全部改为了静态调用, 不管之前的方法是什么类型

  1. <?php
  2. // 控制器: 将商品信息表展示出来
  3. // Facade技术: 规范/统一了对外部对象的调用方式, 全部改为了静态调用, 不管之前的方法是什么类型
  4. namespace mvc;
  5. // 1. 加载模型
  6. use BaconQrCode\Common\Mode;
  7. require 'Model.php';
  8. // 2. 加载视图
  9. require 'View.php';
  10. /**************************************************/
  11. //添加服务容器层
  12. class Container1
  13. {
  14. // 容器属性, 就是一个数组,里面全是创建对象的方法
  15. protected $instance = [];
  16. // 1. 放进去: 将类的实例化过程绑定到容器中
  17. // $alias: 类实例的别名,
  18. public function bind($alias, \Closure $process)
  19. {
  20. // 将类实例化的方法绑定/ 存储到服务容器中
  21. $this->instance[$alias] = $process;
  22. }
  23. // 2. 取出来: 执行容器中的实例方法
  24. public function make($alias, $params=[])
  25. {
  26. return call_user_func_array($this->instance[$alias], []);
  27. }
  28. }
  29. // 实例化容器
  30. $container = new Container1();
  31. // 用到模型对象, 视图对象,将它们绑定到容器中
  32. $container->bind('model', function () {return new Model();});
  33. $container->bind('view', function () {return new View();});
  34. /**************************************************/
  35. // 添加Facade门面类
  36. class Facade
  37. {
  38. protected static $container = null;
  39. protected static $data = [];
  40. // 用服务容器给它初始化
  41. public static function initialize(Container1 $container)
  42. {
  43. static::$container = $container;
  44. }
  45. // 用静态代理方式将模型中的getData()静态化
  46. public static function getData()
  47. {
  48. static::$data = static::$container->make('model')->getData();
  49. }
  50. // 用静态代理方式将视图中的fetch()静态化
  51. public static function fetch()
  52. {
  53. return static::$container->make('view')->fetch(static::$data);
  54. }
  55. }
  56. // 声明一学生类
  57. class Son extends Facade
  58. {
  59. //
  60. }
  61. /**************************************************/
  62. // 3. 创建控制器
  63. class Controller5
  64. {
  65. public function __construct(Container1 $container)
  66. {
  67. // 调用Faceda里面的初始化方法
  68. Son::initialize($container);
  69. }
  70. public function index()
  71. {
  72. // 3.1 获取数据
  73. Son::getData();
  74. // 3.2 渲染模板
  75. return Son::fetch();
  76. }
  77. }
  78. // 4. 客户端调用/访问类成员
  79. // 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
  80. $controller = new Controller5($container);
  81. echo $controller->index();

2. 将最后一个demo5.php中的代码, 手写提交


声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议