[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)
- 序言
- 更新日志
- 安装
- 规范
- 常量
- 配置
- 自动加载
- MVC
- 模块
- 控制器
- 模型
- 视图
- php原生模板
- 模板引擎
- 变量输出
- 模板注释
- 模板继承
- 模板引用
- 流程控制
- 原样输出
- 服务组件
- Hook组件
- Request组件
- Router组件
- Cookie组件
- Encrypter组件
- Dispatch组件
- Response组件
- View组件
- Session组件
- Helper组件
- 数据分页
- 数据验证
- Logger组件
- Cache组件
- Redis组件
- Connection组件
- 执行sql语句
- 查询生成器
- 查询方法详解
- Schema
- Captcha组件
- CLI
- CLI工具
- 事件
- 类事件
- 实例事件
- 全局事件
- 助手函数
- 扩展
- 异常
- 部署
- Apache
- Nginx
- IIS
- 虚拟主机