ThinkPHP从3.0版本开始引入了全新的CBD(核心Core+行为Behavior+驱动Driver)架构模式,因为从底层开始,框架就采用核心+行为+驱动的架构体系,核心保留了最关键的部分,并在重要位置设置了标签用以标记,其他功能都采用行为扩展和驱动的方式组合,开发人员可以根据自己的需要,对某个标签位置进行行为扩展或者替换,就可以方便的定制框架底层,也可以在应用层添加自己的标签位置和添加应用行为。而标签位置类似于AOP概念中的“切面”,行为都是围绕这个“切面”来进行编程。

Core(核心)

ThinkPHP的核心部分包括核心函数库、惯例配置、核心类库(包括基础类和内置驱动及核心行为),这些是ThinkPHP必不可少的部分。

  1. ThinkPHP/Common/functions.php // 核心函数库
  2. ThinkPHP/Conf/convention.php // 惯例配置文件
  3. ThinkPHP/Conf/debug.php // 惯例调试配置文件
  4. ThinkPHP/Mode/common.php // 普通模式定义文件
  5. ThinkPHP/Library/Think // 核心类库包
  6. ThinkPHP/Library/Behavior // 系统行为类库
  7. ThinkPHP/Library/Think/App.class.php // 核心应用类
  8. ThinkPHP/Library/Think/Behavior.class.php // 基础行为类
  9. ThinkPHP/Library/Think/Cache.class.php // 核心缓存类
  10. ThinkPHP/Library/Think/Controller.class.php // 基础控制器类
  11. ThinkPHP/Library/Think/Db.class.php // 数据库操作类
  12. ThinkPHP/Library/Think/Dispatcher.class.php // URL解析调度类
  13. ThinkPHP/Library/Think/Exception.class.php // 系统基础异常类
  14. ThinkPHP/Library/Think/Hook.class.php // 系统钩子类
  15. ThinkPHP/Library/Think/Log.class.php // 系统日志记录类
  16. ThinkPHP/Library/Think/Model.class.php // 系统基础模型类
  17. ThinkPHP/Library/Think/Route.class.php // 系统路由类
  18. ThinkPHP/Library/Think/Storage.class.php // 系统存储类
  19. ThinkPHP/Library/Think/Template.class.php // 内置模板引擎类
  20. ThinkPHP/Library/Think/Think.class.php // 系统引导类
  21. ThinkPHP/Library/Think/View.class.php // 系统视图类

Behavior目录下面是系统内置的一些行为类库,内置驱动则分布在各个不同的驱动目录下面(参考下面的驱动部分)。

Driver(驱动)

3.2在架构设计上更加强化了驱动的设计,替代了之前的引擎和模式扩展,并且改进了行为的设计,使得框架整体更加灵活,并且由于在需要写入数据的功能类库中都采用了驱动化的设计思想,所以使得新的框架能够轻松满足分布式部署的需求,对云平台的支持可以更简单的实现了。因此,在新版的扩展里面,已经取消了引擎扩展和模式扩展,改成配置不同的应用模式即可。

驱动包括

  1. ThinkPHP/Library/Think/Cache/Driver // 缓存驱动类库
  2. ThinkPHP/Library/Think/Db/Driver // 数据库驱动类库
  3. ThinkPHP/Library/Think/Log/Driver // 日志记录驱动类库
  4. ThinkPHP/Library/Think/Session/Driver // Session驱动类库
  5. ThinkPHP/Library/Think/Storage/Driver // 存储驱动类库
  6. ThinkPHP/Library/Think/Template/Driver // 第三方模板引擎驱动类库
  7. ThinkPHP/Library/Think/Template/TagLib // 内置模板引擎标签库扩展类库

Behavior(行为)

行为(Behavior)是ThinkPHP扩展机制中比较关键的一项扩展,行为既可以独立调用,也可以绑定到某个标签(位)中进行侦听。这里的行为指的是一个比较抽象的概念,你可以想象成在应用执行过程中的一个动作或者处理,在框架的执行流程中,各个位置都可以有行为产生,例如路由检测是一个行为,静态缓存是一个行为,用户权限检测也是行为,大到业务逻辑,小到浏览器检测、多语言检测等等都可以当做是一个行为,甚至说你希望给你的网站用户的第一次访问弹出Hello,world!这些都可以看成是一种行为,行为的存在让你无需改动框架和应用,而在外围通过扩展或者配置来改变或者增加一些功能。

而不同的行为之间也具有位置共同性,比如,有些行为的作用位置都是在应用执行前,有些行为都是在模板输出之后,我们把这些行为发生作用的位置称之为标签(位),也可以称之为钩子,当应用程序运行到这个标签的时候,就会被拦截下来,统一执行相关的行为,类似于AOP编程中的“切面”的概念,给某一个标签绑定相关行为就成了一种类AOP编程的思想。

系统标签位

系统核心提供的标签位置包括(按照执行顺序排列):

  • app_init 应用初始化标签位
  • module_check 模块检测标签位(3.2.1版本新增
  • path_info PATH_INFO检测标签位
  • app_begin 应用开始标签位
  • action_name 操作方法名标签位
  • action_begin 控制器开始标签位
  • view_begin 视图输出开始标签位
  • view_template 视图模板解析标签位
  • view_parse 视图解析标签位
  • template_filter 模板解析过滤标签位
  • view_filter 视图输出过滤标签位
  • view_end 视图输出结束标签位
  • action_end 控制器结束标签位
  • app_end 应用结束标签位

在每个标签位置,可以配置多个行为,行为的执行顺序按照定义的顺序依次执行。除非前面的行为里面中断执行了(某些行为可能需要中断执行,例如检测机器人或者非法执行行为),否则会继续下一个行为的执行。

除了这些系统内置标签之外,开发人员还可以在应用中添加自己的应用标签,在任何需要拦截的位置添加如下代码即可:

  1. tag('my_tag'); // 添加my_tag 标签侦听
  2. // 下面的写法作用一致
  3. \Think\Hook::listen('my_tag');

tag函数用于设置某个标签位,可以传入并且只接受一个参数,如果需要传入多个参数,请使用数组,

  1. tag('my_tag',$params); // 添加my_tag 标签侦听

该参数为引用传值,所以只能传入变量,因此下面的传值是错误的:

  1. tag('my_tag','param'); // 添加my_tag 标签侦听
核心行为

系统的很多核心功能也是采用行为扩展组装的,对于满足项目日益纷繁复杂的需求和定制底层框架提供了更多的方便和可能性。

核心行为位于 ThinkPHP/Behavior/ 目录下面,框架核心内置的行为包括如下:

行为名称 说明 对应标签位置
BuildLite 生成Lite文件(3.2.1版本新增) app_init
ParseTemplate 模板文件解析,并支持第三方模板引擎驱动 view_parse
ShowPageTrace 页面Trace功能行为,完成页面Trace功能 view_end
ShowRuntime 运行时间显示行为,完成运行时间显示 view_filter
TokenBuild 令牌生成行为,完成表单令牌的自动生成 view_filter
ReadHtmlCache 读取静态缓存行为 app_init
WriteHtmlCache 生成静态缓存行为 view_filter
行为定义

自定义的扩展行为可以放在核心或者应用目录,只要遵循命名空间的定义规则即可。 行为类的命名采用:行为名称(驼峰法,首字母大写)+Behavior 行为类的定义方式如下:

  1. namespace Home\Behavior;
  2. use Think\Behavior;
  3. class TestBehavior extends Behavior {
  4. // 行为扩展的执行入口必须是run
  5. public function run(&$params){
  6. if(C('TEST_PARAM')) {
  7. echo 'RUNTEST BEHAVIOR '.$params;
  8. }
  9. }
  10. }

3.2.1版本开始,行为类的定义无需继承Think\Behavior类,所以,上面的定义可以简化为:

  1. namespace Home\Behavior;
  2. class TestBehavior {
  3. // 行为扩展的执行入口必须是run
  4. public function run(&$params){
  5. if(C('TEST_PARAM')) {
  6. echo 'RUNTEST BEHAVIOR '.$params;
  7. }
  8. }
  9. }

行为类必须定义执行入口方法run,由于行为的调用机制影响,run方法不需要任何返回值,所有返回都通过引用返回。

run方法的参数只允许一个,但可以传入数组。

行为绑定

行为定义完成后,就需要绑定到某个标签位置才能生效,否则是不会执行的。

我们需要在应用的行为定义文件tags.php文件中进行行为和标签的位置定义,格式如下:

  1. return array(
  2. '标签名称1'=>array('行为名1','行为名2',...),
  3. '标签名称2'=>array('行为名1','行为名2',...),
  4. );

标签名称包括我们前面列出的系统标签和应用中自己定义的标签名称,比如你需要在app_init标签位置定义一个CheckLangBehavior行为类的话,可以使用:

  1. return array(
  2. 'app_init'=>array('Home\Behavior\CheckLang'),
  3. // **如果是3.2.1版本 需要改成(后面不再重复说明)**
  4. // 'app_init'=>array('Home\Behavior\CheckLangBehavior'),
  5. );

可以给一个标签位定义多个行为,行为的执行顺序就是定义的先后顺序,例如:

  1. return array(
  2. 'app_init'=>array(
  3. 'Home\Behavior\CheckLang',
  4. 'Home\Behavior\CronRun'
  5. ),
  6. );

默认情况下tags.php中定义的行为会并入系统行为一起执行,也就是说如果系统的行为定义中app_init标签中已经定义了其他行为,则会首先执行系统行为扩展中定义的行为,然后再执行项目行为中定义的行为。例如: 系统行为定义文件中定义了:

  1. 'app_begin' => array(
  2. 'Behavior\ReadHtmlCache', // 读取静态缓存
  3. ),

而应用行为定义文件有定义:

  1. 'app_begin' => array(
  2. 'Home\Behavior\CheckModule',
  3. 'Home\Behavior\CheckLang',
  4. ),

则最终执行到app_begin标签(位)的时候,会依次执行:

  1. Library\Behavior\ReadHtmlCache
  2. Home\Behavior\CheckModule
  3. Home\Behavior\CheckLang

三个行为(除非中间某个行为有中止执行的操作)。

如果希望应用的行为配置文件中的定义覆盖系统的行为定义,可以改为为如下方式:

  1. 'app_begin' => array(
  2. 'Home\Behavior\CheckModule',
  3. 'Home\Behavior\CheckLang',
  4. '_overlay' => true,
  5. ),

则最终执行到app_begin标签(位)的时候,会依次执行下面两个行为:

  1. Home\Behavior\CheckModule
  2. Home\Behavior\CheckLang

应用行为的定义没有限制,你可以把一个行为绑定到多个标签位置执行,例如:

  1. return array(
  2. 'app_begin'=>array('Home\Behavior\Test'), // 在app_begin 标签位添加Test行为
  3. 'app_end'=>array('Home\Behavior\Test'), // 在app_end 标签位添加Test行为
  4. );
单独执行

行为的调用不一定要放到标签才能调用,如果需要的话,我们可以在控制器中或者其他地方直接调用行为。例如,我们可以把用户权限检测封装成一个行为类,例如:

  1. namespace Home\Behavior;
  2. use Think\Behavior;
  3. class AuthCheckBehavior extends Behavior {
  4. // 行为扩展的执行入口必须是run
  5. public function run(&$return){
  6. if(C('USER_AUTH_ON')) {
  7. // 进行权限认证逻辑 如果认证通过 $return = true;
  8. // 否则用halt输出错误信息
  9. }
  10. }
  11. }

定义了AuthCheck行为后,我们可以在控制器的_initialize方法中直接用下面的方式调用:

  1. B('Home\Behavior\AuthCheck');

thinkphp cbd模式的更多相关文章

  1. ThinkPHP调试模式与日志记录

    1.可以在config.php中进行设置,默认为关闭状态. 'APP_DEBUG'   =>  true 打开\ThinkPHP\Common\debug.php文件可以查看debug的默认设置 ...

  2. ThinkPHP URL模式和URL重写

    现在用的版本是TP3.1.3,这两天总是遇到NotFound的错误,解析路径错误,所以认真研究了一下手册,发现问题出在URL模式上面. URL模式 一般是使用U方法来生成路径,U方法的定义规则如下(方 ...

  3. thinkphp URL 模式

    兼容ThinkPHP三种url模式的nginx rewrite location / { root /var/www; index index.html index.htm index.php; if ...

  4. centos7 nginx完整支持thinkphp pathinfo模式开启方法

    thinkphp运行在linux+nginx,如何开启pathinfo模式,我是完整测试过了,没问题的,在thinkphp配置文件 开启    'URL_MODEL'   =>  1,   1代 ...

  5. thinkphp 应用模式

    应用模式提供了对核心框架进行改造的机会,可以让你的应用适应更多的环境和不同的要求. 每个应用模式有自己的模式定义文件,用于配置当前模式需要加载的核心文件和配置文件,以及别名定义.行为扩展定义等等.根据 ...

  6. thinkphp 调试模式

    ThinkPHP有专门为开发过程而设置的调试模式,开启调试模式后,会牺牲一定的执行效率,但带来的方便和除错功能非常值得. 直线电机哪家好直线电机生产厂家 我们强烈建议ThinkPHP开发人员在开发阶段 ...

  7. thinkphp url模式

    入口文件是应用的单一入口,对应用的所有请求都定向到应用入口文件,系统会从URL参数中解析当前请求的模块.控制器和操作: http://serverName/index.php/模块/控制器/操作 这是 ...

  8. 修改thinkphp路由模式,去掉Home

    第一步:入口文件增加 define('BIND_MODULE', 'Home'); 第二步:修改config文件,我这里路由模式设置为2 效果展示:

  9. nginx+thinkphp pathinfo模式配置

    server { listen 81; server_name http://lanxing.cc gohosts.com; root "D:\WWW\lanxing\public" ...

随机推荐

  1. c# mvc 简洁大气官网

    后台管理 https://g.alicdn.com/idleFish-F2e/app-basic/item.html?itemid=580281597427&ut_sk=1.WCB2zfWM% ...

  2. mongo之$group+$addToSet

    直接举例说明 #ArrangingResult表结构 { "_id" : ObjectId("5acc739df78bf21f8c94f080"), " ...

  3. axios的介绍及使用

    特点:支持promise API . 拦截请求和响应.转换请求数据和响应数据.取消请求.自动转换JSON数据.客户端支持防御XSRF等: axios请求方法(需后端定义):get获取数据. post提 ...

  4. (Struts2学习系列三)Struts2动态方法调用:通配符方式

    更改src/struts2.xml的代码: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  5. Linux网络编程 了解

    IPV4 -- IP地址分类:主机号是区分主机的,网络号是区分网段的 子网掩码是对主机号进行划分子网用的 举例说明: 对 192.168.1.0网段划分4个 其子网掩码 : 拿出主机号的两个位进行划分 ...

  6. vue组件的调用方式

    vue中一般都会把公共内容作为一个组件去布局,但是如何引用自定义的组件呢?下面就是vue调用自定义组件的方式,主要代码如下: <template> <div> <span ...

  7. delphi xe10 网络文件传送

    //网络传送文件(类似Server/Client) TTetheringManager|设备管理.TTetheringAppProfile|文件发送 待补充

  8. 经典单调栈最大子矩形——牛客多校第二场H

    题目是求次大子矩形,那么在求最大子矩形的时候维护M1,M2即可 转移M2时比较的过程要注意一下 #include<bits/stdc++.h> using namespace std; # ...

  9. Android Canvas save和restoreToCount

    @Override public void draw(Canvas canvas) { if (mDrawable!=null) { int sc=canvas.save(); if (mAnimat ...

  10. Nt函数原型

    NTSTATUS NTAPI NtAcceptConnectPort( OUT PHANDLE PortHandle, IN PVOID PortIdentifier, IN PPORT_MESSAG ...