# 行为架构 * * * * * ### 行为介绍 行为(Behavior)是ThinkPHP扩展机制中比较关键的一项扩展,行为既可以独立调用,也可以绑定到某个标签中进行侦听,在官方提出的CBD模式中行为也占了主要的地位,可见行为在ThinkPHP框架中意义非凡。 这里指的行为是一个比较抽象的概念,你可以把行为想象成在应用执行过程中的一个动作或者处理。在框架的执行流程中,例如路由检测是一个行为,静态缓存是一个行为,用户权限检测也是行为,大到业务逻辑,小到浏览器检测、多语言检测等等都可以当做是一个行为,甚至说你希望给你的网站用户的第一次访问弹出Hello,world!这些都可以看成是一种行为,行为的存在让你无需改动框架和应用,而在外围通过扩展或者配置来改变或者增加一些功能。 而不同的行为之间也具有位置共同性,比如,有些行为的作用位置都是在应用执行前,有些行为都是在模板输出之后,我们把这些行为发生作用的位置称之为标签(位),当应用程序运行到这个标签的时候,就会被拦截下来,统一执行相关的行为,类似于AOP编程中的“切面”的概念,给某一个切面绑定相关行为就成了一种类AOP编程的思想。 这些是TP5官方文档中描述的概念,下面来看看OneBase中有哪些行为。 * * * * * ### OneBase中的行为 打开系统app目录下的tags.php,可以看到系统的行为定义。 ~~~ <?php // +---------------------------------------------------------------------+ // | OneBase | [ WE CAN DO IT JUST THINK ] | // +---------------------------------------------------------------------+ // | Licensed | http://www.apache.org/licenses/LICENSE-2.0 ) | // +---------------------------------------------------------------------+ // | Author | Bigotry <3162875@qq.com> | // +---------------------------------------------------------------------+ // | Repository | https://gitee.com/Bigotry/OneBase | // +---------------------------------------------------------------------+ // 行为目录路径 define('BEHAVIOR_PATH', 'app\\common\\behavior\\'); $data = [ // 应用初始化 'app_init' => [], // 应用开始 'app_begin' => [], // 模块初始化 'module_init' => [], // 操作开始执行 'action_begin' => [], // 视图内容过滤 'view_filter' => [], // 日志写入 'log_write' => [], // 应用结束 'app_end' => [], ]; // 若不为安装流程则初始化系统行为 if(BIND_MODULE != 'install') : $data['app_init'] = [BEHAVIOR_PATH . 'InitBase', BEHAVIOR_PATH . 'InitHook']; $data['app_begin'] = [BEHAVIOR_PATH . 'AppBegin']; $data['app_end'] = [BEHAVIOR_PATH . 'AppEnd']; endif; return $data; ~~~ 可以看到咱们OneBase使用了 3个行为标签位,分别是app_init,app_begin,app_end。 初始化的标签位执行了2个行为,OneBase中默认共4个行为。 下面来逐一讲解行为的作用 **初始化基础信息行为** ~~~ <?php // +---------------------------------------------------------------------+ // | OneBase | [ WE CAN DO IT JUST THINK ] | // +---------------------------------------------------------------------+ // | Licensed | http://www.apache.org/licenses/LICENSE-2.0 ) | // +---------------------------------------------------------------------+ // | Author | Bigotry <3162875@qq.com> | // +---------------------------------------------------------------------+ // | Repository | https://gitee.com/Bigotry/OneBase | // +---------------------------------------------------------------------+ namespace app\common\behavior; use think\Loader; /** * 初始化基础信息行为 */ class InitBase { /** * 初始化行为入口 */ public function run() { // 初始化常量 $this->initConst(); // 初始化配置 $this->initConfig(); // 注册命名空间 $this->registerNamespace(); } /** * 初始化常量 */ private function initConst() { // 初始化分层名称常量 $this->initLayerConst(); // 初始化结果常量 $this->initResultConst(); // 初始化数据状态常量 $this->initDataStatusConst(); // 初始化时间常量 $this->initTimeConst(); // 初始化系统常量 $this->initSystemConst(); // 初始化路径常量 $this->initPathConst(); // 初始化API常量 $this->initApiConst(); } /** * 初始化分层名称常量 */ private function initLayerConst() { define('LAYER_LOGIC_NAME' , 'logic'); define('LAYER_MODEL_NAME' , 'model'); define('LAYER_SERVICE_NAME' , 'service'); define('LAYER_CONTROLLER_NAME' , 'controller'); define('LAYER_VALIDATE_NAME' , 'validate'); define('LAYER_VIEW_NAME' , 'view'); } /** * 初始化结果标识常量 */ private function initResultConst() { define('RESULT_SUCCESS' , 'success'); define('RESULT_ERROR' , 'error'); define('RESULT_REDIRECT' , 'redirect'); define('RESULT_MESSAGE' , 'message'); define('RESULT_URL' , 'url'); define('RESULT_DATA' , 'data'); } /** * 初始化数据状态常量 */ private function initDataStatusConst() { define('DATA_STATUS_NAME' , 'status'); define('DATA_NORMAL' , 1); define('DATA_DISABLE' , 0); define('DATA_DELETE' , -1); define('DATA_SUCCESS' , 1); define('DATA_ERROR' , 0); } /** * 初始化API常量 */ private function initApiConst() { define('API_CODE_NAME' , 'code'); define('API_MSG_NAME' , 'msg'); } /** * 初始化时间常量 */ private function initTimeConst() { define('TIME_CT_NAME' , 'create_time'); define('TIME_UT_NAME' , 'update_time'); define('TIME_NOW' , time()); } /** * 初始化路径常量 */ private function initPathConst() { define('PATH_ADDON' , ROOT_PATH . SYS_ADDON_DIR_NAME . DS); define('PATH_PUBLIC' , ROOT_PATH . 'public' . DS); define('PATH_UPLOAD' , PATH_PUBLIC . 'upload' . DS); define('PATH_PICTURE' , PATH_UPLOAD . 'picture' . DS); define('PATH_FILE' , PATH_UPLOAD . 'file' . DS); define('PATH_SERVICE' , ROOT_PATH . DS . SYS_APP_NAMESPACE . DS . SYS_COMMON_DIR_NAME . DS . LAYER_SERVICE_NAME . DS); define('PATH_COMMON_LOGIC' , SYS_APP_NAMESPACE . SYS_DS_CONS . SYS_COMMON_DIR_NAME . SYS_DS_CONS . LAYER_LOGIC_NAME . SYS_DS_CONS); } /** * 初始化系统常量 */ private function initSystemConst() { define('SYS_APP_NAMESPACE' , config('app_namespace')); define('SYS_HOOK_DIR_NAME' , 'hook'); define('SYS_ADDON_DIR_NAME' , 'addon'); define('SYS_DRIVER_DIR_NAME' , 'driver'); define('SYS_COMMON_DIR_NAME' , 'common'); define('SYS_STATIC_DIR_NAME' , 'static'); define('SYS_VERSION' , '1.0.0'); define('SYS_ADMINISTRATOR_ID' , 1); define('SYS_DS_PROS' , '/'); define('SYS_DS_CONS' , '\\'); $database_config = config('database'); define('SYS_DB_PREFIX' , $database_config['prefix']); define('SYS_ENCRYPT_KEY' , $database_config['sys_data_key']); } /** * 初始化配置信息 */ private function initConfig() { $model = model(SYS_COMMON_DIR_NAME . SYS_DS_PROS . 'Config'); $config_list = $model->all(); foreach ($config_list as $info) : $config_array[$info['name']] = $info['value']; endforeach; config($config_array); $this->initTmconfig(); } /** * 初始化动态配置信息 */ private function initTmconfig() { $list_rows = config('list_rows'); $api_key = config('api_key'); $jwt_key = config('jwt_key'); define('DB_LIST_ROWS' , empty($list_rows) ? 10 : $list_rows); define('API_KEY' , empty($api_key) ? 'OneBase' : $api_key); define('JWT_KEY' , empty($jwt_key) ? 'OneBase' : $jwt_key); } /** * 注册命名空间 */ private function registerNamespace() { // 注册插件根命名空间 Loader::addNamespace(SYS_ADDON_DIR_NAME, PATH_ADDON); } } ~~~ 可以看到基本上都是一些常量的定义,就是初始化系统的常量。 另外初始化了系统的配置信息,此处的配置信息是入库的。 最后是注册命名空间。 初始化基础信息行为中基本上就做了这三件事情。 **初始化钩子信息行为** ~~~ <?php // +---------------------------------------------------------------------+ // | OneBase | [ WE CAN DO IT JUST THINK ] | // +---------------------------------------------------------------------+ // | Licensed | http://www.apache.org/licenses/LICENSE-2.0 ) | // +---------------------------------------------------------------------+ // | Author | Bigotry <3162875@qq.com> | // +---------------------------------------------------------------------+ // | Repository | https://gitee.com/Bigotry/OneBase | // +---------------------------------------------------------------------+ namespace app\common\behavior; use think\Hook; /** * 初始化钩子信息行为 */ class InitHook { /** * 行为入口 */ public function run() { $hook = model(SYS_COMMON_DIR_NAME . SYS_DS_PROS . ucwords(SYS_HOOK_DIR_NAME)); $list = $hook->column('id,name,addon_list'); foreach ($list as $v) : $addon_list[$v['name']] = get_addon_class($v['addon_list']); endforeach; Hook::import($addon_list); } } ~~~ 此行为就是将数据库中的钩子查询出来与插件关联,并导入到系统中对系统提供面向切面的扩展方式。 **应用开始与结束行为** ~~~ <?php // +---------------------------------------------------------------------+ // | OneBase | [ WE CAN DO IT JUST THINK ] | // +---------------------------------------------------------------------+ // | Licensed | http://www.apache.org/licenses/LICENSE-2.0 ) | // +---------------------------------------------------------------------+ // | Author | Bigotry <3162875@qq.com> | // +---------------------------------------------------------------------+ // | Repository | https://gitee.com/Bigotry/OneBase | // +---------------------------------------------------------------------+ namespace app\common\behavior; /** * 应用开始行为 */ class AppBegin { /** * 行为入口 */ public function run() { debug('app_begin'); } } ~~~ ~~~ <?php // +---------------------------------------------------------------------+ // | OneBase | [ WE CAN DO IT JUST THINK ] | // +---------------------------------------------------------------------+ // | Licensed | http://www.apache.org/licenses/LICENSE-2.0 ) | // +---------------------------------------------------------------------+ // | Author | Bigotry <3162875@qq.com> | // +---------------------------------------------------------------------+ // | Repository | https://gitee.com/Bigotry/OneBase | // +---------------------------------------------------------------------+ namespace app\common\behavior; /** * 应用结束行为 */ class AppEnd { /** * 行为入口 */ public function run() { debug('app_end'); write_exe_log('app_begin', 'app_end'); } } ~~~ 可以看到在开始行为里面就是debug('app_begin');这个函数的调用,这个函数是TP提供用于调试的函数,用于记录执行时间与内存消耗等。 在结束行为中执行了 debug('app_end'); 用于标记结束的位置。 系统结束行为中会执行 write_exe_log 函数,这个函数是OneBase中封装的,用于记录系统的执行记录,若数据库配置 is_write_exe_log 为启用则会对每次系统操作进行执行记录写入,若为禁用则函数会返回false,跳过后续的记录逻辑。 默认是关闭记录,考虑到有些用户对OneBase不熟悉 导致记录过大 影响系统执行效率。