| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- <?php
- // +----------------------------------------------------------------------
- // | ThinkPHP [ WE CAN DO IT JUST THINK ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
- // +----------------------------------------------------------------------
- // | Author: liu21st <liu21st@gmail.com>
- // +----------------------------------------------------------------------
- declare (strict_types = 1);
- namespace think\route\dispatch;
- use ReflectionClass;
- use ReflectionException;
- use ReflectionMethod;
- use think\App;
- use think\exception\ClassNotFoundException;
- use think\exception\HttpException;
- use think\helper\Str;
- use think\route\Dispatch;
- /**
- * Controller Dispatcher
- */
- class Controller extends Dispatch
- {
- /**
- * 控制器名
- * @var string
- */
- protected $controller;
- /**
- * 操作名
- * @var string
- */
- protected $actionName;
- public function init(App $app)
- {
- parent::init($app);
- $result = $this->dispatch;
- if (is_string($result)) {
- $result = explode('/', $result);
- }
- // 获取应用名
- $appName = $result[0] ?: config('app.default_app');
- // 获取控制器名
- $controller = strip_tags($result[1] ?: $this->rule->config('default_controller'));
- if (strpos($controller, '.')) {
- $pos = strrpos($controller, '.');
- $this->controller = substr($controller, 0, $pos) . '.' . Str::studly(substr($controller, $pos + 1));
- } else {
- $this->controller = Str::studly($controller);
- }
- $app->http->name($appName);
- $appNamespace = defined('APP_NAMESPACE') ? APP_NAMESPACE : 'app';
- $app->setNamespace($appNamespace . '\\' . $appName);
- // 获取操作名
- $result[2] = stristr($result[2], '?', true) ?: $result[2];
- $this->actionName = strip_tags($result[2] ?: $this->rule->config('default_action'));
- // 设置当前请求的控制器、操作
- $this->request
- ->setController($this->controller)
- ->setAction($this->actionName);
- }
- public function exec()
- {
- $this->app->event->trigger('ModuleInit');
- $appName = $this->app->http->getName();
- $appPath = $this->app->getAppPath() . $appName . DIRECTORY_SEPARATOR;
- // 加载应用event
- if (is_file($appPath . 'event.php')) {
- $this->app->loadEvent(include $appPath . 'event.php');
- }
- // 加载应用service
- if (is_file($appPath . 'service.php')) {
- $services = include $appPath . 'service.php';
- foreach ($services as $service) {
- $this->app->register($service);
- }
- }
- try {
- // 实例化控制器
- $instance = $this->controller($this->controller);
- } catch (ClassNotFoundException $e) {
- throw new HttpException(404, 'controller not exists:' . $e->getClass());
- }
- // 注册控制器中间件
- $this->registerControllerMiddleware($instance);
- return $this->app->middleware->pipeline('controller')
- ->send($this->request)
- ->then(function () use ($instance) {
- // 获取当前操作名
- $suffix = $this->rule->config('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 (ReflectionException $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 . '()');
- }
- $this->app->event->trigger('ActionBegin');
- $data = $this->app->invokeReflectMethod($instance, $reflect, $vars);
- return $this->autoResponse($data);
- });
- }
- /**
- * 使用反射机制注册控制器中间件
- * @access public
- * @param object $controller 控制器实例
- * @return void
- */
- 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->app->middleware->controller($val);
- }
- }
- }
- /**
- * 实例化访问控制器
- * @access public
- * @param string $name 资源地址
- * @return object
- * @throws ClassNotFoundException
- */
- public function controller(string $name)
- {
- $suffix = $this->rule->config('controller_suffix') ? 'Controller' : '';
- $controllerLayer = $this->rule->config('controller_layer') ?: 'controller';
- $emptyController = $this->rule->config('empty_controller') ?: 'Error';
- $class = $this->app->parseClass($controllerLayer, $name . $suffix);
- if (class_exists($class)) {
- return $this->app->make($class, [], true);
- } elseif ($emptyController && class_exists($emptyClass = $this->app->parseClass($controllerLayer, $emptyController . $suffix))) {
- return $this->app->make($emptyClass, [], true);
- }
- throw new ClassNotFoundException('class not exists:' . $class, $class);
- }
- }
|