**引子:**今天遇到一个问题,模板中某些变量有时候没有定义,若是php开启了E_ALL报错级别,那么会出现一个notice,提示变量未定义。 一开始的想法是经过三元表达式(<?=isset($var)?$var:'';?>)来给每一个变量设定一个默认值,后来发现这种写法太繁琐,并且与volt标签格格不入。 再后来想到屏蔽E_NOTICE报告,但开发环境下仍是很不恰当的。 最后发现volt引擎有一个过滤器Filters功能,解决了这个问题,写法如:{{ var|default('str') }} ,在$var为空的时候,将会将该处设置为str,固然,str能够是空字符串。 本文就探究一下什么是过滤器,以及如何自定义过滤器。php
第一,模板渲染的是什么? 在使用volt模板引擎的时候,模板是如何渲染的呢?你们都知道,在控制器方法执行完毕后,框架会自动渲染视图View,而这时候因为你使用了volt模板引擎,里面特有的一套标签语法并不是php语法,因此视图没法直接include模板文件而做为php脚本解释。这时候视图会作一件事情,它会先将模板代码中的标签替换为php代码,保存到模板缓存文件中,缓存位置是你在di中配置视图的时候本身设置的,每一个缓存文件都对应一个模板文件,第二次渲染视图的时候将直接取缓存文件,避免了每次都要解析volt标签,因此性能上与原生php模板并没有差距,某些状况下可能更好(布局以及模板继承时,会将多层模板合并为一个,减小了文件读取次数)。html
第二,标签'原形' {{ var|default('str') }}究竟被转化为何?咱们能够经过观察模板缓存看到,这个标签大概被转化为shell
<!-- lang: php --> <?php echo (empty($var) ? ('str') : ($var)); ?>
第三,理解管道'|' 熟悉shell的朋友这一步一眼了然,标签的做用机制是:将$var的值传给下一个过滤器default处理,过滤器还可附加其余参数,只要如同函数调用同样增长参数便可,如上的 ('str');变量类型的标签最终会转化为echo语句。数组
第四,自定义过滤器 经过官方手册能够知道,在di中注册volt模板引擎的时候,能够添加自定义的filter方法,先看一段代码:浏览器
<!-- lang: php --> //volt模板引擎服务 $di->set('voltService', function($view, $di) { $volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di); $volt->setOptions(array( "compiledPath" => APP_PATH."/runtime/volt/", "compiledExtension" => ".compiled" )); //自定义过滤器 $compiler = $volt->getCompiler(); $compiler->addFilter('int', function($resolvedArgs, $exprArgs) { return 'intval(' . $resolvedArgs . ')'; }); return $volt; });
上面咱们首先经过getCompiler拿到"编译器对象"$compiler,在$compiler中经过addFilter添加自定义的过滤器,上面的代码添加了一个叫作 "int" 的过滤器,其做用是将$var的值转化为整形。缓存
第五,理解 当volt模板解析的时候,假若有一个标签{{ var|int }},这时候$compiler会检查对象中有没有int过滤器,显然是有的,那么会调用匿名函数,将返回值字符串放到echo 中,如上定义的int过滤器,最终返回的就是 intval($val),该标签最终被替换为框架
<!-- lang: php --> <?php echo intval($val);?>
以后交由PHP解释并返回html代码到浏览器。 细节:$resolvedArgs是什么? 它是变量名和附加参数的拼接,好比上面int没有附加参数,那么它的值就是 '$var',注意这里是原义字符串,不要当成变量。 假设咱们定义了一个过滤器 trim,咱们想要 {{ var|trim('%') }}的结果为 trim($val,'%')的值,那么在定义过滤器匿名函数的时候就须要这么写函数
<!-- lang: php --> $compiler->addFilter('concat', function($resolvedArgs, $exprArgs) { return 'trim('.$resolvedArgs.')'; }); return $volt;
也就是$resolvedArgs这个变量的值是:$val,'%' 注意,这里是原义字符串,为了表示方便,省略了两边的单引号,$var变量名永远在开头。 最终标签被替换为php代码:<?php echo trim($val,'%');?>
那么$exprArgs是什么呢?它是一个数组,保存了每一个参数的类型、原义字符串、所属脚本等等,通常用不到,不过特殊状况下可能使用,好比内置的 default过滤器,在 default('') 指定参数的时候,返回的是 empty($var)?'':$var 这里就须要从$exprArgs获得每一个参数的信息。布局
自定义模板函数也是一样的原理,目的都是将标签转换为php代码,并保存到模板缓存中。性能
感言: 模板引擎并不神秘,只要理解其工做机制,代码实现原理,每一个人都能实现本身的模板引擎。