Blogger Information
Blog 42
fans 5
comment 0
visits 38608
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
mvc 服务容器,控制反转
张浩刚
Original
1537 people have browsed it

根目录下文件

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. }
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post