登录  /  注册
博主信息
博文 42
粉丝 5
评论 0
访问量 37486
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
mvc 服务容器,控制反转
张浩刚
原创
1503人浏览过

根目录下文件

Controller.php

  1. <?php
  2. //本页面 是服务容器的控制反转,将接口下的类,控制器的类反转到容器中控制
  3. //根目录use调用,第一个一定是 \文件夹名\..\php的文件名
  4. use \view\iVehicle;
  5. use \view\Car;
  6. use \view\Bus;
  7. require __DIR__ . '/Autoload.php';
  8. //容器类
  9. class Container
  10. {
  11. // 闭包数组
  12. private static $binds = [];
  13. // 实例数组
  14. private static $instance = [];
  15. // 将闭包或实例绑定到对应的容器中
  16. public function bind($abstract,$concrete)
  17. {
  18. // 将类实例化的闭包绑定到闭包数组中
  19. // 按照约定,闭包是用来创建对象的
  20. // 重要编码约定: 它的构造方法第一个参数必须是 "容器对象", 便于统一管理 "对象依赖关系"
  21. // 如果第二个参数是闭包类型, 说明该类实例并未创建,应该将实例化过程/闭包绑定到容器中
  22. if($concrete instanceof Closure){
  23. static::$binds[$abstract] = $concrete;
  24. }else{
  25. // 否则,表示该类已被实例化,直接将 "类实例" 绑定到实例数组中即可
  26. static::$instance[$abstract] = $concrete;
  27. }
  28. }
  29. // 从容器中取出指定实例, $parameters是实例的依赖对象(数组形式提供)
  30. public function make($abstract,$parameters = [])
  31. {
  32. // 如果容器中已有指定类实例,则直接返回
  33. if(isset(static::$instance[$abstract])){
  34. return static::$instance[$abstract];
  35. }else{
  36. // 如果没有, 则执行闭包容器中的闭包方法,完成实例化工作,并返回该实例
  37. // 因为所有依赖都使用容器统一管理,所以需要将容器对象注入到所有依赖对象的参数列表中
  38. // 默认容器必须是依赖对象参数列表中的第一个参数,使用array_unshift()就可以
  39. // 注意, $this 是第一个参数, 即当前容器对象,这里就是本服务容器Container
  40. array_unshift($parameters, $this);
  41. // 执行闭包, 如果闭包生成的对象依赖于其它对象,可通过$parameters设置
  42. return call_user_func_array(static::$binds[$abstract],$parameters);
  43. }
  44. }
  45. }
  46. //控制器
  47. class Controller
  48. {
  49. // 交通工具
  50. private static $Traffic;
  51. // 构造方法:接口 接入,第二个$traff就是接口下的对象类:Car,Bus 是数组,通过外部服务容器传参
  52. public function __construct(iVehicle $traff)
  53. {
  54. static::$Traffic = $traff;
  55. }
  56. public function travelMode()
  57. {
  58. return static::$Traffic->drive();
  59. }
  60. }
  61. //容器对象
  62. $container = new Container();
  63. //将汽车类绑定到闭包数组中
  64. //将$container做为闭包参数, 主要用来管理依赖对象的,本例中除调用类外,其它类并未使用到依赖对象
  65. $container->bind('car', function(Container $container){return new Car();});
  66. $container->bind('bus', function(Container $container){return new Bus();});
  67. // 同时将调用类:控制器类也绑定到容器中
  68. // Controller构造方法需要一个实现了iVehicle接口的对象,而该对象需要使用容器中的make()方法获取
  69. // 根据make($container, $parameters)方法签名, 该闭包签名的第一个参数是容器对象,第二个参数是依赖的对象
  70. // 注意, 为了简化, 约定将依赖对象,通过构造方式注入到当前对象中
  71. $container->bind('controller', function(Container $container, $traffi){
  72. return new Controller($container->make($traffi));
  73. });
  74. //客户端
  75. //从容器中取出已实例化的容器类对象 (此时依赖对象已经通过构造方法注入到了控制器类中了)
  76. $controller = $container->make('controller',['car']);
  77. echo $controller->travelMode();//汽车
  78. $controller = $container->make('controller',['car']);
  79. echo $controller->travelMode();//公交车
  80. //如果只想从容器中取出接口下的某一个对象类
  81. $car = $container->make('car');
  82. echo $car->drive();
  83. // 为了便于后面调用, 我们将这四个对象打包到一个数组中管理
  84. $vehicles = compact('car', 'train', 'plane', 'ship');
  85. // 如果已经获取到了依赖对象, 那么就不必使用make()来调用Travel4对象了,直接实例化它就行
  86. foreach ($vehicles as $vehicle) {
  87. $travel = new Controller($vehicle);
  88. echo $travel->travelMode(), '<br>';
  89. }
  90. // 到现在为止, 我们已经实现了依赖注入也控制反转
  91. // 基本流程是:
  92. // 1. 依赖注入: 如果一对象需要依赖另一个对象才能完成某项操作,则必须通过方法参数的形式将依赖对象注入当前到对象中
  93. // 2. 控制反转: 依赖对象的实例化与该对象自身的依赖关系处理, 由一个叫服务容器的类统一处理,实现了对象控制权的转移

Autoload.php

  1. <?php
  2. spl_autoload_register(function (string $class) {
  3. $file = str_replace('\\', '/', $class) . '.php';
  4. if (!is_file($file)) {
  5. throw new \Exception("file don't exists");
  6. }
  7. require $file;
  8. });

根 \view文件夹

iVehicle.php 接口文件

  1. <?php
  2. namespace view;
  3. interface iVehicle
  4. {
  5. public function drive();
  6. }

Car.php

  1. <?php
  2. namespace view;
  3. class Car implements iVehicle
  4. {
  5. public function drive()
  6. {
  7. return '小汽车';
  8. }
  9. }

Bus.php

  1. <?php
  2. namespace view;
  3. class Bus implements iVehicle
  4. {
  5. public function drive()
  6. {
  7. return '公交车';
  8. }
  9. }
本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学