|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
如果不会怎么办,我的视频教程里有个最简单的留言板 最开始离不开模仿, 刚入手下手接触模版引擎的 PHP 设计师,听到 Smarty 时,城市感觉很难。其实笔者也不破例,碰都不敢碰一下。然而后来在分析 XOOPS 的法式架构时,入手下手发明 Smarty 其实其实不难。只需将 Smarty 基本功练好,在普通使用上就已相当足够了。固然基本能打好,前面的进阶使用也就不必怕了。
这篇文章的次要意图并不是要深切切磋 Smarty 的利用,这在官方利用申明中都已写得很完全了。笔者仅在此写下一些本人利用上的心得,让想要懂得 Smarty 却不得其门而入的伴侣,可以从中失掉一些启发。就由于这篇文章的内容不长短常深切,会利用 Smarty 的伴侣们能够会感觉复杂了点。
今朝本文已第三次修订了,本想多加一些料出去;不外碍于工夫的关系,良多 Smarty 的进阶技能笔者并没有研讨得很透辟,所以也不敢拿出来现眼,但笔者信任这篇文章应当可以知足大多半想进修 Smarty 的初学者了。固然本文有错误的中央也接待告诉,笔者会鄙人一次的修订中更正的。
Smarty引见
甚么是模版引擎
不晓得从甚么时分入手下手,有人入手下手对 HTML 内嵌入 Server Script 感觉不太写意。但是不管是微软的 ASP 或是开放源码的 PHP,都是属于内嵌 Server Script 的网页伺服端言语。因而也就有人想到,假如能把法式使用逻辑 (或称贸易使用逻辑) 与网页出现 (Layout) 逻辑分别的话,是否是会对照好呢?
其实这个成绩早就存在已久,从交互式网页入手下手流行时,不管是 ASP 或是 PHP 的利用者都是身兼法式开辟者与视觉设计师两种身份。可是凡是这些利用者不是法式强就是美工强,假如要二者同时统筹,那可得逝世失落很多脑细胞...
所以模版引擎就应运而生啦!模版引擎的目标,就是要到达上述提到的逻辑分别的功效。它能让法式开辟者专注于材料的掌握或是功效的告竣;而视觉设计师则可专注于网页排版,让网页看起来更具有专业感!因而模版引擎很合适公司的网站开辟团队利用,使每一个人都能发扬其特长!
就笔者接触过的模版引擎来讲,依材料出现体例也许分红:需搭配法式处置的模版引擎和完整由模版自己自行决意的模版引擎两种模式。
在需搭配法式处置的模版引擎中,法式开辟者必需要担任变量的出现逻辑,也就是说他必需把变量的内容在输入到模版前先处置好,才干做 assign 的任务。换句话说,法式开辟者仍是很多写一些法式来决意变量出现的面貌。而完整由模版自己自行决意的模版引擎,它答应变量直接 assign 到模版中,让视觉设计师在设计模版时再决意变量要若何出现。因而它便可能会有另外一套属于本人的模版法式语法 (如 Smarty) ,以便利掌握变量的出现。但如许一来,视觉设计师也得进修若何利用模版言语。
模版引擎的运作道理,起首咱们先看看以下的运转图:
普通的模版引擎 (如 PHPLib) 都是在创立模版对象时获得要解析的模版,然后把变量套入后,透过 parse() 这个办法来解析模版,最初再将网页输入。
对 Smarty 的利用者来讲,法式里也不需求做任何 parse 的举措了,这些 Smarty 主动会帮咱们做。并且已编译过的网页,假如模版没有变化的话, Smarty 就主动跳过编译的举措,直接履行编译过的网页,以节俭编译的工夫。
利用Smarty的一些概念
在普通模版引擎中,咱们常看到区域的不雅念,所谓区块也许城市长成如许:
<!-- START : Block name -->
区域内容
<!-- END : Block name -->
这些区块大部分城市在 PHP 法式中以 if 或 for, while 来掌握它们的显示形态,固然模版看起来简约多了,但只需一换了显示体例分歧的模版, PHP 法式必将要再改一次!
在 Smarty 中,一切以变量为主,一切的出现逻辑都让模版自行掌握。由于 Smarty 会有本人的模版言语,所以不论是区块是不是要显示仍是要反复,都是用 Smarty 的模版语法 (if, foreach, section) 搭配变量内容作出现。如许一来感到上好象模版变得有点庞杂,但优点是只需计划妥当, PHP 法式一行都不用改。
由下面的申明,咱们可以晓得利用Smarty 要把握一个准绳:将法式使用逻辑与网页出现逻辑明白地分别。就是说 PHP 法式里不要有太多的 HTML 码。法式中只需决意好那些变量要塞到模版里,让模版本人决意该若何出现这些变量 (乃至不呈现也行) 。
Smarty的基本
装置Smarty
起首,咱们先决意法式放置的地位。
Windows下能够会相似如许的地位:「 d:\appserv\web\demo\ 」。
Linux下能够会相似如许的地位:「 /home/jaceju/public_html/ 」。
到Smarty的官方网站下载最新的Smarty套件:http://smarty.php.net。
解开 Smarty 2.6.0 后,会看到良多档案,个中有个 libs 材料夹。在 libs 中应当会有 3 个 class.php n + 1 个 debug.tpl + 1 个 plugin 材料夹 + 1 个 core 材料夹。然后直接将 libs 复制到您的法式主材料夹下,再改名为 class 就能够了。就如许?没错!这类装置法对照复杂,合适普通没有本人主机的利用者。
至于 Smarty 官方手册中为何要引见一些对照庞杂的装置体例呢?根基上按照官方的体例装置,可以只在主机装置一次,然后供应给该主机下一切设计者开辟分歧法式时直接援用,而不会反复装置太多的 Smarty 复本。而笔者所供应的体例则是合适要把法式带过去移曩昔的法式开辟者利用,如许不必懊恼主机有无装置 Smarty 。
法式的材料夹设定
以笔者在Windows装置Appserv为例,法式的主材料夹是「d:\appserv\web\demo\」。装置好Smarty后,咱们在主材料夹下再创立如许的材料夹:
在 Linux 底下,请记得将 templates_c 的权限变动为 777 。Windows 下则将其只读作废。
第一个用Smarty写的小法式
咱们先设定 Smarty 的途径,请将以下这个档案定名为 main.php ,并放置到主材料夹下:
main.php:
<?php
include "class/Smarty.class.php";
define('__SITE_ROOT', 'd:/appserv/web/demo'); // 最初没有斜线
$tpl = new Smarty();
$tpl->template_dir = __SITE_ROOT . "/templates/";
$tpl->compile_dir = __SITE_ROOT . "/templates_c/";
$tpl->config_dir = __SITE_ROOT . "/configs/";
$tpl->cache_dir = __SITE_ROOT . "/cache/";
$tpl->left_delimiter = '<{';
$tpl->right_delimiter = '}>';
?>
照下面体例设定的意图在于,法式假如要移植到其它中央,只需改 __SITE_ROOT 就能够啦。 (这里是参考 XOOPS 的 )
Smarty 的模版途径设定好后,法式会按照这个途径来抓一切模版的绝对地位 (典范中是 'd:/appserv/web/demo/templates/' ) 。然后咱们用 display() 这个 Smarty 办法来显示咱们的模版。
接上去咱们在 templates 材料夹下放置一个 test.htm:(扩大名叫甚么都无所谓,但便于视觉设计师开辟,笔者都仍是以 .htm 为主。)
templates/test.htm:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5">
<title><{$title}></title>
</head>
<body>
<{$content}>
</body>
</html>
如今咱们要将下面的模版显示出来,并将网页题目 ($title) 与内容 ($content) 改换,请将以下档案内容定名为 test.php ,并放置在主材料夹下:
test.php:
<?php
require "main.php";
$tpl->assign("title", "测试用的网页题目");
$tpl->assign("content", "测试用的网页内容");
// 下面两行也能够用这行取代
// $tpl->assign(array("title" => "测试用的网页题目", "content" => "测试用的网页内容"));
$tpl->display('test.htm');
?>
请翻开阅读器,输出 http://localhost/demo/test.php 碰运气(依您的情况决意网址),应当会看到以下的画面:
再到 templates_c 底下,咱们会看到一个奇异的材料夹 (%%179) ,再点选下去也是一个奇异的材料夹 (%%1798044067) ,而个中有一个档案:
templates_c/%%179/%%1798044067/test.htm.php:
<?php /* Smarty version 2.6.0, created on 2003-12-15 22:19:45 compiled from test.htm */ ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5">
<title><?php echo $this->_tpl_vars['title']; ?></title>
</head>
<body>
<?php echo $this->_tpl_vars['content']; ?>
</body>
</html>
没错,这就是 Smarty 编译过的档案。它将咱们在模版中的变量转换成了 PHP 的语法来履行,下次再读取一样的内容时, Smarty 就会直接抓取这个档案来履行了。
最初咱们收拾整顿一下全部 Smarty 法式撰写步调:
Step 1. 加载 Smarty 模版引擎。
Step 2. 创立 Smarty 对象。
Step 3. 设定 Smarty 对象的参数。
Step 4. 在法式中处置变量后,再用 Smarty 的 assign 办法将变量置入模版里。
Step 5. 使用 Smarty 的 display 办法将网页秀出。
若何布置你的法式架构
下面咱们看到除 Smarty 所需求的材料夹外 (class 、 configs 、 templates 、 templates_c) ,还有两个材料夹: includes 、 modules 。其实这是笔者仿照 XOOPS 的架构所创立出来的,由于 XOOPS 是笔者所接触到的法式中,多数利用 Smarty 模版引擎的架站法式。所谓西瓜偎大边,笔者如许的法式架构虽没有 XOOPS 的百分之一强,但最少给人看时还有 XOOPS 撑腰。
includes 这个材料夹次要是用来放置一些 function 、 sql n,如许在 main.php 就能够将它们引入了,以下:
main.php:
<?php
include "class/Smarty.class.php";
define('__SITE_ROOT', 'd:/appserv/web/demo'); // 最初没有斜线
// 以 main.php 的地位为基准
require_once "includes/functions.php";
require_once "includes/include.php";
$tpl = new Smarty();
$tpl->template_dir = __SITE_ROOT . "/templates/";
$tpl->compile_dir = __SITE_ROOT . "/templates_c/";
$tpl->config_dir = __SITE_ROOT . "/configs/";
$tpl->cache_dir = __SITE_ROOT . "/cache/";
$tpl->left_delimiter = '<{';
$tpl->right_delimiter = '}>';
?>
modules 这个材料夹则是用来放置法式模块的,如斯一来便不会把法式丢失掉处都是,全体架构了如指掌。
下面咱们也提到 main.php ,这是全部法式的次要中心,不管是常数界说、内部法式加载、同享变量创立等,都是在这里入手下手的。所以以后的模块都只需将这个档案包括出去就能够啦。因而在法式流程计划时代,就必需好好构想 main.php 中应当要放那些器材;固然使用 include 或 require 指令,把每一个环节清晰分别是再好不外了。
在上节提到的 Smarty 法式 5 步调, main.php 就会帮咱们先将前 3 个步调做好,前面的模块法式只需做前面两个步调就能够了。
从变量入手下手
若何利用变量
从上一章典范中,咱们可以清晰地看到咱们使用 <{ 及 }> 这两个标示符号将变量包起来。预设的标示符号为 { 及 } ,但为了中文冲码及 Javascript 的关系,因而笔者仍是仿照 XOOPS ,将标示符号换失落。变量的定名体例和 PHP 的变量定名体例是如出一辙的,后面也有个 $ 字号 (这和普通的模版引擎分歧)。标示符号就有点像是 PHP 中的 <?php 及 ?> (现实上它们切实其实会被交换成这个) ,所以以下的模版变量写法都是可行的:
1. <{$var}>
2. <{ $var }> <!-- 和变量之间有空格 -->
3. <{$var
}> <!-- 启始的标示符号和停止的标示符号不在统一行 -->
在 Smarty 里,变量预设是全域的,也就是说你只需指定一次就行了。指定两次以上的话,变量内容会以最初指定的为主。就算咱们在主模版中加载了内部的子模版,子模版中一样的变量一样也会被替换,如许咱们就不必再针对子模版再做一次解析的举措。
而在 PHP 法式中,咱们用 Smarty 的 assign 来将变量置放到模版中。 assign 的用法官方手册中已写得良多了,用法就好像上一节的典范所示。不外在反复区块时,咱们就必需将变量做一些四肢举动后,才干将变量 assign 到模版中,这鄙人一章再提。
润色你的变量
下面咱们提到 Smarty 变量出现的面貌是由模版自行决意的,所以 Smarty 供应了很多润色变量的函式。利用的办法以下:
<{变量|润色函式}> <!-- 当润色函式没有参数时 -->
<{变量|润色函式:"参数(非需要,视函式而定)"}> <!-- 当润色函式有参数时 -->
典范以下:
<{$var|nl2br}> <!-- 将变量中的换行字符换成 <br /> -->
<{$var|string_format:"%02d"}> <!-- 将变量格局化 -->
好,那为何要让模版自行决意变量出现的面貌?先看看底下的 HTML ,这是某个购物车结帐的部分画面。
<input name="total" type="hidden" value="21000" />
总金额:21,000 元
普通模版引擎的模版能够会如许写:
<input name="total" type="hidden" value="{total}" />
总金额:{format_total} 元
它们的 PHP 法式中要如许写:
<?php
$total = 21000;
$tpl->assign("total", $total);
$tpl->assign("format_total", number_format($total));
?>
而 Smarty 的模版就能够如许写: (number_format 润色函式请到Smarty 官方网页下载)
<input name="total" type="hidden" value="<{$total}>" />
总金额:<{$total|number_format:""}> 元
Smarty 的 PHP 法式中只需如许写:
<?php
$total = 21000;
$tpl->assign("total", $total);
?>
所以在 Smarty 中咱们只需指定一次变量,剩下的交给模版自行决意便可。如许懂得了吗?这就是让模版自行决意变量出现面貌的优点!
掌握模版的内容
反复的区块
在 Smarty 样板中,咱们要反复一个区块有两种体例: foreach 及 section 。而在法式中咱们则要 assign 一个数组,这个数组中可以包括数组数组。就像上面这个例子:
起首咱们来看 PHP 法式是若何写的:
test2.php:
<?php
require "main.php";
$array1 = array(1 => "苹果", 2 => "菠萝", 3 => "喷鼻蕉", 4 => "芭乐");
$tpl->assign("array1", $array1);
$array2 = array(
array("index1" => "data1-1", "index2" => "data1-2", "index3" => "data1-3"),
array("index1" => "data2-1", "index2" => "data2-2", "index3" => "data2-3"),
array("index1" => "data3-1", "index2" => "data3-2", "index3" => "data3-3"),
array("index1" => "data4-1", "index2" => "data4-2", "index3" => "data4-3"),
array("index1" => "data5-1", "index2" => "data5-2", "index3" => "data5-3"));
$tpl->assign("array2", $array2);
$tpl->display("test2.htm");
?>
而模版的写法以下:
templates/test2.htm:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5">
<title>测试反复区块</title>
</head>
<body>
<pre>
使用 foreach 来出现 array1
<{foreach item=item1 from=$array1}>
<{$item1}>
<{/foreach}>
使用 section 来出现 array1
<{section name=sec1 loop=$array1}>
<{$array1[sec1]}>
<{/section}>
使用 foreach 来出现 array2
<{foreach item=index2 from=$array2}>
<{foreach key=key2 item=item2 from=$index2}>
<{$key2}>: <{$item2}>
<{/foreach}>
<{/foreach}>
使用 section 来出现 array1
<{section name=sec2 loop=$array2}>
index1: <{$array2[sec2].index1}>
index2: <{$array2[sec2].index2}>
index3: <{$array2[sec2].index3}>
<{/section}>
</pre>
</body>
</html>
履行上例后,咱们发明不论是 foreach 或 section 两个履行了局是一样的。那末二者究竟有何分歧呢?
第一个不同很分明,就是foreach 要以巢状处置的体例来出现咱们所 assign 的两层数组变量,而 section 则以「主数组[轮回称号].子数组索引」便可将全部数组出现出来。由此可知, Smarty 在模版中的 foreach 和 PHP 中的 foreach 是一样的;而 section 则是 Smarty 为了处置如上列的数组变量所开展出来的叙说。固然 section 的功效还不只如斯,除下一节所谈到的巢状材料出现外,官方手册中也供应了好几个 section 的使用典范。
不外要注重的是,丢给 section 的数组索引必需是从 0 入手下手的正整数,即 0, 1, 2, 3, ...。假如您的数组索引不是从 0 入手下手的正整数,那末就得改用 foreach 来出现您的材料。您可以参考官方会商区中的此篇会商,个中切磋了 section 和 foreach 的用法。
巢状材料的出现
模版引擎里最使人伤头脑的也许就是巢状材料的出现吧,很多有名的模版引擎城市特地强调这点,不外这对 Smarty 来讲倒是小儿科。
最多见到的巢状材料,就算论Z法式中的会商主题区吧。假定要出现的了局以下:
通知布告区
站务通知布告
文学专区
好书引见
奇文共赏
盘算机专区
硬件核心
软件会商
法式中咱们先以静态材料为例:
test3.php:
<?php
require "main.php";
$forum = array(
array("category_id" => 1, "category_name" => "通知布告区",
"topic" => array(
array("topic_id" => 1, "topic_name" => "站务通知布告")
)
),
array("category_id" => 2, "category_name" => "文学专区",
"topic" => array(
array("topic_id" => 2, "topic_name" => "好书引见"),
array("topic_id" => 3, "topic_name" => "奇文共赏")
)
),
array("category_id" => 3, "category_name" => "盘算机专区",
"topic" => array(
array("topic_id" => 4, "topic_name" => "硬件核心"),
array("topic_id" => 5, "topic_name" => "软件会商")
)
)
);
$tpl->assign("forum", $forum);
$tpl->display("test3.htm");
?>
模版的写法以下:
templates/test3.htm:
<html>
<head>
<title>巢状轮回测试</title>
</head>
<body>
<table width="200" border="0" align="center" cellpadding="3" cellspacing="0">
<{section name=sec1 loop=$forum}>
<tr>
<td colspan="2"><{$forum[sec1].category_name}></td>
</tr>
<{section name=sec2 loop=$forum[sec1].topic}>
<tr>
<td width="25"> </td>
<td width="164"><{$forum[sec1].topic[sec2].topic_name}></td>
</tr>
<{/section}>
<{/section}>
</table>
</body>
</html>
履行的了局就像笔者举的例子一样。
因而呢,在法式中咱们只需想举措把所要反复值一层一层的塞到数组中,再使用 <{第一层数组[轮回1].第二层数组[轮回2].第三层数组[轮回3]. ... .数组索引}> 如许的体例来显示每个巢状轮回中的值。至于用甚么办法呢?下一节利用数据库时咱们再提。
转换数据库中的材料
下面提到若何显示巢状轮回,而实践上使用时咱们的材料多是从数据库中抓掏出来的,所以咱们就得想举措把数据库的材料酿成上述的多重数组的模式。这里笔者用一个 DB 种别来抓取数据库中的材料,您可以自行用您喜好的办法。
咱们只修正 PHP 法式,模版仍是下面谁人 (这就是模版引擎的优点~),个中 $db 这个对象假定已在 main.php 中创立好了,并且抓出来的材料就是下面的例子。
test3.php:
<?php
require "main.php";
// 先创立第一层数组
$category = array();
$db->setSQL($SQL1, 'CATEGORY');
if (!$db->query('CATEGORY')) die($db->error());
// 抓取第一层轮回的材料
while ($item_category = $db->fetchAssoc('CATEGORY'))
{
// 创立第二层数组
$topic = array();
$db->setSQL(sprintf($SQL2, $item_category['category_id']), 'TOPIC');
if (!$db->query('TOPIC')) die($db->error());
// 抓取第二层轮回的材料
while ($item_topic = $db->fetchAssoc('TOPIC'))
{
// 把抓取的数据推入第二层数组中
array_push($topic, $item_topic);
}
// 把第二层数组指定为第一层数组所抓取的数据中的一个成员
$item_category['topic'] = $topic;
// 把第一层数据推入第一层数组中
array_push($category, $item_category);
}
$tpl->assign("forum", $category);
$tpl->display("test3.htm");
?>
在数据库抓取一笔材料后,咱们失掉的是一个包括该笔数据的数组。透过 while 叙说及 array_push 函式,咱们将数据库中的材料一笔一笔塞到数组里。假如您只用到单层轮回,就把第二层轮回 (白色的部分) 去失落便可。
决意内容是不是显示
要决意是不是显示内容,咱们可使用 if 这个语法来做选择。例如假如利用者已登入的话,咱们的模版就能够如许写:
<{if $is_login == true}>
显示利用者操作选单
<{else}>
显示输出帐号和暗码的窗体
<{/if}>
要注重的是,「==」号双方必定要各留最少一个空格符,不然 Smarty 会没法解析。
if 语法普通的使用可以参照官方利用申明,所以笔者在这里就不详加引见了。不外笔者发明了一个风趣的使用:经常会看到法式里要发生如许的一个表格: (数字代表的是材料集的按次)
1 2
3 4
5 6
7 8
这个笔者称之为「横向反复表格」。它的特征和传统的纵向反复分歧,前几节咱们看到的反复表格都是从上而下,一列只要一笔材料。而横向反复表格则可以横向地在一列中发生 n 笔材料后,再换下一列,直到全部轮回停止。要到达如许的功效,最复杂的体例只需求 section 和 if 搭配便可。
咱们来看看上面这个例子:
test4.php:
<?php
require "main.php";
$my_array = array(
array("value" => "0"),
array("value" => "1"),
array("value" => "2"),
array("value" => "3"),
array("value" => "4"),
array("value" => "5"),
array("value" => "6"),
array("value" => "7"),
array("value" => "8"),
array("value" => "9"));
$tpl->assign("my_array", $my_array);
$tpl->display('test4.htm');
?>
模版的写法以下:
templates/test4.htm:
<html>
<head>
<title>横向反复表格测试</title>
</head>
<body>
<table width="500" border="1" cellspacing="0" cellpadding="3">
<tr>
<{section name=sec1 loop=$my_array}>
<td><{$my_array[sec1].value}></td>
<{if $smarty.section.sec1.rownum is div by 2}>
</tr>
<tr>
<{/if}>
<{/section}>
</tr>
</table>
</body>
</html>
重点在于 $smarty.section.sec1.rownum 这个 Smarty 变量,在 section 轮回中这个变量会获得从 1 入手下手的索引值,所以当 rownum 能被 2 除尽时,就输入 </tr><tr> 使表格换列 (注重!是 </tr> 在后面<tr> 在前面) 。因而数字 2 就是咱们在一列中想要出现的材料笔数。列位可以由此去变更其它分歧的出现体例。
加载内部内容
咱们可以在模版内加载 PHP 法式代码或是另外一个子模版,分离是利用 include_php 及 include 这两个 Smarty 模版语法; include_php 笔者较罕用,利用体例可以查询官方手册,这里不再叙说。
在利用 include 时,咱们可以事后加载子模版,或是静态加载子模版。事后加载凡是利用在有配合的文件标头及版权宣布;而静态加载则可以用在一致的框架页,而进一步到达如 Winamp 般可换 Skin 。固然这两种咱们也能够混用,视情况而定。
咱们来看看上面这个例子:
test5.php:
<?php
require "main.php";
$tpl->assign("title", "Include 测试");
$tpl->assign("content", "这是模版 2 中的变量");
$tpl->assign("dyn_page", "test5_3.htm");
$tpl->display('test5_1.htm');
?>
模版 1 的写法以下:
templates/test5_1.htm:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5">
<title><{$title}></title>
</head>
<body>
<{include file="test5_2.htm"}><br />
<{include file=$dyn_page}>
<{include file="test5_4.htm" custom_var="自订变量的内容"}>
</body>
</html>
模版 2 的写法以下:
templates/test5_2.htm:
<{$content}>
模版 3 的写法以下:
templates/test5_3.htm:
这是模版 3 的内容
模版 4 的写法以下:
templates/test5_4.htm:
<{$custom_var}>
这里注重几个重点:1. 模版的地位都是以先前界说的 template_dir 为基准;2. 一切 include 出去的子模版中,其变量也会被解译。;3. include 中可以用「变量称号=变量内容」来指定引含出去的模版中所包括的变量,好像下面模版 4 的做法。 可以在书上很方便地做标记,及时记下自己的心得体会。 |
|