在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 相关文章推荐
从网上搜到的phpwind 0day的代码
Dec 07 PHP
浅析PHP水印技术
Feb 14 PHP
php email邮箱正则
Oct 08 PHP
PHP 七大优势分析
Jun 23 PHP
php allow_url_include的应用和解释
Apr 22 PHP
PHP源码之explode使用说明
Aug 05 PHP
php使用GeoIP库实例
Jun 27 PHP
PHP判断来访是搜索引擎蜘蛛还是普通用户的代码小结
Sep 14 PHP
php使用ffmpeg向视频中添加文字字幕的实现方法
May 23 PHP
php微信公众号开发(3)php实现简单微信文本通讯
Dec 15 PHP
Yii 2.0自带的验证码使用经验分享
Jun 19 PHP
PHP数据源架构模式之表入口模式实例分析
Jan 23 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实现paypal 授权登录
2015/05/28 PHP
关于PHP内置的字符串处理函数详解
2017/02/04 PHP
javascript 流畅动画实现原理
2009/09/08 Javascript
屏蔽F1~F12的快捷键的js函数
2010/05/06 Javascript
jquery判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
2010/10/15 Javascript
jquery无缝向上滚动实现代码
2013/03/29 Javascript
js获取url参数值的两种方式
2013/09/10 Javascript
转换字符串为json对象的方法详解
2013/11/29 Javascript
jquery序列化表单去除指定元素示例代码
2014/04/10 Javascript
ExtJS4如何给同一个formpanel不同的url
2014/05/02 Javascript
JavaScript基于setTimeout实现计数的方法
2015/05/08 Javascript
jQuery插件windowScroll实现单屏滚动特效
2015/07/14 Javascript
jquery结婚电子请柬特效源码分享
2015/08/21 Javascript
JavaScript实现DOM对象选择器
2016/09/24 Javascript
Javascript 函数的四种调用模式
2016/11/05 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
2016/12/14 Javascript
jQuery中 bind的用法简单介绍
2017/02/13 Javascript
layer弹窗插件操作方法详解
2017/05/19 Javascript
js实现多张图片延迟加载效果
2017/07/17 Javascript
关于前后端json数据的发送与接收详解
2017/07/30 Javascript
node文字生成图片的示例代码
2017/10/26 Javascript
Angular4学习之Angular CLI的安装与使用教程
2018/01/04 Javascript
Vue+Element-UI实现上传图片并压缩
2019/11/26 Javascript
微信小程序保存图片到相册权限设置
2020/04/09 Javascript
js实现鼠标拖曳效果
2020/12/30 Javascript
python3实现名片管理系统
2020/11/29 Python
Python程序打包工具py2exe和PyInstaller详解
2019/06/28 Python
flask 实现上传图片并缩放作为头像的例子
2020/01/09 Python
解决margin 外边距合并问题
2019/07/03 HTML / CSS
HTML5 LocalStorage 本地存储详细概括(多图)
2017/08/18 HTML / CSS
自我评价个人范文
2013/12/16 职场文书
美术指导求职信
2014/03/17 职场文书
2014党员民主评议个人总结
2014/09/10 职场文书
小学生节水倡议书
2015/04/29 职场文书
商场圣诞节活动总结
2015/05/06 职场文书
MySQL中正则表达式(REGEXP)使用详解
2022/07/07 MySQL