在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 相关文章推荐
Session的工作方式
Oct 09 PHP
不错的一篇面向对象的PHP开发模式(简写版)
Mar 15 PHP
php 面试碰到过的问题 在此做下记录
Jun 09 PHP
php 创建以UNIX时间戳命名的文件夹(示例代码)
Mar 08 PHP
Codeigniter中集成smarty和adodb的方法
Mar 04 PHP
配置Nginx+PHP的正确思路与过程
May 10 PHP
使用PHP免费发送定时短信的实例
Oct 24 PHP
PHP三种方式实现链式操作详解
Jan 21 PHP
php 广告点击统计代码(php+mysql)
Feb 21 PHP
php语法检查的方法总结
Jan 21 PHP
使用SMB共享来绕过php远程文件包含的限制执行RFI的利用
May 31 PHP
TP5框架使用QueryList采集框架爬小说操作示例
Mar 26 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
PHP中用header图片地址 简单隐藏图片源地址
2008/04/09 PHP
PHP命名空间(namespace)的动态访问及使用技巧
2014/08/18 PHP
关于URL最大长度限制的相关资料查证
2014/12/23 PHP
PHP实现Google plus的好友拖拽分组效果
2016/10/21 PHP
PHP缩略图生成和图片水印制作
2017/01/07 PHP
Linux下安装Memcached服务器和客户端与PHP使用示例
2019/04/15 PHP
JQuery AJAX实现目录浏览与编辑的代码
2008/10/21 Javascript
Tinymce+jQuery.Validation使用产生的BUG
2010/03/29 Javascript
20款超赞的jQuery插件 Web开发人员必备
2011/02/26 Javascript
Jquery ajaxStart()与ajaxStop()方法(实例讲解)
2013/12/18 Javascript
JavaScript字符串对象toUpperCase方法入门实例(用于把字母转换为大写)
2014/10/17 Javascript
浅谈jquery中delegate()与live()
2015/06/22 Javascript
利用jQuery和CSS将背景图片拉伸
2015/10/16 Javascript
简单理解JavaScript中的封装与继承特性
2016/03/19 Javascript
详解JavaScript中基于原型prototype的继承特性
2016/05/05 Javascript
Node.js 日志处理模块log4js
2016/08/28 Javascript
简单谈谈Vue 模板各类数据绑定
2016/09/25 Javascript
vue 标签属性数据绑定和拼接的实现方法
2018/05/17 Javascript
JS Object.preventExtensions(),Object.seal()与Object.freeze()用法实例分析
2018/08/25 Javascript
bootstrap table表格插件之服务器端分页实例代码
2018/09/12 Javascript
Laravel admin实现消息提醒、播放音频功能
2019/07/10 Javascript
Vue替代marquee标签超出宽度文字横向滚动效果
2019/12/09 Javascript
理解JavaScript中的对象
2020/08/25 Javascript
[00:34]DOTA2上海特级锦标赛 VG战队宣传片
2016/03/04 DOTA
在Python的Django框架中实现Hacker News的一些功能
2015/04/17 Python
Windows和Linux下Python输出彩色文字的方法教程
2017/05/02 Python
python录音并调用百度语音识别接口的示例
2020/12/01 Python
微软巴西官方网站:Microsoft Brasil
2019/09/26 全球购物
生物技术研究生自荐信
2013/11/12 职场文书
生物学学生自我评价
2014/01/17 职场文书
机械设计毕业生自荐信
2014/02/02 职场文书
优秀护士获奖感言
2014/02/20 职场文书
“四风”问题的主要表现和危害思想汇报
2014/09/19 职场文书
2015年中学元旦晚会活动方案
2014/12/09 职场文书
2015年售票员工作总结
2015/04/29 职场文书
windows11怎么查看自己安装的版本号? win11版本号的查看方法
2021/11/21 数码科技