ThinkPHP3.2学习——架构_CBD模式

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



一、Core(核心)

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

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

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



二、Driver(驱动)  

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

ThinkPHP/Library/Think/Cache/Driver // 缓存驱动类库
ThinkPHP/Library/Think/Db/Driver // 数据库驱动类库
ThinkPHP/Library/Think/Log/Driver // 日志记录驱动类库
ThinkPHP/Library/Think/Session/Driver // Session驱动类库
ThinkPHP/Library/Think/Storage/Driver // 存储驱动类库
ThinkPHP/Library/Think/Template/Driver // 第三方模板引擎驱动类库
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 应用结束标签位

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

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

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

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

tag(‘my_tag‘,$params); // 添加my_tag 标签侦听

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

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 行为类的定义方式如下:

namespace Home\Behavior;
use Think\Behavior;
class TestBehavior extends Behavior {
     // 行为扩展的执行入口必须是run
     public function run(&$params){
         if(C(‘TEST_PARAM‘)) {
             echo ‘RUNTEST BEHAVIOR ‘.$params;
         }
     }
}

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

namespace Home\Behavior;
class TestBehavior {
     // 行为扩展的执行入口必须是run
     public function run(&$params){
         if(C(‘TEST_PARAM‘)) {
             echo ‘RUNTEST BEHAVIOR ‘.$params;
         }
     }
}

行为类必须定义执行入口方法run,由于行为的调用机制影响,run方法不需要任何返回值,所有返回都通过引用返回。run方法的参数只允许一个,但可以传入数组。

行为绑定

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

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

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

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

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

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

return array(
  ‘app_init‘=>array(
    ‘Home\Behavior\CheckLang‘,
    ‘Home\Behavior\CronRun‘
   ),
);

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

‘app_begin‘  =>  array(
    ‘Behavior\ReadHtmlCache‘, // 读取静态缓存
),

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

‘app_begin‘  =>  array(
    ‘Home\Behavior\CheckModule‘,
    ‘Home\Behavior\CheckLang‘,
),

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

Library\Behavior\ReadHtmlCache
Home\Behavior\CheckModule
Home\Behavior\CheckLang

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

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

‘app_begin‘  =>  array(
    ‘Home\Behavior\CheckModule‘,
    ‘Home\Behavior\CheckLang‘,
    ‘_overlay‘    =>    true,
),

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

Home\Behavior\CheckModule
Home\Behavior\CheckLang

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

return array(
     ‘app_begin‘=>array(‘Home\Behavior\Test‘), // 在app_begin 标签位添加Test行为
     ‘app_end‘=>array(‘Home\Behavior\Test‘), // 在app_end 标签位添加Test行为
 );
单独执行

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

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

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

B(‘Home\Behavior\AuthCheck‘);
时间: 2024-10-13 15:11:23

ThinkPHP3.2学习——架构_CBD模式的相关文章

Thinkphp3.2学习——架构_命名空间

3.2版本全面采用命名空间方式定义和加载类库文件,有效的解决多个模块之间的冲突问题,并且实现了更加高效的类库自动加载机制. 命名空间的概念必须了解,否则会成为3.2版本开发的重大障碍.如果不清楚什么是命名空间,可以参考PHP手册:PHP命名空间 由于新版完全采用了命名空间的特性,因此只需要给类库正确定义所在的命名空间,而命名空间的路径与类库文件的目录一致,那么就可以实现类的自动加载. 例如,Org\Util\File类的定义为: namespace Org\Util; class File {

用VS2010创建三层架构开发模式及三层架构的研究

三层架构的研究 三层体系结构的概念 用户界面表示层(USL) 业务逻辑层(BLL) 数据访问层(DAL) BLL将USL与DAL隔开了,并且加入了业务规则 各层的作用 1:数据数据访问层:主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务. 2:业务逻辑层:主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建. 3:表

设计模式学习之外观模式(Facade,结构型模式)(8)

1.什么是外观模式为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用 2.为什么要使用外观模式在软件开发系统中,客户程序经常会与复杂系统的内部子系统之间产生耦合,从而导致客户程序随着子系统的变化而变化,那么如何简化客户程序与子系统之间的交互接口?如何将复杂系统的内部子系统与客户程序之间的依赖解耦? 现在来考虑这样一个抵押系统,当有一个客户来时,有如下几件事情需要确认:到银行子系统查询他是否有足够多的存款,到信用子系统查询他是否有良好的信

Hive基础之Hive体系架构&运行模式&Hive与关系型数据的区别

Hive架构 1)用户接口: CLI(hive shell):命令行工具:启动方式:hive 或者 hive --service cli ThriftServer:通过Thrift对外提供服务,默认端口是10000:启动方式:hive --service hiveserver WEBUI(浏览器访问hive):通过浏览器访问hive,默认端口是9999:启动方式:hive --service hwi 2)元数据存储(Metastore):启动方式:hive -service metastore

LVS学习笔记--DR模式部署

一.部署环境: 服务器版本:CentOS6.5(Finnal) 网络拓扑: 二.需求分析:调度服务器与网页服务器均在同一网段局域网环境,用户提交的请求会经过调度器的分配指定到网页服务器,同时保证服务高可用性(任意一台网站服务器宕机后调度器会剔除它直至服务器恢复至正常:主调度器宕机后从调度器会接管它直至其恢复正常.). 三.相关配置: 部署调度器LVS服务脚本: #!/bin/sh mkdir tools cd tools/ # yum install lrzsz # rz # ls wget h

设计模式学习之-状态模式

一.状态模式状态模式,当一个对象的内在状态发生改变时允许改变其行为行为,这个对象像是改变了其子类.状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同的状态的一系列类当中,可以把复杂的判断逻辑简化.当然,如果这个状态判断比较简单,那就没有必要用“状态模式”了.这段话有点难以理解,简而言之就是,在一类中根据当前状态去实例化下一状态子类.下面是状态模式结构图. State类,是一个抽象状态类,定义一个接口以封装与Context的特定状态相关的行为.

《Head First 设计模式》学习笔记——模板方法模式

模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模板方法模式的用意. 设计模式 模板方法模式:在一个方法中定义一个算法的框架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结果的情况下,重新定义算法中的某些步骤. 模板就是一个方法,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现.这样可以确

设计模式学习笔记--外观模式

好久没写设计模式的blog了,这次重新回来填坑,先找一个最简单但是却最常用的设计模式来学习,外观模式.其实说是一个设计模式,其实我们在实际的编程中无时无刻不在用外观模式,可以说这个设计模式已经渗透到编程的各个方便,可能我们自己没感觉出来罢了. 一.外观模式的定义 先来看一下外观模式的定义: 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一系列子系统更加容易使用. 简单解释一下,所谓外观模式,就是在我们设计系统的时候,将若干个子系统的功

数据库学习设计模式--组合模式

介绍: 想必你已经了解了数据结构中的树,ok,组合模式对于你就是一会儿的功夫了.组合模式相对来说比较简单.看一下定义 abstract class Component { protected String name; //这个用来标示一下节点 public Component(String name) { this.name = name; } public abstract void add(Component c);//增加儿子节点 public abstract void remove(C