# 行为扩展
[上一页](# "上一页")[下一页](# "下一页")
### 行为和标签
行为在新版ThinkPHP的架构里面起着举足轻重的作用,在系统核心之上,设置了很多标签扩展位,而每个标签位置可以依次执行各自的独立行为。行为扩展就因此而诞生了,而且很多系统功能也是通过内置的行为扩展完成的,所有行为扩展都是可替换和增加的,由此形成了底层框架可组装的基础。
系统核心提供的标签位置包括下面几个(按照执行顺序排列):
| app_init | 应用初始化标签位 |
|-----|-----|
| path_info | PATH_INFO检测标签位 |
| route_check | 路由检测标签位 |
| app_begin | 应用开始标签位 |
| action_name | 操作方法名标签位 |
| action_begin | 控制器开始标签位 |
| view_begin | 视图输出开始标签位 |
| view_template | 视图模板解析标签位 |
| view_parse | 视图解析标签位 |
| view_filter | 视图输出过滤标签位 |
| view_end | 视图输出结束标签位 |
| action_end | 控制器结束标签位 |
| app_end | 应用结束标签位 |
在每个标签位置,可以配置多个行为定义,行为的执行顺序按照定义的顺序依次执行。除非前面的行为里面中断执行了(某些行为可能需要中断执行,例如检测机器人或者非法执行行为),否则会继续下一个行为的执行。
除了这些系统内置标签之外,开发人员还可以在应用中添加自己的应用标签,例如我们给应用的公共Action类CommonAction添加一个action_init标签位。`Class CommonAction extends Action{
Public function _initialize(){
tag('action_init'); // 添加action_init 标签
}
}`注意:tag函数用于设置某个标签位,可以传入并且只接受一个参数,如果需要传入多个参数,请使用数组,该参数为引用传值,所以只能传入变量。
### 内置行为
新版系统的很多核心功能也是采用行为扩展组装的,虽然在开发过程中可能感觉不到这种变化,但正是由于这种架构设计的改变,让新版变得更加灵活和易扩展,这是一个里程碑式的改变,对于满足项目日益纷繁复杂的需求和定制底层框架提供了更多的方便和可能性。
内置的行为包括下面:
| 行为名称 | 说明 | 对应标签位置 |
|-----|-----|-----|
| checkRoute | 路由检测行为,完成内置的路由功能 | route_check |
| LocationTemplate | 模板定位行为,完成模板文件自动定位和输出规则 | view_template |
| ParseTemplate | 模板文件解析,并支持第三方模板引擎驱动 | view_parse |
| ShowPageTrace | 页面Trace功能行为,完成页面Trace功能 | view_end |
| ShowRuntime | 运行时间显示行为,完成运行时间显示 | view_filter |
| TokenBuild | 令牌生成行为,完成表单令牌的自动生成 | view_filter |
| ReadHtmlCache | 读取静态缓存行为 | app_init |
| WriteHtmlCache | 生成静态缓存行为 | view_filter |
### 行为扩展
行为扩展首先是定义行为类,然后加入某个标签位置即可,内置的行为扩展就是一个很好的扩展示例。行为扩展类继承内置的行为基础类Behavior即可,类的命名规范是:
行为名称+Behavior
行为的执行入口方法是run方法,因此行为类只需要run方法具备public访问权限,入口方法只支持一个参数(可以用数组),并且采用引用方式传参,因此不需要任何返回值。每个行为可以定义options属性,该属性中的参数会自动转换成单独配置参数,下面是一个示例:`class TestBehavior extends Behavior {
// 行为参数定义
protected $options = array(
'TEST_PARAM' => false, // 行为参数 会转换成TEST_PARAM配置参数
);
// 行为扩展的执行入口必须是run
public function run(&$params){
if(C('TEST_PARAM')) {
echo 'RUNTEST BEHAVIOR '.$params;
}
}`我们把TestBehavior行为扩展类放到项目目录的Lib/Behavior目录下面,其中options属性必须是数组方式定义,而且在行为初始化的同时options属性中的参数会转换成全局的配置参数,所以,我们在入口方法里面可以直接使用:`C('TEST_PARAM ')`TEST_PARAM参数是没有预先定义的,行为的options属性里面提供的参数只是一个初始值,所有的参数我们可以在项目配置文件中重新定义。例如,上面的Test行为如果要执行,我们需要在项目配置文件中添加下面的配置:`'TEST_PARAM' =>true`
### 行为调用
定义了一个行为扩展之后,系统提供了三种方式可以调用行为:
一、添加到行为配置文件
为了执行Test行为,我们在这里把Test行为加入app_end 标签位置,在项目配置目录中添加tags.php文件,在其中添加下面代码:`return array(
'app_end'=>array('Test'), // 在app_end 标签位添加Test行为
);`tags文件是项目的行为定义文件,在这个文件中可以给每个标签位置添加项目自己的扩展行为,当然你也可以添加到应用自己的标签位,例如,我们可以把Test行为添加到前面项目自己定义的action_init标签位置:`return array(
'action_init'=>array('Test'), // 在action_init 标签位添加Test行为
);`应用行为的定义没有限制,你甚至可以把同一个行为放到多个标签位置执行多次,例如:`return array(
'app_begin'=>array('Test'), // 在app_begin 标签位添加Test行为
'app_end'=>array('Test'), // 在app_end 标签位添加Test行为
);`默认情况下应用行为扩展会并入系统行为扩展一起执行,也就是说如果系统的行为定义中app_end标签中已经定义了其他行为,会首先执行系统行为扩展,然后再执行应用行为扩展,如果你希望项目的行为扩展完全替换系统的行为扩展,可以使用:`return array(
'app_end'=>array('Test','_overlay'=>1),
);`表示app_end标签位用定义的应用行为完全替换该位置的系统行为,也就是说即使系统标签在app_end定义了其他的系统行为也不会被执行,但是必须注意,行为的命名不要和系统行为一样。
二、函数方式动态定义
除了定义tags行为配置文件之外,系统还提供了动态添加行为到标签位的方法,例如我们可以使用下面的方式添加Test行为到app_end标签位,而无需在tags文件中添加定义:
add_tag_behavior('app_end','Test');
表示把Test行为添加到app_end标签位的最后,你可以把这个代码放到项目的公共函数文件中甚至直接放到行为类的最后(如果你确定这个行为扩展只有你的项目会用到的话)。
应用行为扩展类除了放到项目类库的Behavior目录外, 还可以放到系统的行为扩展目录Extend/Behavior/,行为类在执行过程中会自动加载。
三、不放入标签直接执行
有时候,行为的调用不一定要放到标签才能调用,如果需要的话,我们可以在控制器中直接调用行为。例如,我们可以把用户权限检测封装成一个行为类,例如:`class AuthCheckBehavior extends Behavior {
// 行为参数定义
protected $options = array(
'USER_AUTH_ON' =>false, // 是否开启用户认证
'USER_AUTH_ID' => 'user_id', // 定义用户的id为权限认证字段
);
// 行为扩展的执行入口必须是run
public function run(&$return){
if(C('USER_AUTH_ON ')) {
// 进行权限认证逻辑 如果认证通过 $return = true;
// 否则用halt输出错误信息
}
}`定义了AuthCheck行为后,然后在_initialize方法中直接用下面的方式调用:`B('AuthCheck');`
注意:因为这种方式的行为调用需要在相关位置添加代码,所以一般只有在应用代码才直接使用B方法调用。
[上一页](# "上一页")[下一页](# "下一页")
- 序言
- 1. 入门
- 1.1 简介
- 1.2 基础概念
- 1.3 获取ThinkPHP
- 1.4 环境要求
- 1.5 许可协议
- 1.6 目录结构
- 1.7 命名规范
- 1.8 MVC分层
- 1.9 CBD架构
- 1.10 特性概述
- 1.11 系统流程
- 1.12 开发流程
- 2. 入口
- 2.1 入口文件
- 2.2 项目目录
- 2.3 部署目录
- 2.4 项目编译
- 2.5 调试模式
- 3. 配置
- 3.1 配置格式
- 3.2 惯例配置
- 3.3 项目配置
- 3.4 调试配置
- 3.5 分组配置
- 3.6 读取配置
- 3.7 动态配置
- 3.8 扩展配置
- 4. 函数和类库
- 4.1 函数库
- 4.2 类库
- 5. 控制器
- 5.1 URL模式
- 5.2 模块和操作
- 5.3 定义控制器
- 5.4 空操作
- 5.5 空模块
- 5.6 模块分组
- 5.7 URL伪静态
- 5.8 URL路由
- 5.9 URL重写
- 5.10 URL生成
- 5.11 URL大小写
- 5.12 前置和后置操作
- 5.13 跨模块调用
- 5.14 页面跳转
- 5.15 重定向
- 5.16 获取系统变量
- 5.17 判断请求类型
- 5.18 获取URL参数
- 5.19 AJAX返回
- 5.20 Action参数绑定
- 5.21 多层控制器支持
- 6. 模型
- 6.1 模型定义
- 6.2 模型实例化
- 6.3 字段定义
- 6.4 数据主键
- 6.5 属性访问
- 6.6 跨库操作
- 6.7 连接数据库
- 6.8 切换数据库
- 6.9 分布式数据库
- 6.10 创建数据
- 6.11 字段映射
- 6.12 连贯操作
- 6.13 CURD操作
- 6.14 ActiveRecord
- 6.15 自动验证
- 6.16 命名范围
- 6.17 自动完成
- 6.18 查询语言
- 6.19 查询锁定
- 6.20 字段排除
- 6.21 事务支持
- 6.22 高级模型
- 6.23 视图模型
- 6.24 关联模型
- 6.25 Mongo模型
- 6.26 动态模型
- 6.27 虚拟模型
- 6.28 多层模型支持
- 7. 视图
- 7.1 模板定义
- 7.2 模板赋值
- 7.3 模板输出
- 7.4 模板替换
- 7.5 获取内容
- 7.6 模板引擎
- 7.7 布局模板
- 8. 模板引擎
- 8.1 变量输出
- 8.2 系统变量
- 8.3 使用函数
- 8.4 默认值输出
- 8.5 使用运算符
- 8.6 内置标签
- 8.7 包含文件
- 8.8 导入文件
- 8.9 Volist标签
- 8.10 Foreach标签
- 8.11 For标签
- 8.12 Switch标签
- 8.13 比较标签
- 8.14 三元运算
- 8.15 范围判断标签
- 8.16 Present标签
- 8.17 Empty标签
- 8.18 Defined标签
- 8.19 Define标签
- 8.20 Assign标签
- 8.21 IF标签
- 8.22 标签嵌套
- 8.23 使用PHP代码
- 8.24 模板布局
- 8.25 模板继承
- 8.26 原样输出
- 8.27 模板注释
- 8.28 引入标签库
- 8.29 修改定界符
- 8.30 避免JS混淆
- 9. 日志
- 9.1 日志级别
- 9.2 记录方式
- 9.3 手动记录
- 10. 错误
- 10.1 异常处理
- 10.2 异常模板
- 10.3 异常显示
- 11. 调试
- 11.1 运行状态
- 11.2 页面Trace
- 11.3 调试方法
- 12. 缓存
- 12.1 缓存方式
- 12.2 动态缓存
- 12.3 缓存队列
- 12.4 快捷缓存
- 12.5 快速缓存
- 12.6 查询缓存
- 12.7 SQL解析缓存
- 12.8 静态缓存
- 13. 扩展
- 13.1 行为扩展
- 13.2 类库扩展
- 13.3 控制器扩展
- 13.4 模型扩展
- 13.5 驱动扩展
- 13.6 Widget扩展
- 13.7 模式扩展
- 13.8 引擎扩展
- 14. 安全
- 14.1 表单令牌
- 14.2 字段类型验证
- 14.3 防止SQL注入
- 14.4 输入过滤
- 14.5 上传安全
- 14.6 防止XSS攻击
- 14.7 其他安全建议
- 14.8 目录安全文件
- 14.9 保护模板文件
- 15. 性能
- 15.1 关闭调试模式
- 15.2 开启缓存
- 15.3 合并字段缓存
- 15.4 优化SQL
- 15.5 替换入口
- 15.6 前端优化
- 16. 部署
- 16.1 PATH_INFO支持
- 16.2 隐藏index.php
- 16.3 二级域名部署
- 16.4 定制错误页面
- 16.5 设置时区
- 17. SAE支持
- 17.1 SAE介绍
- 17.2 获取SAE
- 17.3 SAE开发
- 18. REST支持
- 18.1 REST介绍
- 18.2 REST模式
- 18.3 REST配置
- 18.4 REST路由
- 18.5 REST方法
- 19. 杂项
- 19.1 Session支持
- 19.2 Cookie支持
- 19.3 日期和时间
- 19.4 WML开发
- 19.5 多语言
- 19.6 数据分页
- 19.7 文件上传
- 19.8 验证码
- 19.9 图片添加水印
- 19.10 IP获取和定位
- 20. 附录
- 20.1 常量参考
- 20.2 配置参考
- 20.3 关于升级
- 20.4 大事记
- 鸣谢
- 关于