|
Project Information
Featured
Downloads
Links
|
TagFeather 手册 这是鬼才的创意,但不是专业的作品 TagFeather 所见所得的 模板引擎 序 开始 什么是TagFeather 安装 入门指引 扩展 更高级的扩展 钻研 TagFeather FAQ 出错信息表 TagFeather 是什么 TagFeather 是一个让美工不用去学任何程序代码,只需要借助流行工具就能所见所得的预览的 Web 开发模板引擎。简单的讲,页面设计人员只需要按照程序员指定的 CSS Class 和 ID 就什么都不用管了。对于程序员来说,TagFeather很容易掌握,而且开放的结构使得扩展极为方便。TagFeather 目前还只有PHP实现的版本,但将来会在各种语言上实现的。 TagFeather 有什么优点 和其他 PHP 模板 模板比较。TagFeather 比现有的所有模板都更美工欢迎。因为他们不需要学任何其它程序语言或者模板语言。他们用普通HTML工具预览所得到的结果就是最终输出结果的小样。相比使用内嵌代码的而其很多只见结构不见预览的模板比如 Smarty 来说这是一种质的飞跃,对于使用标记性标签,如 Struct,ASP.Net 来说 TagFeather 则不需要专用的编辑器来预览。相比另一个优秀的PHP模板引擎PHPTAL,TagFeahter 则是不必一定在模板html 文件中加入特殊属性。 TagFeather 的原理是用自定义的 SAX 引擎解析宽松 xml 格式的模板文件。编译成和 TagFeather 引擎无关的 PHP 代码。常见的模板引擎如 Smarty 则是通过解析编译字符串得到编译后代码的。TagFeather的各种功能都是用钩子函数来实现的。TagFeather 编译后的代码是原生,不需要额外支持就可以执行的 PHP代码。 TagFeather 为了更方便程序员和美工 所见所得 页面设计不再只见结构不见预览结果,不需要任何辅助工具。 完全的页面设计和程序逻辑分离 不需要在模板HTML文件中加入任何奇怪的东西。 不必学任何模板语言 页面设计人员不需要。程序员也只需了解一些特殊的属性怎么用,可以用 PHP 语言来检查配置。 容易入门 因为不需要学习模板语言,所以页面设计是几乎0学习成本,程序员学习的成本也低于 smarty 方便的格式重排 你可以实现现有模板都很难做到的功能:预览横排但不满足整除关系的表格。 如果设计得当,模板输出文件甚至可以作为输入模板使用。 运行速度快 TagFeather 编译后的代码是不需要 TagFeather 支持的。和某号称“It is extremely fast”,但实际上是效率最低下的某模板引擎比起来。TagFeather 编译后的文件就和你不用任何模板自己写的一样。 编译出来的文件可读 用某模板的人都不知道生成的代码是怎么样的,但 TagFeather 让你很清楚你做的是什么。 可以做辅助设计 即使你不相信 TagFeather 在运行时候的表现,你也可以用他编译出来的 PHP 文件。因为编译出来的文件很容易明白。方便 确实很灵活方便开始建模的时候可以把代码,配置和模板三个文件混合写在一起。后来可以把代码,配置写在一起。或者你也可以三者分离。 扩展性强 TagFeather 的功能都是由钩子函数实现的,写一个钩子函数是很容易的事情。 不需要配置 简单项目 通用 大部分模板都很容易转为TagFeather 模板 模板可以和代码混用。你可以在模板里自由书写代码,但是也可以设置为模板安全。 安全 有插件使得模板是安全的,就是只能 增强的XML解析器 TagFeather的模板文件是XML,但是TagFeather的解析器做了一些改进,你可以在属性和文本区域里混合使用宿主语言(当前是PHP)和普通文本。 TagFeather 的缺点 TagFeather 目前还没有经过大规模的应用考验。 TagFeather 的编译效率和文档复杂度有关,编译效率很低,简单的页面不到1秒,能每次运行时都可以实时编译。但复杂页面会导致运行超时。编译前后效率比可达1000:1以上。 TagFeather 支持 GB2312 编码,但理论上对 GBK编码会有问题。 TagFeather 的产品完成度还不够,作为一个程序合格,但是作为一个产品,还有很多不足。尽管我已经竭力以产品角度来对待 很多从非 TagFeather 的模板转移到 TagFeather 的麻烦在于: TagFeather 要求输入的必须是可以含标准服务端属性的 XML文件。 XHTML 的一些属性导致那些源模板不符合 XML。尽管TagFeather已经够宽松了。 编译型的模板的一个缺点:必须要可写的文件作为缓存。 TagFeather 的特点 TagFeather 的工作原理是用 SAX 方式 解析 xml 模板输出解析后数据,和一般通用 的 SAX Parser 解析器不同的是: TagFeather 的 SAX 解析器 TF_XmlParser 是支持带服务端标记 <? <% 的,而且不会替换 & 实体符号。而且 而且做了部分扩充 根据系统和用户添加的解析钩子,TagFeather 因此得到不同的输出。 TagFeather 的输入和输出都是可稍微扩展的 XML 文件 TagFeather 为什么没有缓存系统? 缓存系统不是模板系统考虑的事,TagFeather 推荐使用 Pear::CacheLite 配合生成实静态化。 钩子指引, TagFeather 根据 入门指引 示例在 demo 文件夹(TODO )。 TagFeather 的 多列预览, TagFeather 解析器的特性。 关于模板安全钩子的注册,注销 TagFeather 的工作原理是用 SAX 方式 解析 xml 模板输出解析后数据,和一般通用 的 SAX Parser 解析器不同的是: TagFeather 的 SAX 解析器 TF_XmlParser 是支持带服务端标记 <? <% 的,而且不会替换 & 实体符号。 命苦的程序员 不使用模板的时候: 美工切图,程序员写PHP代码和简单页面代码。程序员根据美工的页面嵌入 PHP代码。 使用Smarty 的时候: 美工切图,程序员写PHP代码和简单页面代码。程序员根据美工的页面嵌入Smarty 代码。 使用 TagFeather 模板的时候 美工切图,同时程序员编写PHP代码和简单页面代码。美工根据程序员的要求按 class.id 等指定内容得到静态小样。程序员看美工哪里漏了加了。 碰到页面调整的时候 美工:我不懂代码,你来调整页面吧。程序员:命苦,还好俺练就手写 html 的神功。 美工:我不懂代码,你来调整页面吧。程序员:命苦,还要学一种语言(smarty)。 美工: Class / ID 是什么?我通通不懂,算了,我就切出图来,剩下的你来做吧。程序员:命苦,我怎么跟连CSS 都不懂的美工啊。 经典 Hello World 。 很多例子里,写代码之前都要配置很多非代码方面的东西。就比如目录设置。 好吧,我们的目录结构如下吧: Tagfeather/ 这个就是我们下载解压的TagFeather 的文件夹了。 cache/ 建立这个文件夹,放缓存文件的,要可写 Hello.php 这个是我们要写的 hello world 文件。 现在美工还没到位,所以我们一手全包了。 <?php $str="Hello World";?> <html> <body><?=$hello world?></body> </html> 哦,以上是不用模板的。那么这么来吧。 <?php Require_once("tagfeather/tagfeather.inc.php"); $str="Hello"; TagFeather::TeamplateAndDie(FILE);?> <html> <body><?=$hello world?></body> </html> 多这两句没有用啊? //////////////////// TagFeather 使用入门 比如你有一个 php 文件 hello.php <?php $word="hello word" ?> <html> <?=$word?> </html> 你加上 <?php include_once ("tagfeather.inc.php"); TagFeather::TemplateAndDie(FILE); $word="hello word" ?> <html> <?=$word?> </html> 并确保 cache目录可写 他已经就是使用 TagFeather 模板的 PHP 了 看上去没什么区别。但是 TagFeather::TemplateAndDie(FILE); 这个函数已经打乱了页面的执行顺序 cache 目录下面有 hello.cache.php 内容为: <??><?php include_once ("tagfeather.inc.php"); TagFeather::GO(); $word="hello word" ?> <html> <?php echo $word?> </html> 什么都没发生,那么 多加这些代码有什么用呢? 实际上,TagFeather::TemplateAndDie()改变了 脚本剩余代码的流程。 当在正常文件中执行的时候 当不带任何参数的时候,会把当前的 Script_Filename 作为模板源文件,输出文件为 cache/【去除.php 的 Scriptfilename】.cache.php 如果没有模板文件或模板文件时间比源文件旧, 则会编译生成模板输出文件。 然后 extract($GLOBALS);使得 模板输出文件可以直接使用 $GLOBALS 变量 $GLOBALS['TF_IN_CACHE']=true 表示在缓存文件中 include (【模板输出文件】); exit; 而在 模板输出文件执行的时候 $GLOBALS['TF_IN_CACHE']==true 则不做任何操作。 简单的来说就是包含模板输出文件并跳出。 因为 php 没有 return return 的方法。 而 TagFeather::Template() 则温柔多了 新版本的 TagFeather 推荐这么使用 if(TagFeaether::Template())return; 那么编译过程是如何呢。 载入文件后, get_template() 调用 comment 钩子,判断是否要编译。 否则载入 源文件。 build() 输出 目标文件。 build 就是编译的过程. 编译过程就是解析 xml 树 类似 sax 方式解析 xml 树。 优点 TagFeather 的工作原理是用 SAX 方式 解析 xml 模板输出解析后数据,和一般通用 的 SAX Parser 解析器不同的是: TagFeather 的 SAX 解析器 TF_XmlParser 是支持带服务端标记 <? <% 的,而且不会替换 & 实体符号。 所有钩子类型 的说明 钩子类型表 钩子类型 调用方式 参数说明 说明 modifier bool $is_builded 是否需要编译 在编译文件的时候最先调用,编译数据$TagFeather->build()的时候不会被调用 prebuild 先进先出 string $data 要编译的数据 编译之前调用 postbuild string $data 要编译的数据 编译之后调用 pretag 先进先出 array $attrs 标签属性数组 解析到标签开始的时候调用 posttag array $attrs标签属性数组 解析到标签结束的时候调用 error array $error_array 错误信息数组 解析出错的时候调用 text string $text 解析的文本 解析到文本的时候调用 comment string $comment 解析的注释,含 <!-- --> 解析到注释的时候调用 doctype string $doctype 含 <!doctype > 里的全部内容 解析到 <!doctype 的时候调用 cdata string $cdata 含 <![cdata ]]>里的全部内容 解析到 <![cdata 的时候调用,注意: <script>标签内的也当成 cdata 处理 asp string $asp 含 <% %>里的全部内容 解析到 <% 标记的时候调用,标签属性中文本为此标记时候也会调用 pi string $pi 含<??>里的全部内容 解析到 <? 标记的时候调用, 标签属性中文本为此标记时候也会调用 钩子类型的说明: 解析钩子接口的调用形式都为 $callback( mixed $arg, TagFeather $tf, string $hooktype) 返回修改后的 $arg 。 钩子类型分先进先出和先进后出两种 $tf为传入的对象调用 $tf->hookmanager->stop_nexthook() , 可以中断下一个钩子,常用与 text ,comment 等互斥性钩子。注意 tagbegin, tagend, error 三个钩子请不要用此函数 注册钩子用 $TagFeather->reg_parsehook($type,$name,$callback,$overfollow=false) $overfollow 表示是否覆盖原来的钩子 ($TagFeather->insert_parsehook尚在试验中) 注销钩子用 $tf->unreg_parsehook($name,$type=false) 当 $type==false 的时候为注销全部类型的同名钩子 所有钩子类型 钩子族的说明: 解析钩子接口的调用形式都为 $callback( mixed $arg, TagFeather $tf, string $hooktype) 返回修改后的 $arg 。 钩子类型分先进先出和先进后出两种 $tf为传入的对象调用 $tf->stop_nexthook() , 可以中断下一个钩子,常用与 text ,comment 等互斥性钩子。 注册钩子用 $TagFeather->reg_parsehook($type,$name,$callback,$overfollow=false) $overfollow 表示是否覆盖原来的钩子 ($TagFeather->insert_parsehook尚在试验中) 注销钩子用 $tf->unreg_parsehook($name,$type=false) 当 $type==false 的时候为注销全部类型的同名钩子系统默认钩子 'pi_tf_outblock','comment_ssi', 'postbuild_final','postbuild_signature','postbuild_unmatch', //'postbuild_loadlibrary', 'prebuild_signature','prebuild_struct', 'doctype_final','text_cookie', 默认钩子列表 钩子类型 钩子名称(按照执行的顺序) 钩子作用 modifier (新注册的 modifier 钩子) modifier_morequick 为了更方便使用,如果有函数 tf_modifier_default 则返回 tf_modifier_default 的值 modifier_loadconfig 加载配置文件 tagfeather.ini modifier_filename 如果没有源文件名,则目标文件为 源文件的基本名+ .cache.cphp modifier_time 对比目标文件和源文件的修改时间,决定是否编译error (新注册的 error 钩子) error_final 显示输出错误消息,设置解析信息为出错 并把剩下要解析的数据清空postbuild (新注册的 postbuild 钩子) postbuild_signature 添加编译签名信息 postbuild_final 组织直接访问pi (新注册的 post 钩子) pi_tf_outblock 替换 PHP 代码中 的 TagFeather::OutBegin() TagFeather::OutEnd 之间的代码让运行时候跳过。这是为了避免 重复包含函数的 PHP 错误comment (新注册的 comment 钩子) comment_ssi TagFeather 的 SSI (Sever Side Include )钩子 实验性的prebuild (新注册的 post 钩子) prebuild_signature 编译前准备签名信息 prebuild_struct 根据配置把 struct 文件内容添加到 要编译的数据,由于这样不是脚本安全,现在正准备改进tagbegin (新注册的 tagbegin 钩子) tagblock_script_final 处理 script 标签 tagbegin_php_assign 处理 php:assign 标记的标签, php:assign 标记的标签很重要 tagbegin_assign 配合处理 php:assign 标记的标签,在解析标签开始的时候给满足条件的标签附加相应的属性 tagblock_parser_pure 原样显示标签及子标签(未完成,未测试) tagblock_feather 常用一些 php: 开始的标签在此处理。详细请见 TF_Feather 类 tagblock_morequick 使得可以使用 tf_php_serverattr() 处理对应 php:severattr 属性 tf_class_theclass 处理带 class 属性带theclass的标签 tf_id_theid 对应 id=theid tf_tagname_thetag 对应 标签名称为 thetag 的。 前缀 tf 表示标签前后, tfbegin 仅仅是在 标签开始之前,tfend 是在标签开始之后tagend (新注册的 post 钩子) tagblock_morequick 使得可以使用 tf_php_serverattr() 处理对应 php:severattr 属性 tf_class_theclass 处理带 class 属性带theclass的标签 tf_id_theid 对应 id=theid tf_tagname_thetag 对应 标签名称为 thetag 的。 前缀 tf 表示标签前后, tfbegin 仅仅是在 标签开始之前,tfend 是在标签开始之后 tagend_attrcookie 处理 标签属性里的 {} tagblock_feather 常用一些 php: 开始的标签在此处理。详细请见 TF_Feather 类 tagblock_parser_pure 原样显示标签及子标签(未完成,未测试) tagend_unmatch 如果标签匹配不对则报错 tagend_final 将当前一级标签内容添加到放入父级的 parser:text 里text text_cookie 处理 文本中 {} 的内容 常见解析错误原因表 timeout 文档结构过于复杂,编译的时候超时 Unmatched Data 不知道属于什么类别无法解析接下来的数据 Unclose PI 没关闭的 PI 有 “<?” 没有 “?> ” Unclose ASP 没关闭的ASP 有 “<%”没有“%>” Attribute Not Qouted 属性没有用 引号包围,最常见原因是 忘记关闭 引号 Unclose SCRIPT 没有 </script> 结尾 Unmatch TagName 标签名称不匹配,最常见原因是写错或漏写结束标签 核心标签属性 parser:pretag 在标签之前输出 parser:posttag 在标签之前输出 parser:pretext 在标签文本前输出 parser:posttext 在标签文本后输出 parser:text 标签文本 parser:tagname 标签名字 parser:keeptext 不使用精简模式输出标签,保留标签文字部分 TagFeather 默认附加标签属性(按执行顺序) 钩子类别php:block 用于代替标签文本 tagend php:block_mode php:block 的附加选项 tagend php:showonce 有同样 php:showonce 的标签只会输出一次(但解析不受限制) tagbegin php:assign 给特定标签 增加属性 tagbegin php:assign_mode php:assign 的附加属性 tagbegin php:byvisible 根据标签显示内容附加特性 tagend php:maphref tagend php:removeclass tagend tagendover: tagend那些框架 都试图 把 本来的语言 转变成 框架的语言本身 FAQ 空白框架的速度,做过一个测试,不用模板要占0.5毫秒。 Smarty 要占220毫秒 ,TagFeather 要占 70毫秒。 由于 PHP Bug#33595 TagFeather 有 634 字节的泄露。 |