PluginRoute.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. namespace laytp\library;
  3. use think\exception\HttpException;
  4. use think\facade\Config;
  5. use think\facade\Middleware;
  6. use think\facade\Request;
  7. use think\Response;
  8. use think\Route;
  9. class PluginRoute extends Route
  10. {
  11. protected $middleware;
  12. protected $actionName;
  13. /**
  14. * 插件路由
  15. * 路由访问规则,http(s)://yourDomain/plugin/[插件名称]/[插件controller目录下的类名,多级目录以.号分割]/[方法名]/[参数列表]
  16. * @param null $plugin
  17. * @return mixed
  18. */
  19. public function execute($plugin = null)
  20. {
  21. $this->middleware = Middleware::instance();
  22. $this->request = Request::instance();
  23. $url = $this->request->url();
  24. $urlArr = array_filter(explode('/', $url));
  25. // print_r($urlArr);
  26. if(SYS_TYPE == 'W7'){
  27. $controller = isset($urlArr[7]) ? $urlArr[7] : 'Index';
  28. }else{
  29. $controller = isset($urlArr[3]) ? $urlArr[3] : 'Index';
  30. }
  31. $plugin = $plugin ? trim(strtolower($plugin)) : $plugin;
  32. if (!defined('LT_PLUGIN')) {
  33. define('LT_PLUGIN', $plugin);
  34. }
  35. $controller = $controller ? str_replace('.', '\\', trim($controller)) : 'Index';
  36. $classAndAction = $this->getPluginClassAndAction($plugin, $controller);
  37. $this->request->setController($controller)->setAction($classAndAction['action']);
  38. $common_func_file = app()->getRootPath() . DS . 'plugin' . DS . $plugin . DS . 'common.php';
  39. if (file_exists($common_func_file)) {
  40. include_once app()->getRootPath() . DS . 'plugin' . DS . $plugin . DS . 'common.php';
  41. }
  42. $class = $classAndAction['class'];
  43. $action = $classAndAction['action'];
  44. $instance = app()->make($class, [], true);
  45. $this->actionName = $action;
  46. try {
  47. $this->registerControllerMiddleware($instance);
  48. } catch (\ReflectionException $e) {
  49. throw new HttpException(500, $e->getMessage());
  50. }
  51. return $this->middleware->pipeline('controller')
  52. ->send($this->request)
  53. ->then(function () use ($instance) {
  54. // 获取当前操作名
  55. $suffix = Config::get('route.action_suffix');
  56. $action = $this->actionName . $suffix;
  57. if (is_callable([$instance, $action])) {
  58. $vars = $this->request->param();
  59. try {
  60. $reflect = new \ReflectionMethod($instance, $action);
  61. // 严格获取当前操作方法名
  62. $actionName = $reflect->getName();
  63. if ($suffix) {
  64. $actionName = substr($actionName, 0, -strlen($suffix));
  65. }
  66. $this->request->setAction($actionName);
  67. } catch (\Exception $e) {
  68. $reflect = new \ReflectionMethod($instance, '__call');
  69. $vars = [$action, $vars];
  70. $this->request->setAction($action);
  71. }
  72. } else {
  73. // 操作不存在
  74. throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
  75. }
  76. $data = $this->app->invokeReflectMethod($instance, $reflect, $vars);
  77. return $this->autoResponse($data);
  78. });
  79. }
  80. /**
  81. * 得到插件完整类名
  82. * @param $plugin
  83. * @param $controller
  84. * @return array
  85. */
  86. public function getPluginClassAndAction($plugin, $controller)
  87. {
  88. $request = Request::instance();
  89. $url = $request->url();
  90. $urlArr = array_filter(explode('/', $url));
  91. $controllerArr = explode("\\", $controller);
  92. $controllerArr[count($controllerArr) - 1] = ucfirst($controllerArr[count($controllerArr) - 1]);
  93. $controller = implode("\\", $controllerArr);
  94. $class = 'plugin\\' . $plugin . '\\controller\\' . $controller;
  95. // print_r($class);
  96. if (!class_exists($class)) {
  97. throw new HttpException(404, $class . '类不存在');
  98. }
  99. $class = 'plugin\\' . $plugin . '\\controller\\' . $controller;
  100. if(SYS_TYPE == 'W7'){
  101. if (isset($urlArr[8])) {
  102. $action_param = explode('?', $urlArr[8]);
  103. $action = $action_param[0];
  104. } else {
  105. $action = 'index';
  106. }
  107. }else{
  108. if (isset($urlArr[4])) {
  109. $action_param = explode('?', $urlArr[4]);
  110. $action = $action_param[0];
  111. } else {
  112. $action = 'index';
  113. }
  114. }
  115. $action = $action ? str_replace('.' . Config::get("route.url_html_suffix"), '', trim($action)) : 'index';
  116. if (!method_exists($class, $action)) {
  117. throw new HttpException(404, $class . '->' . $action . '()' . '方法不存在');
  118. }
  119. return ['class' => $class, 'action' => $action];
  120. }
  121. /**
  122. * 使用反射机制注册控制器中间件
  123. * @param $controller
  124. * @throws \ReflectionException
  125. */
  126. protected function registerControllerMiddleware($controller): void
  127. {
  128. $class = new \ReflectionClass($controller);
  129. if ($class->hasProperty('middleware')) {
  130. $reflectionProperty = $class->getProperty('middleware');
  131. $reflectionProperty->setAccessible(true);
  132. $middlewares = $reflectionProperty->getValue($controller);
  133. foreach ($middlewares as $key => $val) {
  134. if (!is_int($key)) {
  135. if (isset($val['only']) && !in_array($this->request->action(true), array_map(function ($item) {
  136. return strtolower($item);
  137. }, is_string($val['only']) ? explode(",", $val['only']) : $val['only']))) {
  138. continue;
  139. } elseif (isset($val['except']) && in_array($this->request->action(true), array_map(function ($item) {
  140. return strtolower($item);
  141. }, is_string($val['except']) ? explode(',', $val['except']) : $val['except']))) {
  142. continue;
  143. } else {
  144. $val = $key;
  145. }
  146. }
  147. if (is_string($val) && strpos($val, ':')) {
  148. $val = explode(':', $val);
  149. if (count($val) > 1) {
  150. $val = [$val[0], array_slice($val, 1)];
  151. }
  152. }
  153. $this->middleware->controller($val);
  154. }
  155. }
  156. }
  157. protected function autoResponse($data): Response
  158. {
  159. if ($data instanceof Response) {
  160. $response = $data;
  161. } elseif (!is_null($data)) {
  162. // 默认自动识别响应输出类型
  163. $type = $this->request->isJson() ? 'json' : 'html';
  164. $response = Response::create($data, $type);
  165. } else {
  166. $data = ob_get_clean();
  167. $content = false === $data ? '' : $data;
  168. $status = '' === $content && $this->request->isJson() ? 204 : 200;
  169. $response = Response::create($content, 'html', $status);
  170. }
  171. return $response;
  172. }
  173. }