基本概念

个人理解:url访问到的逻辑代码

目录结构

控制器文件通常放在controller下面,类名和文件名保持大小写一致,并采用驼峰命名(首字母大写)。
如果要改变controller目录名,需要在route.php配置文件中设置:

  1. 'controller_layer' => 'controllers',

单应用模式

单应用模式控制器的类的定义如下:

  1. <?php
  2. namespace app\controller;
  3. class User
  4. {
  5. public function login()
  6. {
  7. return 'login';
  8. }
  9. }

控制器类文件的实际位置是

  1. app\controller\User.php

访问URL地址是(假设没有定义路由的情况下)

  1. http://localhost/user/login

如果你的控制器是HelloWorld,并且定义如下:

  1. <?php
  2. namespace app\controller;
  3. class HelloWorld
  4. {
  5. public function hello()
  6. {
  7. return 'hello,world!';
  8. }
  9. }

控制器类文件的实际位置是

  1. app\controller\HelloWorld.php

访问URL地址是(假设没有定义路由的情况下)

  1. http://localhost/index.php/HelloWorld/hello

并且也可以支持下面的访问URL

  1. http://localhost/hello_world/hello

多应用模式

多应用模式下,控制器类定义仅仅是命名空间有所区别,例如:

  1. <?php
  2. namespace app\home\controller;
  3. class User
  4. {
  5. public function login()
  6. {
  7. return 'login';
  8. }
  9. }

控制器类文件的实际位置是

  1. app\home\controller\User.php

访问URL地址是(假设没有定义路由的情况下)

  1. http://localhost/index.php/home/user/login

多级控制器(控制器子目录)

支持任意层次级别的控制器,并且支持路由,例如:

  1. <?php
  2. namespace app\home\controller\user;
  3. class Blog
  4. {
  5. public function index()
  6. {
  7. return 'index';
  8. }
  9. }

该控制器类的文件位置为:

  1. app/home/controller/user/Blog.php

访问地址可以使用

  1. http://serverName/home.php/user.blog/index

由于URL访问不能访问默认的多级控制器(可能会把多级控制器名误识别为URL后缀),因此建议所有的多级控制器都通过路由定义后访问,如果要在路由定义中使用多级控制器,可以使用:

  1. Route::get('user/blog/index','user.blog/index');

渲染输出

默认情况下,控制器的输出全部采用return的方式,无需进行任何的手动输出,系统会自动完成渲染内容的输出。
下面都是有效的输出方式:

  1. <?php
  2. namespace app\index\controller;
  3. class Index
  4. {
  5. public function hello()
  6. {
  7. // 输出hello,world!
  8. return 'hello,world!';
  9. }
  10. public function json()
  11. {
  12. // 输出JSON
  13. return json($data);
  14. }
  15. public function read()
  16. {
  17. // 渲染默认模板输出
  18. return view();
  19. }
  20. }

控制器一般不需要任何输出,直接return即可。并且控制器在json请求会自动转换为json格式输出。

不要在控制器中使用包括die、exit在内的中断代码。如果你需要调试并中止执行,可以使用系统提供的halt助手函数。

  1. halt('输出测试');

基础控制器

大多数情况下,我们建议给你的控制器继承一个基础控制器,基础控制器建议按照不同的应用分别设置。
默认安装后,系统提供了一个app\BaseController基础控制器类,你可以对该基础控制器进行修改。

基础控制器的位置可以随意放置,只需要注意更改命名空间即可。

基础控制器模板

  1. <?php
  2. declare(strict_types=1);
  3. namespace app\home;
  4. use think\App;
  5. use think\exception\ValidateException;
  6. use think\Validate;
  7. /**
  8. * 控制器基础类
  9. */
  10. abstract class BaseController {
  11. /**
  12. * Request实例
  13. * @var \think\Request
  14. */
  15. protected $request;
  16. /**
  17. * 应用实例
  18. * @var \think\App
  19. */
  20. protected $app;
  21. /**
  22. * 是否批量验证
  23. * @var bool
  24. */
  25. protected $batchValidate = false;
  26. /**
  27. * 控制器中间件
  28. * @var array
  29. */
  30. protected $middleware = [];
  31. /**
  32. * 构造方法
  33. * @access public
  34. * @param App $app 应用对象
  35. */
  36. public function __construct(App $app) {
  37. $this->app = $app;
  38. $this->request = $this->app->request;
  39. // 控制器初始化
  40. $this->initialize();
  41. }
  42. // 初始化
  43. protected function initialize() {
  44. }
  45. /**
  46. * 验证数据
  47. * @access protected
  48. * @param array $data 数据
  49. * @param string|array $validate 验证器名或者验证规则数组
  50. * @param array $message 提示信息
  51. * @param bool $batch 是否批量验证
  52. * @return array|string|true
  53. * @throws ValidateException
  54. */
  55. protected function validate(array $data, $validate, array $message = [], bool $batch = false) {
  56. if (is_array($validate)) {
  57. $v = new Validate();
  58. $v->rule($validate);
  59. } else {
  60. if (strpos($validate, '.')) {
  61. // 支持场景
  62. [$validate, $scene] = explode('.', $validate);
  63. }
  64. $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
  65. $v = new $class();
  66. if (!empty($scene)) {
  67. $v->scene($scene);
  68. }
  69. }
  70. $v->message($message);
  71. // 是否批量验证
  72. if ($batch || $this->batchValidate) {
  73. $v->batch(true);
  74. }
  75. return $v->failException(true)->check($data);
  76. }
  77. }

一般文件位置(多应用,位置可以自定义,但是建议放到多应用目录下)
该控制器类的文件位置为:

  1. app/home/BaseController.php

控制器后缀

如果你希望避免引入同名模型类的时候冲突,可以在route.php配置文件中设置

  1. // 使用控制器后缀
  2. 'controller_suffix' => true,

这样,上面的控制器类就需要改成

  1. <?php
  2. namespace app\controller;
  3. class UserController
  4. {
  5. public function login()
  6. {
  7. return 'login';
  8. }
  9. }

相应的控制器类文件也要改为

  1. app\controller\UserController.php

完整模板

控制器后缀&基础控制器&多应用模式&多级控制器
设定基础多应用为:home

目录结构

开启了控制器后缀,因此控制文件名后面要加入Controller,对应的类上面也加入Controller

  1. app/home/BaseController.php
  2. app/home/user/LoginController.php

文件内容

文件:app/home/BaseController.php

  1. <?php
  2. declare(strict_types=1);
  3. namespace app\home;
  4. use think\App;
  5. use think\exception\ValidateException;
  6. use think\Validate;
  7. /**
  8. * 控制器基础类
  9. */
  10. abstract class BaseController {
  11. /**
  12. * Request实例
  13. * @var \think\Request
  14. */
  15. protected $request;
  16. /**
  17. * 应用实例
  18. * @var \think\App
  19. */
  20. protected $app;
  21. /**
  22. * 是否批量验证
  23. * @var bool
  24. */
  25. protected $batchValidate = false;
  26. /**
  27. * 控制器中间件
  28. * @var array
  29. */
  30. protected $middleware = [];
  31. /**
  32. * 构造方法
  33. * @access public
  34. * @param App $app 应用对象
  35. */
  36. public function __construct(App $app) {
  37. $this->app = $app;
  38. $this->request = $this->app->request;
  39. // 控制器初始化
  40. $this->initialize();
  41. }
  42. // 初始化
  43. protected function initialize() {
  44. }
  45. /**
  46. * 验证数据
  47. * @access protected
  48. * @param array $data 数据
  49. * @param string|array $validate 验证器名或者验证规则数组
  50. * @param array $message 提示信息
  51. * @param bool $batch 是否批量验证
  52. * @return array|string|true
  53. * @throws ValidateException
  54. */
  55. protected function validate(array $data, $validate, array $message = [], bool $batch = false) {
  56. if (is_array($validate)) {
  57. $v = new Validate();
  58. $v->rule($validate);
  59. } else {
  60. if (strpos($validate, '.')) {
  61. // 支持场景
  62. [$validate, $scene] = explode('.', $validate);
  63. }
  64. $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
  65. $v = new $class();
  66. if (!empty($scene)) {
  67. $v->scene($scene);
  68. }
  69. }
  70. $v->message($message);
  71. // 是否批量验证
  72. if ($batch || $this->batchValidate) {
  73. $v->batch(true);
  74. }
  75. return $v->failException(true)->check($data);
  76. }
  77. }

文件:app/home/user/LoginController.php

  1. <?php
  2. declare(strict_types=1);
  3. namespace app\home\controller\user;
  4. // 引入基础控制器命名空间
  5. use app\home\BaseController;
  6. class LoginController extends BaseController {
  7. public function index() {
  8. return "controller\user:Login@index";
  9. }
  10. }

访问URL

访问地址可以使用

  1. http://serverName/home.php/user.login/index

定义路由访问
定义:

  1. Route::get('user/login/index','user.login/index');

URL

  1. http://serverName/home.php/user/login/index

空控制器(暂未理解)

空控制器的概念是指当系统找不到指定的控制器名称的时候,系统会尝试定位当前应用下的空控制器(Error)类,利用这个机制我们可以用来定制错误页面和进行URL的优化。
例如,下面是单应用模式下,我们可以给项目定义一个Error控制器类。

  1. <?php
  2. namespace app\controller;
  3. class Error{
  4. public function __call($method, $args)
  5. {
  6. return 'error request!';
  7. }
  8. }

控制器中间件(暂未理解)

官方地址:https://www.kancloud.cn/manual/thinkphp6_0/1037515