Shine模板引擎,第一部分:使用入门
本文内容
- Django模板语言和Shine的关系
- 安装Shine
- 在PHP中使用Shine模板
- 创建Shine实例
- Shine模板变量
- Shine模板标签
- Shine模板注释
- 写一个完整的Shine模板
- 使用模板缓存
- 使用命令行创建模板配置
- 总结
Django是一个非常流行的Python Web开发框架,其提供的模板语言非常简单,但也非常强大。本文中所介绍的Shine模板引擎是用使用PHP语言对其模板部分的实现。通过本文您可以知道如何在PHP中使用Shine模板引擎和如何写Shine模板语言。
Django模板语言和Shine的关系
Shine是使用PHP5对Django模板语言的移植。在移植过程中,Shine定位于独立的模板引擎,所以在移植的过程中去除了一些与Django框架相关的内容,如:模板文件加载器、Requext_Context等。但Shine并不是简单的移植,添加了新的模板加载方式,加入了编译缓存等Django模板 语言不存在的东西。Shine还在不断的发展,最终将形成一个更适合PHP,但又继承了Django模板语言精髓的模板引擎。
Django模板语言在设计上非常有自己的特色,因此Shine也是符合这种设计思想的。这些设计思想包括以下几点,下面的内容参考自DjangoBook并做适当的修改:
- 业务逻辑应该和表现逻辑相对分开 。我们将模板系统视为控制表现及表现相关逻辑的工具,仅此而已。模板系统不应提供超出此基本目标的功能。
- 出于以上原因,在Shine模板中是不可能直接调用PHP代码的。所有的编程工作基本上都被局限于模板标签的能力范围。当然, 是有可能写出自定义的模板标签来完成任意工作,但这些“超范围”的 Shine模板标签有意地不允许执行任何PHP代码。
- 语法不应受到HTML/XML的束缚。尽管Shine模板系统主要用于生成HTML,它还是被有意地设计为可生成非HTML格式,如纯文本。一些其它的模板语言是基于XML的,将所有的模板逻辑置于XML标签与属性之中,而Django有意地避开了这种限制。强制要求使用有效XML编写模板将会引发大量的人为错误和难以理解的错误信息,而且使用XML引擎解析模板也会导致令人无法容忍的模板处理开销。
- 假定设计师精通HTML编码。模板系统的设计意图并不是为了让模板一定能够很好地显示在Dreamweaver这样的所见即所得编辑器中。这种限制过于苛刻,而且会使得语法不能像目前这样的完美。Shine要求模板创作人员对直接编辑HTML非常熟悉。
- 假定设计师不是PHP程序员。模板系统开发人员认为:网页模板通常由设计师而不是程序员编写,因而假定这些人并不掌握PHP相关知识。
- 目标并不是要发明一种编程语言。目标是恰到好处地提供如分支和循环这一类编程式功能,这是进行与表现相关判断的基础。
这些设计思想,造成了对模板语言的限制,比如:模板中不能设置变量和改变变量的值;模板中不能调用任何PHP代码。但这些设计并不是说不能实现,您可以通过扩展Shine的标签来实现这些功能,只是在默认的模板标签中没有实现。
Shine模板语言是基于文本的,这意味着您能使用它输出任何文本内容,比如:html、xml、css等等,在Shine模板语法中,有三种类型的语法块:{% %}、{{ }}、{# #}。我们在将下面的内容向您介绍他们有哪些作用。
安装Shine
Shine是一个开源项目,同Django一样使用BSD授权发布源码。Shine项目使用Mercurial对源码进行管理,项目首页位于http://bitbucket.org/gonefish/shine/,您可以下载最新的开发版本和正式发布的版本。
下载最新的Shine源码包或发行包后,解压后里有会有4个目录:bin、demo、lib和unittest。如下图:

bin 目录中包含一个命令行工作,用于快速创建一个Shine模板目录结构;demo目录中包含simple.php和complex.php两个例子;lib目录中包含使用Shine所需要的文件;unittest目录中包含了所有的单元测试代码,需要使用PHPUnit 3.3以上的版本。
安装Shine非常容易,就像其它的PHP库一样,你只需要将lib目录下的所有文件和目录拷贝到PHP的include_path所设置的的目录可以了。
在PHP中使用Shine模板
在PHP代码中使用Shine非常简单,很容易和您现有的代码整合起来。
require_once 'Shine.php'; $t = new Shine('Hello {{ user }}.'); $context = array(); $context['user'] = 'Shine'; echo $t->render($context);
执行代码后,屏幕上会输出Hello Shine. 通过传递模板字符串或者模板文件的路径做为参数创建一个Shine实例,然后通过一个PHP的关联数组来组织模板参数,由于PHP的数组可以容纳任意类型 的数据,您可以放心的组织您的模板参数,当然您可以使用强大的模板语言调用它们。最后使用Shine实例的render方法返回模板结果,该方法接受一个 可选参数,参数是一个包含模板变量的PHP关联数组。
创建Shine实例
通过上面的代码片断,我们了解到要使用Shine模板引擎,必须先创建一个Shine实例。在Shine中,支持三种不同的方式来创建模板实例,您可以自由的选择以任何一种方式来创建实例,充分给予您最大的灵活性。
第一种方式:直接传入Shine模板字符串,这种方式最直观,也最灵活,您可以自定义模板字符的来源。
$t = new Shine('Hello {{ user }}.');
这种方式的特点是模板的来源是不限的,您可以使用任何容器来保存模板字符串。
第二种方式:将模板文件的相对路径或绝对路径做为参数,创建Shine实例。
$t = new Shine('./test.html');
或者:
$t = new Shine('/the/template/path');
这种方法最简单,您只需要知道模板文件的路径就可以了。
第三种方式:设置模板文件目录,然后通过将模板文件的名称做为参数创建Shine实例。
Shine::config(array('templates' => array('/the/template/dir/path'))); $t = new Shine('index.html');
上面这种方法,当设置了模板目录后,在创建Shine实例的时候,系统会自动地在已经设置了模板目录中查找文件,如果在已经设置的模板目录中没有找到,还会尝试在当前的目录上下文中查找。在设置上会稍显复杂,但这样更容易组织您的模板文件。
Shine模板变量
在 Shine模板标记中,以两个大括号括起来的内容将解析成变量,如;{{ foo }}。模板变量来自于Shine实例render方法的参数,即一个关联数组。在Shine模板中,模板变量的访问是非常强大的,因为你只需要通过”.”符号来访问任何数据,如:{{ foo.bar }}。这个”.”符号会自动查找模板变量的上下文,根据变量环境的不同调用不同的东西,像上面的例子中,bar可能是一个foo关联数组的键;或者是 foo对象的bar方法;或者是foo对象的属性。如果在模板变量上下文中没有发现任何可调用的变量时,将会抛出模板语法异常。
Shine模板变量还支持另外一种强大的功能:过滤器,如:
{{ foo|default:”Hello World.” }}使用方法是在需要使用过滤器参数的后面添加”|”符号和想调用的过滤器名称。这看起来像Unix中的管道符一样,实际上确实很像,因为被过滤的参数,作为过滤器输入。某些过滤器中还能接收一个额外的参数,在上面的例子中,如果foo在模板变量上下文中是一个逻辑假值,那么这个变量最终将以Hello World.输出,而不是foo在模板变量上下文中的值。同Unix管道符一样,过滤器支持多个,如:
{{ foo|default:”Hello World.”|upper }}第一个过滤器输出的结果会作为第二个过滤的输入,这个变量foo是逻辑假值时,最终会输出HELLO WORLD.
Shine模板标签
在 shine模板标签中,以大括号和百分号包围的文本是模板标签,如:{% if foo %}bar{% endif %}。很明显这个标签是一个if流程判断标记。标签的设计比变量要复杂得多,当然所提供的功能也更为强大,在Shine中通过模板标签您能够创建一段文本 输出;实现流程控制逻辑;包含另外一段模板代码;继承一个模板等。下面我们来看一些例子:
{% if foo %}
If foo is true ...
{% else %}
If foo is false ...
{% endif %}if标签会判断foo的逻辑值,当为逻辑真是的时候执行if和else之间的部分,如果foo是逻辑假值,会执行else和endif之间的部分。
{% for v in list %}
{{ v }}
{% endfor %}list是一个数组或者任何可迭代的东西,v则是当前的值,你可以在for和endfor中组织这些变量。提示:这看起来跟PHP中的for不一样,实际上for标签更像PHP中的foreach。当然for标签还支持一些更复杂的方法,可以去查看相关参考。
模板继承是Shine的非常重要的特性,通过模板继承可以非常简单的实现二步视图模式。我们来看一个例子:
base.html
{% block content %}
{% endblock %}index.html
{% extends ”base.html“ %}
{% block title %}Hello Shine{% endblock %}
{% block content %}This is Shine template.{% endblock %}通过extends标签声明继承,注意:继承标签必须写在模板文件的最前面。这样渲染index.html模板后输出的是:
This is Shine template.
Shine模板注释
在 Shine模板标签中,以大括号和井号包围的文本是单行注释,如:{# commit|upper #}。注释的内容不会在模板渲染时输出。注意:{# #}只能应用于单行注释,当有任何换行符出现时,注释将不会有效,这个限制是为了提高模板解析性能。如果需要使用多行注释请使用{% commit %}{% endcommit %}标签,就像其它标签一样。
写一个完整的Shine模板
base.html模板文件,定义基本的页面模板。
{% include 'header.html' %}
{% block content %}
{% endblock %}
{% include 'footer.html' %}header.html页头模板文件。
<div id="”header”"> This is header.</div>
footer.html页脚模板文件。
<div id="”footer”"> This is footer.</div>
index.html模板文件继承于base.html模板,并重新填充title和conent块。
{% extends "base.html" %}
{% block title %}{{ section.title }}{% endblock %}
{% block content %}
<h1>{{ section.title }}</h1>
{% for story in story_list %}
<h2>
<a href="{{ story.url}}">
{{ story.name|upper }}
</a></h2>
{{ story.timestamp |date:"Ymd" }}
{% endfor %}
{% endblock %}模板变量如下:
$context = array( 'section' => array( 'title' => 'Demo' ), 'story_list' => array( array( 'url' => 'http://gonefish.cn', 'name' => 'Gonefish', 'timestamp' => '1240992979' ), array( 'url' =>'http://www.lifefix.cn', 'name' => 'LifeFix', 'timestamp' => '1240992979' ) ) );
上面这就是一个完整的Shine模板例子,其中包括了:模板继承、模板包含、模板流程控制、模板变量的输出。
使用模板缓存
由 于Shine模板语言是需要编译的,如果每次重新编译模板是非常消耗时间的,所以在Shine中内建一个模板编译后的缓存系统,缓存系统会生成一个特殊的 PHP文件。由于Shine模板引擎不同于Smarty,编译后的代码还是需要解析的,所以在使用Shine时,推荐使用模板缓存来加强性能。要开启模板 缓存非常简单,只需要设置一个缓存目录即可,缓存目录必须可写,才能正常使用。
Shine::config(array('cache' => '/the/cache/dir'));
设置后,在使用Shine编译模板时,会在相应的文件生成缓存。因此,最好使用Shine模板前,完成模板缓存的设置。
使用命令行创建模板配置
在shine的发布的bin目录中,有一个叫startshine.php的命令行工具。您可以使用这个命令行工具创建一个标准的Shine模板目录结构。通过执行下面的命令创建一个名为django的Shine模板目录:
php startshine.php django

在 这个目录中包括三个目录:cache、templates、templatetags。cache目录用于缓存编译后的模板文件;templates目录 用于存放所有的模板文件;templatetags目录用于存放自定义的模板Tag和Filter,如何开发自定义的模板Tag和Filter,将在本系 列的第二部分介绍。Shine.config.php包含了默认了初始化的代码及一些配置项,然后您只需要通过require和include包含 Shine.config.php就可以开始使用Shine模板引擎了。
总结
通过对本文的学习,相信您已经知道了如何在PHP中使用Shine模板引擎及编写模板文件了。但Shine模板引擎功能还不仅仅局限于此,在本系列文章的第二部分,我们将介绍如何扩展Shine模板引擎,通过扩展Shine模板引擎,将无限扩展Shine的功能。