middleware = Middleware::instance(); $this->request = Request::instance(); $url = $this->request->url(); $urlArr = array_filter(explode('/', $url)); $controller = isset($urlArr[3]) ? $urlArr[3] : 'Index'; $plugin = $plugin ? trim(strtolower($plugin)) : $plugin; if (!defined('LT_PLUGIN')) { define('LT_PLUGIN', $plugin); } $controller = $controller ? str_replace('.', '\\', trim($controller)) : 'Index'; $classAndAction = $this->getPluginClassAndAction($plugin, $controller); $this->request->setController($controller)->setAction($classAndAction['action']); $class = $classAndAction['class']; $action = $classAndAction['action']; $instance = app()->make($class, [], true); $this->actionName = $action; try { $this->registerControllerMiddleware($instance); } catch (\ReflectionException $e) { throw new HttpException(500, $e->getMessage()); } return $this->middleware->pipeline('controller') ->send($this->request) ->then(function () use ($instance) { // 获取当前操作名 $suffix = Config::get('route.action_suffix'); $action = $this->actionName . $suffix; if (is_callable([$instance, $action])) { $vars = $this->request->param(); try { $reflect = new \ReflectionMethod($instance, $action); // 严格获取当前操作方法名 $actionName = $reflect->getName(); if ($suffix) { $actionName = substr($actionName, 0, -strlen($suffix)); } $this->request->setAction($actionName); } catch (\Exception $e) { $reflect = new \ReflectionMethod($instance, '__call'); $vars = [$action, $vars]; $this->request->setAction($action); } } else { // 操作不存在 throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } $data = $this->app->invokeReflectMethod($instance, $reflect, $vars); return $this->autoResponse($data); }); } /** * 得到插件完整类名 * @param $plugin * @param $controller * @return array */ public function getPluginClassAndAction($plugin, $controller) { $request = Request::instance(); $url = $request->url(); $urlArr = array_filter(explode('/', $url)); $controllerArr = explode("\\", $controller); $controllerArr[count($controllerArr) - 1] = ucfirst($controllerArr[count($controllerArr) - 1]); $controller = implode("\\", $controllerArr); $class = 'plugin\\' . $plugin . '\\controller\\' . $controller; if (!class_exists($class)) { throw new HttpException(404, $class . '类不存在'); } $class = 'plugin\\' . $plugin . '\\controller\\' . $controller; if (isset($urlArr[4])) { $action_param = explode('?', $urlArr[4]); $action = $action_param[0]; } else { $action = 'index'; } $action = $action ? str_replace('.' . Config::get("route.url_html_suffix"), '', trim($action)) : 'index'; if (!method_exists($class, $action)) { throw new HttpException(404, $class . '->' . $action . '()' . '方法不存在'); } return ['class' => $class, 'action' => $action]; } /** * 使用反射机制注册控制器中间件 * @param $controller * @throws \ReflectionException */ protected function registerControllerMiddleware($controller): void { $class = new \ReflectionClass($controller); if ($class->hasProperty('middleware')) { $reflectionProperty = $class->getProperty('middleware'); $reflectionProperty->setAccessible(true); $middlewares = $reflectionProperty->getValue($controller); foreach ($middlewares as $key => $val) { if (!is_int($key)) { if (isset($val['only']) && !in_array($this->request->action(true), array_map(function ($item) { return strtolower($item); }, is_string($val['only']) ? explode(",", $val['only']) : $val['only']))) { continue; } elseif (isset($val['except']) && in_array($this->request->action(true), array_map(function ($item) { return strtolower($item); }, is_string($val['except']) ? explode(',', $val['except']) : $val['except']))) { continue; } else { $val = $key; } } if (is_string($val) && strpos($val, ':')) { $val = explode(':', $val); if (count($val) > 1) { $val = [$val[0], array_slice($val, 1)]; } } $this->middleware->controller($val); } } } protected function autoResponse($data): Response { if ($data instanceof Response) { $response = $data; } elseif (!is_null($data)) { // 默认自动识别响应输出类型 $type = $this->request->isJson() ? 'json' : 'html'; $response = Response::create($data, $type); } else { $data = ob_get_clean(); $content = false === $data ? '' : $data; $status = '' === $content && $this->request->isJson() ? 204 : 200; $response = Response::create($content, 'html', $status); } return $response; } }