chengkun
2025-06-05 4080b5997b38ca84b3b203c7101dcadb97b76925
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 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 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);
 
        $path = $this->dispatch;
        if (is_string($path)) {
            $path = explode('/', $path);
        }
 
        $action     = !empty($path) ? array_pop($path) : $this->rule->config('default_action');
        $controller = !empty($path) ? array_pop($path) : $this->rule->config('default_controller');
        $layer      = !empty($path) ? implode('/', $path) : '';
 
        if ($layer && !empty($this->option['auto_middleware'])) {
            // 自动为顶层layer注册中间件
            $alias = $app->config->get('middleware.alias', []);
 
            if (isset($alias[$layer])) {
                $this->app->middleware->add($layer, 'route');
            }
        }
 
        // 获取控制器名和分层(目录)名
        if (str_contains($controller, '.')) {
            $pos        = strrpos($controller, '.');
            $layer      = ($layer ? $layer . '.' : '') . substr($controller, 0, $pos);
            $controller = Str::studly(substr($controller, $pos + 1));
        } else {
            $controller = Str::studly($controller);
        }
 
        $this->actionName = strip_tags($action);
        $this->controller = strip_tags(($layer ? $layer . '.' : '') . $controller);
 
        // 设置当前请求的控制器、操作
        $this->request
            ->setLayer(strip_tags($layer))
            ->setController($this->controller)
            ->setAction($this->actionName);
    }
 
    public function exec()
    {
        try {
            // 实例化控制器
            $instance = $this->controller($this->controller);
        } catch (ClassNotFoundException $e) {
            throw new HttpException(404, 'controller not exists:' . $e->getClass());
        }
 
        return $this->responseWithMiddlewarePipeline($instance, $this->actionName);
    }
 
    /**
     * 实例化访问控制器
     * @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);
    }
}