在Yii框架中使用PHP模板引擎Twig的例子


Posted in PHP onJune 13, 2014

Twig是一款快速、安全、灵活的PHP模板引擎,它内置了许多filter和tags,并且支持模板继承,能让你用最简洁的代码来描述你的模板。他的语法和Python下的模板引擎Jinjia以及Django的模板语法都非常像。 比如我们在PHP中需要输出变量并且将其进行转义时,语法比较累赘:

<?php echo $var ?>
<?php echo htmlspecialchars(\$var, ENT_QUOTES, 'UTF-8') ?>

但是在Twig中可以这样写:
{{ var }}
{{ var|escape }}
{{ var|e }}         {# shortcut to escape a variable #}

遍历数组:
{% for user in users %}
  * {{ user.name }}
{% else %}
  No user has been found.
{% endfor %}

但是要在Yii Framework集成Twig就会遇到点麻烦了,官方网站中已经有能够集成Twig的方案,所以这里我也不再赘述。但是由于Twig中是不支持PHP语法的,所以在有些表达上会遇到困难,比如我们在写Form的视图时,经常会这么写:

<?php $form=$this->beginWidget('CActiveForm'); ?>
    <span>Login</span>
    <ul>
  <li>
    <?php echo $form->label($model,'username'); ?>
                <?php echo $form->textField($model,'username'); ?>
  </li>
  <li>
    <?php echo $form->label($model,'password'); ?>
                <?php echo $form->passwordField($model,'password'); ?>
  </li>
  <li class="last">
    <button type="submit">Login</button>
  </li>
</ul>
    <?php echo $form->error($model,'password'); ?>
<?php $this->endWidget(); ?>

但是这样的语法是没法在twig中表达的,所以想去扩展下Twig的功能,让他能够支持我们自定义的widget标签,然后自动解析成我们需要的代码。 总共需要两个类:TokenParser和Node,下面直接上代码:
<?php
/*
 * This file is an extension of Twig.
 *
 * (c) 2010 lfyzjck
 */
/**
 * parser widget tag in Yii framework
 *
 * {% beginwidget 'CActiveForm' as form %}
 *    content of form
 * {% endwidget %}
 *
 */
class Yii_WidgetBlock_TokenParser extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();
        $name = $stream->expect(Twig_Token::STRING_TYPE);
        if($stream->test(Twig_Token::PUNCTUATION_TYPE)){
            $args = $this->parser->getExpressionParser()->parseHashExpression();
        }
        else{
            $args = new Twig_Node_Expression_Array(array(), $lineno);
        }
        $stream->expect(Twig_Token::NAME_TYPE);
        $assign = $stream->expect(Twig_Token::NAME_TYPE);
        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        return new Yii_Node_WidgetBlock(array(
            'alias' => $name->getValue(),
            'assign' => $assign,
        ), $body, $args, $lineno, $this->getTag());
    }
    /**
     * Gets the tag name associated with this token parser.
     *
     * @param string The tag name
     */
    public function getTag()
    {
        return 'beginwidget';
    }
    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endwidget');
    }
}
class Yii_Node_WidgetBlock extends Twig_Node
{
    public function __construct($attrs, Twig_NodeInterface $body, Twig_Node_Expression_Array $args = NULL, $lineno, $tag)
    {
        $attrs = array_merge(array('value' => false),$attrs);
        $nodes = array('args' => $args, 'body' => $body); 
        parent::__construct($nodes, $attrs, $lineno,$tag);
    }
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);
        $compiler->write('$context["'.$this->getAttribute('assign')->getValue().'"] = $context["this"]->beginWidget("'.$this->getAttribute('alias').'",');
        $argNode = $this->getNode('args');
        $compiler->subcompile($argNode)
                 ->raw(');')
                 ->raw("\n");
        $compiler->indent()->subcompile($this->getNode('body'));
        $compiler->raw('$context["this"]->endWidget();');
    }
}
?>

然后在Twig初始化的地方增加我们的语法解析类:
$twig->addTokenParser(new Yii_WidgetBlock_TokenParser);

然后我们就可以在twig的模板里这么写了:
{% beginwidget 'CActiveForm' as form %}
<ul>
  <li>
    {{ form.label(model, 'username') }}
    {{ form.textField(model, 'username') }}
  </li>
  <li>
    {{ form.label(model, 'password') }}
    {{ form.passwordField(model, 'password') }}
  </li>
</ul>
{% endwidget %}
PHP 相关文章推荐
用 php 编写的日历
Oct 09 PHP
php代码优化及php相关问题总结
Oct 09 PHP
用PHP书写安全的脚本代码
Feb 05 PHP
PHP中SimpleXML函数用法分析
Nov 26 PHP
Smarty使用自定义资源的方法
Aug 08 PHP
PHP验证码生成原理和实现
Jan 24 PHP
PHP中子类重载父类的方法【parent::方法名】
May 06 PHP
EarthLiveSharp中cloudinary的CDN图片缓存自动清理python脚本
Apr 04 PHP
Django 中 cookie的使用
Aug 17 PHP
详解Yaf框架PHPUnit集成测试方法
Dec 27 PHP
PHP扩展mcrypt实现的AES加密功能示例
Jan 29 PHP
laravel 解决paginate查询多个字段报错的问题
Oct 22 PHP
ThinkPHP中U方法的使用浅析
Jun 13 #PHP
PHP实现单例模式最安全的做法
Jun 13 #PHP
PHP5.5和之前的版本empty函数的不同之处
Jun 13 #PHP
PHP输出英文时间日期的安全方法(RFC 1123格式)
Jun 13 #PHP
PHP中多维数组的foreach遍历示例
Jun 13 #PHP
PHP根据传来的16进制颜色代码自动改变背景颜色
Jun 13 #PHP
php smarty truncate UTF8乱码问题解决办法
Jun 13 #PHP
You might like
极典R601SW收音机
2021/03/02 无线电
文件上传的实现
2006/10/09 PHP
修改destoon会员公司的伪静态中的com目录的方法
2014/08/21 PHP
学习PHP session的传递方式
2016/06/15 PHP
自适应高度框架 ----属个人收藏内容
2007/01/22 Javascript
Extjs中使用extend(js继承) 的代码
2012/03/15 Javascript
js 判断计算字符串长度/判断空的简单方法
2013/08/05 Javascript
基于JQuery实现的Select级联
2014/01/27 Javascript
jQuery+ajax实现动态执行脚本的方法
2015/01/27 Javascript
XML文件转化成NSData对象的方法
2015/08/12 Javascript
javascript bom是什么及bom和dom的区别
2015/11/26 Javascript
js格式化时间的方法
2015/12/18 Javascript
逻辑表达式中与或非的用法详解
2016/06/06 Javascript
jQuery控制div实现随滚动条滚动效果
2016/06/07 Javascript
jQuery和hwSlider实现内容响应式可触控滑动切换效果附源码下载(二)
2016/06/22 Javascript
关于Javascript中defer和async的区别总结
2016/09/20 Javascript
微信小程序 数据访问实例详解
2016/10/08 Javascript
微信小程序Server端环境配置详解(SSL, Nginx HTTPS,TLS 1.2 升级)
2017/01/12 Javascript
vue v-for 使用问题整理小结
2019/08/04 Javascript
15 分钟掌握vue-next响应式原理
2019/10/13 Javascript
微信小程序监听用户登录事件的实现方法
2019/11/11 Javascript
原生js实现弹幕效果
2020/11/29 Javascript
[48:00]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第二场 11.04
2020/11/04 DOTA
Python调用命令行进度条的方法
2015/05/05 Python
Python爬虫获取整个站点中的所有外部链接代码示例
2017/12/26 Python
pytorch + visdom CNN处理自建图片数据集的方法
2018/06/04 Python
解决pip install psycopg2出错问题
2020/07/09 Python
用CSS3的box-reflect设置文字倒影效果的方法讲解
2016/03/07 HTML / CSS
Html5实现iPhone开机界面示例代码
2013/06/30 HTML / CSS
中邮全球便购:中国邮政速递物流
2017/03/04 全球购物
美国著名的女性内衣零售商:Frederick’s of Hollywood
2018/02/24 全球购物
夏季药店促销方案
2014/08/22 职场文书
2014年党员自我评议总结
2014/09/23 职场文书
领导干部“四风”问题批评与自我批评材料
2014/09/24 职场文书
公务员保密工作承诺书
2015/05/04 职场文书
优秀教师主要事迹材料
2015/11/04 职场文书