onethink钩子 视图和视图控制器的生命周期类型有什么区别

OneThink 1.0.131129开发版 - ThinkPHP框架
OneThink V1.0.131129 开发版发布
本次是正式版发布之前的最后一个开发版本,由于文档的开发和书写进度耽搁,原定的发布计划将推迟到12月初。
在正式版发布之前,BUG反馈和建议请到
文档工作我们正在紧张整理中,再次感谢大家对OT的关注和支持,你们的努力让OT走的更远!
注意事项:
1、再次提醒,OneThink安装要求PHP5.3+版本,否则会出错
2、目前开发版不支持升级功能,所以请备份好之前的数据和文件后重新安装。
3、目前不支持BAE,SAE的支持会在正式版发布的时候增加。(貌似BAE3.0支持文件写入,OT可以直接支持,有兴趣的童鞋可以测试下!!)
4、正式版发布之后,将开放GIT地址,转为社区模式维护更新^_^。
更新日志:
[ 1.0.131129开发版 ]
* 修复 状态修改(AdminController::changeStatus())批量操作bug
* 修复 文档编辑页上传附件与自动生成的模板冲突问题
* 修复 文档编辑页 '推荐位'项的保存和显示bug
* 修复 后台'附件'插件的文件列表中文件大小显示错误的bug
* 改进 上传模型改进,防止产生垃圾数据
* 改进 文档编辑页表单排序完善
* 改进 优化了一些公共函数
* 改进 parse_field_attr函数 字段的枚举值定义支持函数,采用:fun(var1,var2...)
+ 新增 前台documentDetailAfter 钩子传入文章的信息数组。
+ 新增 核心框架的标签库定义升级
+ 新增 插件系统提供一个__ADDONROOT__模板常量,以方便获取插件的资源文件目录。
[ 1.0.131115开发版 ]
+新增 新增菜单中新增 顶级菜单的选项,方便用户编辑时将才能单切换到顶级下。
+新增 增加Think标签库
+新增 模型列表定义支持链接,增加系统特殊变量支持
+新增 增加应用列表搜索
* 更新 文档列表和表单支持自定义(在模型管理中定义即可)
* 更新 配置参数支持不分组 0 为不分组 需要修改原来的配置分组列表配置
* 更新 更新框架核心到最新开发版,修正日志文件写到根目录的问题
- 修复 修复分页导航不高亮的问题
- 修复 修正应用列表的分页显示 列表增加批量删除功能
- 修复 修正数据库文件中的兼容问题
- 修复 修正Home模块的DocumentModel的position方法参数错误
- 修复 修正应用列表和meta_title
- 修复 修正模型表单的显示问题
[ 1.0.131108开发版 ]
+ 新增 添加的更多的模型属性支持
+ 新增 系统模型导入到数据库
+ 新增 模型表单自动生成支持更多类型
+ 优化 优化了日志显示
+ 修复 访问授权不能保存的BUG
+ 修复 修复了一些已知的BUG
[ 1.0.131101开发版 ]
+ 新增 新增开发者模式(可以在配置后台配置文件开启)
+ 新增 不同的分类设定自己特有的行为规则
+ 新增 行为日志记录
+ 新增 系统日志记录
+ 新增 新增Api层,通过 api 函数调用(目前内置 api 为空,以后版本陆续添加系统内置API)
+ 新增 模型表单生成和列表生成支持文档模型
# 变更 取消模型继承,模型分为文档模型和独立模型。
目前建立文档模型还需要对应简历Logic类,下周完善后会不用创建
# 变更 后台菜单管理调整到数据库管理
# 变更 后台菜单管支持设置是否开发者模式可见
[ 1.0.131025开发版 ]
+ 独立模型的创建,字段的创建,支持通过已有数据表导入模型
+ 独立模型字段排序
+ 数据列表的定制,可自由定制显示列
+ 新增和编辑表单的自动生成 (目前支持的类型有限,下周继续完善)
+ 权限管理添加按模型授权支持
[ 1.0.131018开发版 ]+&新增&数据库备份支持压缩功能
+&新增&数据库压缩功能可以配置是否开启,并可以设置压缩级别
+&新增&数据库还原功能
+&新增&插件入口文件$info属性增加url字段,用于配置插件官网url,&没配置则链接到插件上传者onethink官网用户中心(目前连接到onethink官网首页)
+&新增&基础文档表新增root字段,便于子文档的搜索及其他操作
+&新增&分类的移动和合并操作
+&新增&后台添加新用户功能
+&新增&后台用户搜索功能
+&新增&Upload上传增加SAE驱动
*&&完善&文档的标识只在同一根节点下不重复
-&修复&批量导入没有进行自动验证和自动完成
-&修复&文档外链获取链接错误BUG
#&变更&编辑器插件markdown编辑变更为&thinkeditor(新版)[ 1.0.131011开发版 ]+&新增&导航管理支持层级
+&新增&数据备份
+&新增&&内容&增加&目录文档&导入功能
+&改进&&系统/配置管理&列表支持分页和搜索
+&改进&文档标识只需在同一根节点下不重复
+&改进&富文本编辑器可以设置高度
+&修复&“内容”&左侧菜单不显示二级以上分类
+&修复&如果后台回收站没有数据时,点击清空,会把所有文章数据都清空
+&修复&草稿不能发布的问题[ 1.0.130929开发版 ]+&增加&文档模型表单字段自定义排序功能
+&增加&新版本后台提醒功能
*&修复&模板中多处URL链接错误
*&修复&文件上传类型验证bug
*&修复&被删除文档有子文档时无法删除所属分类的问题
*&修复&个别MYSQL版本安装时数据表创建失败的问题
*&改进&安装程序用户体验
*&改进&默认的数据库连接地址改为127.0.0.1&避免PHP5.3+版本连接mysql过慢的问题
*&改进&安装时保留默认用户组
*&改进&验证码性能
*&改进&简化文档类型,去除专辑类型和改进文档类型的逻辑
*&改进&分类增加默认创建的文章是否需要审核
*&改进&插件和钩子机制&支持直接使用框架内置的标签位作为钩子
&&&&-&hooks函数改为Addons类改为&A&插件类名由Addons更改为Addon
*&改进&文档列表更加灵活,更容易根据文档类型输出对应类型的文档列表.
&&&&-&通过在ArticleController增加自己的列表方法,并注册到index方法中可以根据文档类型输出对应模板,参见回复列表的实现.
*&改进&大量代码规范化调整,性能优化,缓存优化
*&其他许多细微调整改进不再一一列出
积分:8810
ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。视图类view主要用于页面内容的输出,模板调用等,用在控制器类中,可以使得控制器类把表现和数据结合起来。下面我们来看一下执行流程。
首先,在控制器类中保持着一个view类的对象实例,只要继承自控制器父类的类都可以使用这个实例,所以我们在控制器子类中就可以使用view类实例去很容易的调用模板,输出内容。
看Controller.class.php类的第22行和35行,分别声明了一个实例变量,在构造函数中实例化一个view实例。
namespace T
* ThinkPHP 控制器基类 抽象类
abstract class Controller {
* 视图实例对象
* @var view
* @access protected
* 控制器参数
* @var config
* @access protected
protected $config = array();
* 架构函数 取得模板对象实例
* @access public
public function __construct() {
Hook::listen('action_begin',$this-&config);
//实例化视图类
//控制器初始化
if(method_exists($this,'_initialize'))
$this-&_initialize();
123456789101112131415161718192021222324252627282930
namespace Think;/*** ThinkPHP 控制器基类 抽象类*/abstract class Controller {&/*** 视图实例对象* @var view* @access protected&/*** 控制器参数* @var config* @access protected*/protected $config = array();&/*** 架构函数 取得模板对象实例* @access public*/public function __construct() {Hook::listen('action_begin',$this-&config);//实例化视图类&//控制器初始化if(method_exists($this,'_initialize'))$this-&_initialize();}
我们在控制器类中输出模板和内容主要调用控制器类中的display方法,但是我们查看此方法就会发现,此方法里面调用的还是view类的display方法,display的主要实现逻辑还在view类中。在view类的大概67行左后,我们就可以看到这个函数的实现过程,下面来分析一个display方法。
* 加载模板和页面输出 可以返回输出内容
* @access public
* @param string $templateFile 模板文件名
* @param string $charset 模板输出字符集
* @param string $contentType 输出类型
* @param string $content 模板输出内容
* @param string $prefix 模板缓存前缀
* @return mixed
public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
G('viewStartTime');
// 视图开始标签
Hook::listen('view_begin',$templateFile);
// 解析并获取模板内容
$content = $this-&fetch($templateFile,$content,$prefix);
// 输出模板内容
$this-&render($content,$charset,$contentType);
// 视图结束标签
Hook::listen('view_end');
123456789101112131415161718192021
/*** 加载模板和页面输出 可以返回输出内容* @access public* @param string $templateFile 模板文件名* @param string $charset 模板输出字符集* @param string $contentType 输出类型* @param string $content 模板输出内容* @param string $prefix 模板缓存前缀* @return mixed*/public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {G('viewStartTime');// 视图开始标签Hook::listen('view_begin',$templateFile);// 解析并获取模板内容$content = $this-&fetch($templateFile,$content,$prefix);// 输出模板内容$this-&render($content,$charset,$contentType);// 视图结束标签Hook::listen('view_end');}
我们可以看到在display方法中也是分别调用多个函数来协作完成模板处理工作的。
我们来整理分析一下流程。
dispaly方法接受一个templateFile参数,调用parseTemplate方法根据这个参数去侦测模板文件的位置,结合主题组合出一个模板的地址,执行view_parse标签行为,在行为类里面去调用模板引擎的fetch方法去解析模板,返回编译后的内容。
所以我们知道,对于视图类来说,大概分为以下几步,第一是根据参数去侦测出模板文件的地址,然后调用模板引擎去编译模板文件,形成编译缓存php文件,然后执行php文件返回内容。
下面我们来分析一下tp是怎样根据用户传进来的参数来侦测模板文件的地址的。核心代码逻辑在view类的140行左右。
* 自动定位模板文件
* @access protected
* @param string $template 模板文件规则
* @return string
public function parseTemplate($template='') {
//如果$template是一个文件地址的话,那么就直接返回该地址。这是最简单的一种使用方式。
//这里的文件地址是一个相对文件路径地址,要注意模板文件位置是相对于项目的入口文件
if(is_file($template)) {
//获取模板文件的分隔符,模板文件CONTROLLER_NAME与ACTION_NAME之间的分割符
$depr = C('TMPL_FILE_DEPR');
//将冒号替换成分隔符
$template = str_replace(':', $depr, $template);
// 获取当前主题名称
$theme = $this-&getTemplateTheme();
我们来看一下tp的模板侦测逻辑。
首先tp要求我们传入一个地址表达式。格式如下:
[模块@][控制器:][操作]
表示m模块下的c控制器下的a方法
我们只要给此方法传入模块,控制器和方法三个参数,这个方法就能给我们侦测出对应的模板文件地址。
具体来说,他会先定义出截止到模块这个阶段的目录,然后在得到控制器到最后的模板文件地址,最后组合起来形成最终的文件地址。
1:先定义模块的目录
首先解析地址表达式,如果有@,表示传入了模块地址,解析她,赋值给module变量。
我们的控制器文件夹和方法存放在哪里呢?
如果定义了视图目录,就存放在视图目录中,如果没有定义,就看看是否定义了模板路径,如果定义了就存放在该路径下的对应模块目录下,如果没有定义模板路径,默认就存放在应用文件夹下的对应模块文件夹下的默认视图层下。
最后我们会得到一个THEME_PATH表示控制器模板存放的目录。如果有主题的话加上主题
// 获取当前模块
$module = MODULE_NAME;
if(strpos($template,'@')){ // 跨模块调用模版文件
list($module,$template) = explode('@',$template);
// 获取当前主题的模版路径
if(!defined('THEME_PATH')){
if(C('VIEW_PATH')){ // 模块设置独立的视图目录
$tmplPath = C('VIEW_PATH');
}else{ // 定义TMPL_PATH 改变全局的视图目录到模块之外
$tmplPath = defined('TMPL_PATH')? TMPL_PATH.$module.'/' : APP_PATH.$module.'/'.C('DEFAULT_V_LAYER').'/';
define('THEME_PATH', $tmplPath.$theme);
// 分析模板文件规则
然后分析地址表达式中的模板规则,如果地址表达式为空,或者只是传了一个模块名,那么这里的template就为空,那么默认的地址就是默认控制器下的默认方法
if('' == $template) {
// 如果模板文件名为空 按照默认规则定位
$template = CONTROLLER_NAME . $depr . ACTION_NAME;
}elseif(false === strpos($template, $depr)){
$template = CONTROLLER_NAME . $depr . $
//最后结合一下得到最后的模板文件地址
$file = THEME_PATH.$template.C('TMPL_TEMPLATE_SUFFIX');
if(C('TMPL_LOAD_DEFAULTTHEME') && THEME_NAME != C('DEFAULT_THEME') && !is_file($file)){
// 找不到当前主题模板的时候定位默认主题中的模板
$file = dirname(THEME_PATH).'/'.C('DEFAULT_THEME').'/'.$template.C('TMPL_TEMPLATE_SUFFIX');
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
/*** 自动定位模板文件* @access protected* @param string $template 模板文件规则* @return string*/public function parseTemplate($template='') {//如果$template是一个文件地址的话,那么就直接返回该地址。这是最简单的一种使用方式。//这里的文件地址是一个相对文件路径地址,要注意模板文件位置是相对于项目的入口文件if(is_file($template)) {return $template;}//获取模板文件的分隔符,模板文件CONTROLLER_NAME与ACTION_NAME之间的分割符$depr = C('TMPL_FILE_DEPR');//将冒号替换成分隔符$template = str_replace(':', $depr, $template);// 获取当前主题名称$theme = $this-&getTemplateTheme();/*我们来看一下tp的模板侦测逻辑。首先tp要求我们传入一个地址表达式。格式如下:[模块@][控制器:][操作]&&比如:&&m@c:a&&表示m模块下的c控制器下的a方法我们只要给此方法传入模块,控制器和方法三个参数,这个方法就能给我们侦测出对应的模板文件地址。具体来说,他会先定义出截止到模块这个阶段的目录,然后在得到控制器到最后的模板文件地址,最后组合起来形成最终的文件地址。1:先定义模块的目录首先解析地址表达式,如果有@,表示传入了模块地址,解析她,赋值给module变量。我们的控制器文件夹和方法存放在哪里呢?如果定义了视图目录,就存放在视图目录中,如果没有定义,就看看是否定义了模板路径,如果定义了就存放在该路径下的对应模块目录下,如果没有定义模板路径,默认就存放在应用文件夹下的对应模块文件夹下的默认视图层下。最后我们会得到一个THEME_PATH表示控制器模板存放的目录。如果有主题的话加上主题&&*/// 获取当前模块$module = MODULE_NAME;if(strpos($template,'@')){ // 跨模块调用模版文件list($module,$template) = explode('@',$template);}// 获取当前主题的模版路径if(!defined('THEME_PATH')){if(C('VIEW_PATH')){ // 模块设置独立的视图目录$tmplPath = C('VIEW_PATH');}else{ // 定义TMPL_PATH 改变全局的视图目录到模块之外$tmplPath = defined('TMPL_PATH')? TMPL_PATH.$module.'/' : APP_PATH.$module.'/'.C('DEFAULT_V_LAYER').'/';}define('THEME_PATH', $tmplPath.$theme);}&// 分析模板文件规则/*然后分析地址表达式中的模板规则,如果地址表达式为空,或者只是传了一个模块名,那么这里的template就为空,那么默认的地址就是默认控制器下的默认方法*/if('' == $template) {// 如果模板文件名为空 按照默认规则定位$template = CONTROLLER_NAME . $depr . ACTION_NAME;}elseif(false === strpos($template, $depr)){$template = CONTROLLER_NAME . $depr . $template;}//最后结合一下得到最后的模板文件地址$file = THEME_PATH.$template.C('TMPL_TEMPLATE_SUFFIX');if(C('TMPL_LOAD_DEFAULTTHEME') && THEME_NAME != C('DEFAULT_THEME') && !is_file($file)){// 找不到当前主题模板的时候定位默认主题中的模板$file = dirname(THEME_PATH).'/'.C('DEFAULT_THEME').'/'.$template.C('TMPL_TEMPLATE_SUFFIX');}return $file;}
到这里为止,我们已经根据用户传入的模板地址表达式得到了模板文件地址,接下来就是调用模板引擎来解析这个模板。在view类的fetch方法中并没有直接调用模板引擎template类的的方法去解析模板,而是去调用了一个view_parse标签,在这个标签上绑定了行为模式扩展类ParseTemplateBehavior,模板的解析就是在这个类的run方法中进行的,这个类总我们不仅而已使用tp自带的模板引擎,还可以使用其他开源第三方的模板引擎类,具有很好的高扩展性。关于模板引擎解析模板的裸机,请看源码分析8建议插件可以不需要添加钩子就能直接调用
&& 发表于: 22:34&&
每个插件都要加个钩子才能调用,感觉有点啰嗦了,大多数插件,只属于一个钩子,这样,感觉后台的钩子会很啰嗦。可以增加个类似hook的方法,直接调用插件
共 3 条关于 建议插件可以不需要添加钩子就能直接调用 的回复 &&
最后回复 02-26 05:56
于 02/07 22:31 说:
弄那么多钩子的确是毫无意义...
于 02/08 08:23 说:
回1楼:chuanpu
弄那么多钩子的确是毫无意义...
可以自己减少点钩子,或者弄清楚该用什么钩子来避免添加新钩子
于 02/26 05:56 说:
钩子还是有必要的。这样会更灵活一些。否则你的插件出现在什么位置怎么控制啊。
上海顶想信息科技有限公司版权所有
沪ICP备号-3 本站由onethink强力驱动

我要回帖

更多关于 onethink 内容类型 的文章

 

随机推荐