企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] > 以下示例代码我们都假设模块为`index`,控制器为`IndexCtrl.php`,并且模块没有绑定域名,服务器支持rewrite,域名为`domain.com`。 ### 定义控制器 * Lying的控制器都是放在模块下的`controller`目录。 * Lying的控制器必须继承控制器基类`lying\base\Controller`。 * 控制器的命名是首字母大写的驼峰命名+`Ctrl`,如:`PostListCtrl.php`,类名应和文件名一致。 * 如果要创建不可访问的控制器,则去掉`Ctrl`即可,如:`PostList.php`。 * 控制器的命名空间是从`module`开始的`module\模块名\controller`。 ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { } ~~~ 这样一个最基本的控制器就定义好了。 ### 控制器方法 url访问的时候其实就是访问控制器的一个方法。我们这边举个栗子,定义一个`index`方法: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public function index() { return '我访问了' . __METHOD__; } } ~~~ 现在我们访问`domain.com/index/index/index`,是不是看到浏览器输出了`'我访问了index'`。方法里面`return`等同于`echo`,推荐用`return`,因为 [response](response.md) 类会对你所输出的值进行处理 ### 带参数方法 你可以为你的控制器设置参数,参数可以设置默认值,如果不设置默认值,就必须在url中带上该参数,参数名和变量名一致: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public function index($id, $name = 'lying') { } } ~~~ 现在你可以这样访问: ~~~html http://domain.com/index/index/index/id/3/name/yourname/ http://domain.com/index/index/index/id/3/ ~~~ 但是如果你这样访问的话,是要报错的: ~~~html http://domain.com/index/index/index/ http://domain.com/index/index/index/name/yourname/ ~~~ 因为你缺少了必须的参数`id` * * * * * 当然,你还可以如下操作: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public function index($id = 1, $name) { } } ~~~ 现在你可以这样访问: ~~~html http://domain.com/index/index/index/id/3/name/yourname/ http://domain.com/index/index/index/name/yourname/ ~~~ 但是如果你这样访问的话,是要报错的: ~~~html http://domain.com/index/index/index/ http://domain.com/index/index/index/id/3/ ~~~ 因为你缺少了必须的参数`name` > 你可以品味一下上述两种定义的区别 ### 初始化方法 * 你不能定义控制器的构造函数,因为控制器基类继承服务类,服务类的构造函数定义为`final`的,因为要执行特定功能。 * 你可以重写父类的`init`方法,这个方法类似构造函数执行,你可以把初始化代码写在这里: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public function init() { parent::init(); //你的逻辑 } } ~~~ > 请注意:如果重写`init`方法,请在方法首行调用`parent::init();`。 * 你还可以定义`beforeAction`方法(前置操作)和`afterAction`(后置操作)方法: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { //这个方法将在你要执行的方法之前执行 public function beforeAction($event) { //记得在这个方法的首行调用父级的beforeAction parent::beforeAction($event); //获取即将调用方法的ID $action = $event->action; //如果事件的return被设置为true,那么就不会再执行后面的方法和后置操作了 $event->return =true; } //这个方法将在你要执行的方法之后执行 public function afterAction($event) { //记得在这个方法的首行调用父级的afterAction parent::afterAction($event); //获取已经调用方法的ID $action = $event->action; //获取即将调用方法的返回值 $action = $event->response; } } ~~~ ### 方法过滤器 你看了上面的特定方法,如果担心用户会执行到你的`init`方法,或者`beforeAction`、`afterAction`方法,这个你完全不必担心,Lying为你提供了方法过滤器: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public $deny = [ //接受一个正则数组对方法名进行过滤 '/^user/', '/^before/' ]; } ~~~ 如上定义的属性`$deny`就是设定`user`和`before`开头的方法都不允许访问,抛出404错误。 > * 注意:控制器属性`$deny`必须设置为`public`。 > * `init`、`beforeAction`、`afterAction`三个方法已经默认被过滤了。 ### CSRF Lying默认在控制器的基类的`beforeAction`校验了CSRF的TOKEN值,如果你不喜欢,你可以重写`beforeAction`函数,如果你重写了`beforeAction`并且不需要默认的校验,你可以: ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public function beforeAction($event) { //parent::beforeAction($event); //注释掉此行则不会进行CSRF校验 //此处写你的逻辑代码 } } ~~~ ### 控制器快捷操作 ~~~php <?php namespace module\index\controller; use lying\base\Controller; class IndexCtrl extends Controller { public function index() { $module = $this->module; //当前控制器所属的模块ID $id = $this->id; //当前控制器所属的控制器ID $action = $this->action; //当前控制器执行的方法ID $this->assign('username', 'Lying'); //渲染参数到模板,更多使用方式请参考视图章节 return $this->render(); //渲染模板:当前模块/view/控制器ID/index.php,更多使用方式请参考视图章节 } } ~~~ ### 在控制器中获取外部输入 参见 [Request组件](request.md)