在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中其实也可以用方法链
Nov 10 PHP
如何用PHP实现插入排序?
Apr 10 PHP
如何使用“PHP” 彩蛋进行敏感信息获取
Aug 07 PHP
php ZipArchive压缩函数详解实例
Nov 06 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
Oct 21 PHP
PHP+MySQL修改记录的方法
Jan 21 PHP
thinkPHP下的widget扩展用法实例分析
Dec 26 PHP
php简单解析mysqli查询结果的方法(2种方法)
Jun 29 PHP
PHP实现的mysql主从数据库状态检测功能示例
Jul 20 PHP
PHP实现基于3DES算法加密解密字符串示例
Aug 24 PHP
PHP实现PDO操作mysql存储过程示例
Feb 13 PHP
PHP里的$_GET数组介绍
Mar 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
收音机史话 - 1960年代前后的DIY
2021/03/02 无线电
PHP初学入门
2006/11/19 PHP
php框架Phpbean说明
2008/01/10 PHP
PHP生成HTML静态页面实例代码
2008/08/31 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
PHP使用header()输出图片缓存实例
2014/12/09 PHP
PHP中递归的实现实例详解
2017/11/14 PHP
基于jquery循环map功能的代码
2011/02/26 Javascript
JQuery slideshow的一个小问题(如何发现及解决过程)
2013/02/06 Javascript
jQuery实现仿微软首页感应鼠标变化滑动窗口效果
2015/10/08 Javascript
自己动手写的jquery分页控件(非常简单实用)
2015/10/28 Javascript
javascript正则表达式总结
2016/02/29 Javascript
使用JavaScript实现弹出层效果的简单实例
2016/05/31 Javascript
JS代码实现根据时间变换页面背景效果
2016/06/16 Javascript
javascript监听页面刷新和页面关闭事件方法详解
2017/01/09 Javascript
Angular.js指令学习中一些重要属性的用法教程
2017/05/24 Javascript
vue 粒子特效的示例代码
2017/09/19 Javascript
原生JS实现的跳一跳小游戏完整实例
2019/01/27 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
mpvue实现左侧导航与右侧内容的联动
2019/10/21 Javascript
vue-cli3.0实现一个多页面应用的历奇经历记录总结
2020/03/16 Javascript
使用Python的Flask框架构建大型Web应用程序的结构示例
2016/06/04 Python
Python实现登陆文件验证方法
2018/10/06 Python
使用Python+selenium实现第一个自动化测试脚本
2020/03/17 Python
python3中确保枚举值代码分析
2020/12/02 Python
html5 兼容IE6结构的实现代码
2012/05/14 HTML / CSS
台湾网购生鲜第一品牌:i3Fresh爱上新鲜
2017/10/26 全球购物
美国高档百货Nordstrom的折扣店:Nordstrom Rack
2017/11/13 全球购物
美国打印机墨水和碳粉购物网站:QuikShip Toner
2018/08/29 全球购物
Java里面有没有全局变量?为什么?
2015/02/06 面试题
什么叫做SQL注入,如何防止
2016/10/04 面试题
高中校园广播稿
2014/01/11 职场文书
社区矫正工作方案
2014/06/04 职场文书
2014年敬老院工作总结
2014/12/08 职场文书
2015年度工程师评职称工作总结
2015/10/14 职场文书
Python可视化学习之seaborn绘制矩阵图详解
2022/02/24 Python