## 控制器定义 控制器文件通常放在`application/module/controller`下面,类名和文件名保持大小写一致,并采用驼峰命名(首字母大写)。 一个典型的控制器类定义如下: ~~~ <?php namespace app\index\controller; use think\Controller; class Index extends Controller { public function index() { return 'index'; } } ~~~ >[danger] 为了更方便使用,控制器类建议继承系统的控制器基类`think\Controller`,虽然无需继承也可以使用。 控制器类文件的实际位置是 ~~~ application\index\controller\Index.php ~~~ 访问URL地址是(假设没有定义路由的情况下) ~~~ http://localhost/index.php/index ~~~ 如果你的控制器是`HelloWorld`,并且定义如下: ~~~ <?php namespace app\index\controller; class HelloWorld { public function index() { return 'hello,world!'; } } ~~~ 控制器类文件的实际位置是 ~~~ application\index\controller\HelloWorld.php ~~~ 访问URL地址是(假设没有定义路由的情况下) ~~~ http://localhost/index.php/index/hello_world ~~~ 如果你期望通过 ~~~ http://localhost/index.php/index/HelloWorld ~~~ 可以访问,那么必须关闭URL的自动转换设置 ~~~ // 是否自动转换URL中的控制器和操作名 'url_convert' => false, ~~~ ## 控制器的命名空间 控制器类的所在命名空间为`app\module\controller`,其中根命名空间`app`为系统默认,并且只能通过环境变量设置更改,例如我们可以在`.env`配置文件中设置: ~~~ APP_NAMESPACE = application ~~~ 则实际的控制器类应该更改定义如下: ~~~ <?php namespace application\index\controller; class Index { public function index() { return 'index'; } } ~~~ >[danger] 只是命名空间改变了,但实际的文件位置和文件名并没有改变。 ## 单一模块控制器 在应用配置文件`app.php`中设置 ~~~ // 是否支持多模块 'app_multi_module' => false, ~~~ 可以启用单一模块,那么控制器的命名空间中不需要模块名了,类的定义就变成了 ~~~ <?php namespace app\controller; class Index { public function index() { return 'index'; } } ~~~ 控制器类文件的实际位置则变成 ~~~ application\controller\Index.php ~~~ ## 渲染输出 默认情况下,控制器的输出全部采用`return`的方式,无需进行任何的手动输出,系统会自动完成渲染内容的输出。 下面都是有效的输出方式: ~~~ <?php namespace app\index\controller; class Index { public function hello() { // 输出hello,world! return 'hello,world!'; } public function json() { // 输出JSON return json_encode($data); } public function read() { // 渲染默认模板输出 return view(); } } ~~~ > 控制器一般不需要任何输出,直接return即可。 ## 输出转换 默认情况下,控制器的返回输出不会做任何的数据处理,但可以设置输出格式,并进行自动的数据转换处理,前提是控制器的输出数据必须采用`return`的方式返回。 如果控制器定义为: ~~~ <?php namespace app\index\controller; class Index { public function hello() { return 'hello,world!'; } public function data() { return ['name'=>'thinkphp','status'=>1]; } } ~~~ 当我们设置输出数据格式为JSON: ~~~ // 默认输出类型 'default_return_type' => 'json', ~~~ 我们访问 ~~~ http://localhost/index.php/index/Index/hello http://localhost/index.php/index/Index/data ~~~ 输出的结果变成: ~~~ "hello,world!" {"name":"thinkphp","status":1} ~~~ 默认情况下,控制器在ajax请求会对返回类型自动转换,默认为json 如果我们控制器定义 ~~~ <?php namespace app\index\controller; class Index { public function data() { return ['name'=>'thinkphp','status'=>1]; } } ~~~ 我们访问 ~~~ http://localhost/index.php/index/Index/data ~~~ 输出的结果变成: ~~~ {"name":"thinkphp","status":1} ~~~ ## 多级控制器 支持任意层次级别的控制器,并且支持路由,例如: ~~~ <?php namespace app\index\controller\user; use think\Controller; class Blog extends Controller { public function index() { return 'index'; } } ~~~ 该控制器类的文件位置为: ~~~ application/index/controller/user/Blog.php ~~~ 访问地址可以使用 ~~~ http://serverName/index.php/index/user.blog/index ~~~ 由于URL访问不能访问默认的多级控制器(可能会把多级控制器名误识别为URL后缀),因此建议所有的多级控制器都通过路由定义后访问,如果要在路由定义中使用多级控制器,可以使用: ~~~ \think\Route::get('user/blog','index/user.blog/index'); ~~~ ## 自动定位控制器 如果你使用了多级控制器的话,可以设置`controller_auto_search`参数开启自动定位控制器,便于URL访问,首先在应用配置文件中设置: ~~~ 'controller_auto_search' => true, ~~~ 然后定义控制器如下: ~~~ <?php namespace app\index\controller\user; use think\Controller; class Blog extends Controller { public function index() { return 'index'; } } ~~~ 我们就可以直接访问下面的URL地址了: ~~~ http://serverName/index.php/index/user/Blog ~~~ ## 控制器初始化 如果你的控制器类继承了系统控制器基类(`\think\Controller`)的话,可以定义控制器初始化方法`initialize`,该方法会在调用控制器的方法之前首先执行,如非必要,不建议直接修改控制器的架构函数。 例如: ~~~ <?php namespace app\index\controller; use think\Controller; class Index extends Controller { protected function initialize() { echo 'init<br/>'; } public function hello() { return 'hello'; } public function data() { return 'data'; } } ~~~ >[danger] `initialize`方法不需要任何返回值 如果访问 ~~~ http://localhost/index.php/index/Index/hello ~~~ 会输出 ~~~ init hello ~~~ 如果访问 ~~~ http://localhost/index.php/index/Index/data ~~~ 会输出 ~~~ init data ~~~