Middleware.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: Slince <taosikai@yeah.net>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. use InvalidArgumentException;
  13. use LogicException;
  14. use think\exception\HttpResponseException;
  15. class Middleware
  16. {
  17. protected $queue = [];
  18. protected $app;
  19. protected $config = [
  20. 'default_namespace' => 'app\\http\\middleware\\',
  21. ];
  22. public function __construct(App $app, array $config = [])
  23. {
  24. $this->app = $app;
  25. $this->config = array_merge($this->config, $config);
  26. }
  27. public static function __make(App $app, Config $config)
  28. {
  29. return new static($app, $config->pull('middleware'));
  30. }
  31. public function setConfig(array $config)
  32. {
  33. $this->config = array_merge($this->config, $config);
  34. }
  35. /**
  36. * 导入中间件
  37. * @access public
  38. * @param array $middlewares
  39. * @param string $type 中间件类型
  40. */
  41. public function import(array $middlewares = [], $type = 'route')
  42. {
  43. foreach ($middlewares as $middleware) {
  44. $this->add($middleware, $type);
  45. }
  46. }
  47. /**
  48. * 注册中间件
  49. * @access public
  50. * @param mixed $middleware
  51. * @param string $type 中间件类型
  52. */
  53. public function add($middleware, $type = 'route')
  54. {
  55. if (is_null($middleware)) {
  56. return;
  57. }
  58. $middleware = $this->buildMiddleware($middleware, $type);
  59. if ($middleware) {
  60. $this->queue[$type][] = $middleware;
  61. }
  62. }
  63. /**
  64. * 注册控制器中间件
  65. * @access public
  66. * @param mixed $middleware
  67. */
  68. public function controller($middleware)
  69. {
  70. return $this->add($middleware, 'controller');
  71. }
  72. /**
  73. * 移除中间件
  74. * @access public
  75. * @param mixed $middleware
  76. * @param string $type 中间件类型
  77. */
  78. public function unshift($middleware, $type = 'route')
  79. {
  80. if (is_null($middleware)) {
  81. return;
  82. }
  83. $middleware = $this->buildMiddleware($middleware, $type);
  84. if ($middleware) {
  85. array_unshift($this->queue[$type], $middleware);
  86. }
  87. }
  88. /**
  89. * 获取注册的中间件
  90. * @access public
  91. * @param string $type 中间件类型
  92. */
  93. public function all($type = 'route')
  94. {
  95. return $this->queue[$type] ?: [];
  96. }
  97. /**
  98. * 清除中间件
  99. * @access public
  100. */
  101. public function clear()
  102. {
  103. $this->queue = [];
  104. }
  105. /**
  106. * 中间件调度
  107. * @access public
  108. * @param Request $request
  109. * @param string $type 中间件类型
  110. */
  111. public function dispatch(Request $request, $type = 'route')
  112. {
  113. return call_user_func($this->resolve($type), $request);
  114. }
  115. /**
  116. * 解析中间件
  117. * @access protected
  118. * @param mixed $middleware
  119. * @param string $type 中间件类型
  120. */
  121. protected function buildMiddleware($middleware, $type = 'route')
  122. {
  123. if (is_array($middleware)) {
  124. list($middleware, $param) = $middleware;
  125. }
  126. if ($middleware instanceof \Closure) {
  127. return [$middleware, isset($param) ? $param : null];
  128. }
  129. if (!is_string($middleware)) {
  130. throw new InvalidArgumentException('The middleware is invalid');
  131. }
  132. if (false === strpos($middleware, '\\')) {
  133. if (isset($this->config[$middleware])) {
  134. $middleware = $this->config[$middleware];
  135. } else {
  136. $middleware = $this->config['default_namespace'] . $middleware;
  137. }
  138. }
  139. if (is_array($middleware)) {
  140. return $this->import($middleware, $type);
  141. }
  142. if (strpos($middleware, ':')) {
  143. list($middleware, $param) = explode(':', $middleware, 2);
  144. }
  145. return [[$this->app->make($middleware), 'handle'], isset($param) ? $param : null];
  146. }
  147. protected function resolve($type = 'route')
  148. {
  149. return function (Request $request) use ($type) {
  150. $middleware = array_shift($this->queue[$type]);
  151. if (null === $middleware) {
  152. throw new InvalidArgumentException('The queue was exhausted, with no response returned');
  153. }
  154. list($call, $param) = $middleware;
  155. try {
  156. $response = call_user_func_array($call, [$request, $this->resolve($type), $param]);
  157. } catch (HttpResponseException $exception) {
  158. $response = $exception->getResponse();
  159. }
  160. if (!$response instanceof Response) {
  161. throw new LogicException('The middleware must return Response instance');
  162. }
  163. return $response;
  164. };
  165. }
  166. public function __debugInfo()
  167. {
  168. $data = get_object_vars($this);
  169. unset($data['app']);
  170. return $data;
  171. }
  172. }