ECMall2.x模板制作入门系列之1(认识ECMall模板)
从ECMall2.0全新架构发布以来,随着版本的不断更新,ECMall已经逐渐走向一个稳定时期,是时候整理一些实用教程了。下面给大家带来一个模板制作入门教程。
申明:本人第一次写教程。可能只能说一些比较浅显的基础知识。条理性可能不是很到位,说得不对的地方欢迎拍砖并指正,目的是希望通过这次教程能让新手们对模板有一个比较系统的认识。
一.ECMall的模板文件在网站中怎么分布的。怎么找到一个页面所对应的模板
theme/ 主题目录
商城模板
theme/mall/ 包含所有商城模板,里面的每个目录即为一套模板
theme/mall/default/ 商城默认模板,里面的html文件是模板文件,theme.info.php主题信息配置
theme/mall/default/styles/ 皮肤目录,里面每一个目录即为一套皮肤
theme/mall/default/styles/default/ 默认皮肤目录,style.info.php为皮肤配置信息,screenshot.jpg主题截图,preview.jpg为主题预览图
店铺模板
theme/store/ 包含所有店铺模板
theme/store/default/ 默认店铺模板
theme/store/default/styles/ 皮肤目录,里面每一个目录即为一套皮肤
theme/store/default/styles/default/ 默认皮肤目录,style.info.php为皮肤配置信息,screenshot.jpg主题截图,preview.jpg为主题预览图
引用:
与模板相关的几个概念
1.主题
严格意义上来讲,大家在论坛里常说的一套模板,在ECMall2中被定义为一个主题。一个主题是一套模板和一套皮肤的组合,这可能跟其他某些开源产品有所区别。一套模板可以对应多套皮肤从而形成多个主题。比如 默认模板+粉红皮肤 = 默认粉红主题,默认模板+淡蓝皮肤 =默认淡蓝主题,这样就能在网站后台(设置->主题设置)看到这两个主题。模板和皮肤的概念我接着往下说。
2.模板、皮肤
模板负责决定页面中都由哪些数据、信息构成。
从网页制作角度来看。模板就是一系列HTML网页文件构成。
皮肤负责决定页面中的数据、信息如何展示给用户。
皮肤就包含图片、层叠样式表CSS、JAVASCRIPT等。
如何找到当前页面对应的模板文件
引用:
强烈建议不要修改默认模板,否则以后升级会很麻烦。如果要修改我们可以新建一套,然后在后台启用新主题
在制作模板前先掌握摸清模板的藏身之处是很得力的,知己知彼百战不殆,废话少说了,动真格的,举例给大家说明。
例一:分析注册页面对应哪些模板文件
通过首页点注册进入注册页面,发现地址栏的地址为(需要关闭伪静态功能):
引用:
http://ecmall.shopex.cn/demo/index.php?app=member&act=register&ret_url=
前面的http://ecmall.shopex.cn/demo/是网站访问的路径这个不用多说,
这里的index.php就是网站根目录那个index.php文件,这个是php程序文件,在ECMall中是系统入口文件,所有前台页面必须通过这个入口进行访问(当然后台也有入口admin/index.php)
我们分析模板要看的是app和act两个参数:这里的是app=member和act=register。
这里的app、act代表什么含义呢?
app是英文单词application的缩写,意思是“应用”,那么这里我们访问的就是一个叫member(意为会员)的应用
act是英文单词action的缩写,意为“行为”,那么这里我们访问的就是member应用的register行为
引用:
插播广告
通常情况下
如果地址栏没有app,那么app默认为default
如果地址栏没有act,那么act默认为index
app是放到app目录下的。进去之后发现有个member.app.php,这个文件就是我们要找的注册页面对应的app文件。
打开member.app.php,文件里面是php程序代码,通过搜索“function register”我们就找到了register act即会员应用的注册行为。
这里function register开始是定义函数的代码,我们需要找到结束位置。我们在这个函数内就能找到这段代码
引用:
$this->display('member.register.html');
这里单引号中间的“member.register.html”就是模板文件名了。
ps:可能同学们很多不是做程序的,如果你很难判断这个function register函数代码哪里是结束,可以借助有折叠功能的编辑器。
现在我们得知了模板文件名。那么这个文件在哪里呢?
有了上头对模板分布的基础认识,可以下结论其实可能性就两个,themes/mall/default(默认商城模板目录)或themes/store/default(默认店铺模板目录)。
到了这一步,其实很简单了。我们可以根据页面的含义来找。这里的注册行为是商城的功能,所有当然在商城模板目录。这样模板位置我们算是找到了,很简单吧
,先喝口茶,休息下再继续。
让我们来看看这个member.register.html的庐山真面目。
打开后我们看到了大部分模板都有的这样的结构
复制内容到剪贴板
代码:
{include file="header.html"}
......
{include file="footer.html"}
首尾都有{include file="xxx"}这样的模板标签,这代表这个模板含有嵌套模板,我们当前的这个模板嵌套了两个模板header.html和footer.html,他们的位置与member.register.html同级目录的。
到目前为止已经教给大家一种比较通用的找模板的方法。通过这种方法你可以应付大部分情况了。
希望大家通过这个教程能对ECMall模板有个全局的认识。强烈建议经常问“这个页面的模板在哪里”的同学认真看看。
二.如何新建一套商城主题。
第一步:复制默认主题
进入theme/mall/目录,找到default目录 复制一个复件,重命名,起一个我们想要的名字“mytheme”
第二步:修改主题配置
修改程序文件需要程序编辑器,这里给大家推荐本人一直使用的editplus编辑器,比较小巧而且灰常靠谱。
放出个可用的地址http://down.cnzz.cn/info/37178.aspx
下载后,需要进行“去BOM”设置,菜单“工具”-->“首选项”,在设置面板设置为“总是删除签名”如下图:
进入刚刚复制的那个文件夹(mytheme)里面,如下图
打开theme.info.php文件
上面这段代码是主题的配置信息,其中
version:主题版本,主题作者自行设定版本号
author:主题作者
description:主题描述。
请自行进行修改,修改好后保存。如果你的版本是UTF-8的需要在保存时用文件菜单里的“另存为”,选择UTF-8编码,这时弹出的提示是否替换,选择“是”。
第三步:修改预览图和缩略图
主题预览图在themes/mall/mytheme/styles/default下
这里我们的新主题只有一套默认皮肤,如果再复制styles目录下的default文件夹,重命名为newstyle,这时我们就得到了由一套模板和两套皮肤组成的两套主题了。这里再次巩固一下上面讲到的ECMall主题的定义。
第四步:启用新主题
进入后台“设置”-->“主题设置”,发现我们新建的主题显示出来了
点击“应用”后。即可切换到我们自己的主题了。
ECMall2.x模板制作入门系列之2(模标签/语板法)
在ECMall模板中,用"{"开头,以"}"结尾就构成一个标签单元,"{"紧接着的单词就是标签名。在标签单元中单词前含"$"(美元符)的为变量名。
资源引用
res标签
- 功能:返回当前模板当前风格目录的url路径
- 实例:{res file=css/ecmall.css}这个标签在模板编译后将变成http://商城域名/themes/default/styles/default,注意末尾没有"/",返回结果会随后台设置的主题变化
lib标签
- 功能:返回javascript库的url路径
- 实例:{lib file=ecmall.js}这个标签在模板编译后将变成http://商城域名/includes/libraries/javascript,注意末尾没有"/",返回结果不会随后台设置的主题变化
url标签
- 功能:url解析器,可根据后台伪静态状态返回相应url等。
- 说明:如果一个链接的目标页面需要伪静态功能,请使用该url标签,只有当后台开启伪静态并在.htaccess文件为目标页面设置了伪静态规则时url标签才能解析为静态url地址。
- 实例:{url app=goods&id=$goods_id}解析后如果伪静态成功则返回"goods/19"
include标签:include 标签用于在当前模板中包含其它模板。当前模板中的变量在被包含的模板中可用。必须指定 file 属性,该属性指明模板资源的位置。实例:
1 |
{ include file= "header.html" } |
2 |
{* body of template goes here *} |
3 |
{ include file= "footer.html" } |
模板变量
1. 模板保留变量
模板预置的一些系统变量,包括
- $smarty.now 当前时刻对应的格林尼治时间戳,可以用{$smarty.now|date}显示当前日期时间,关于date变量调节器请看下文讲解。
- $smarty.get $smarty.post $smarty.cookie $smarty.env $smarty.server $smarty.request $smarty.session同php的$_GET、$_POST、$_COOKIE、$_ENV、$_SEVER、$_REQUEST、$_SESSION变量。非程序人员如果需要了解请参考php相关手册了解。
2. 自定义变量
从php赋值变量。例如在调用该模板的app程序文件中进行赋值
1 |
//在app/default.app.php文件的index方法中$this->display前添加赋值语句 |
2 |
$this ->assign( 'name' , 'Tom' ); //普通变量 |
3 |
$this ->assign( 'user' , array ( |
7 |
$this ->display( 'index.html' ); |
在themes/mall/default/index.html中显示变量
1 |
Hello,{ $name },your age are { $user .age}! |
在模板中赋值变量。assign标签,例在themes/mall/default/index.html中赋值变量
1 |
{assign var = "name" value= "Tom" } |
3.模板上使用语言项
说明:为了满足多语言需求,ECMall采用了语言包机制,除挂件外,在模板、js文件中均使用语言项代替直接显示语言文字。
语言文件:语言文件位于商城根目录下的languages目录下,为当前语言建了一个目录,如果您用的是sc-gbk版本,则会有sc-gbk目录,进去之后就能看到属于前台控制器的全部语言文件了。除common.lang.php属于所有app外,每一个语言文件都只属于一个app(ECMall中称为控制器)。语言文件属于某个控制器而不属于某个模板,同一个模板如果被不同控制器调用将使用不同语言文件进行语言解析。
在默认控制器对应的语言文件default.lang.php添加语言项"test":
3 |
'hot_search' => '热门搜索' , |
5 |
'best_recommended' => '精品推荐' , |
在index.html模板中显示语言项"test"
模板中还支持数组形式语言项,在默认控制器对应的语言文件default.lang.php添加语言项"test_array"
03 |
'hot_search' => '热门搜索' , |
05 |
'best_recommended' => '精品推荐' , |
06 |
'test_array' => array ( |
在index.html模板中显示语言项"test"
1 |
{ $lang .test_array.key1} |
4. 变量调节器
* escape
功能:提供各种编码功能。
参数:可选参数html、url、quotes、input、editor,缺省为html html:分别替换变量中的如下字符& < > "为其html实体代码,用于按原样输出html源代码。
- url:如果该变量用于储存url地址,需要进行url编码
- quotes:在单双引号字符前添加反斜杠
- input:给输入框赋值时使用
- editor:当显示通过文本编辑器录入的内容,需要用此参数
例如php赋值:
1 |
$this ->assign( 'goods_name' , "L'oreal/欧莱雅" . ' "' . " 清润全日保湿乳霜 " . '" ' . "50ml<br /><script>" ); |
2 |
$this ->display( 'index.tpl' ); |
模板
3 |
{ $goods_name |escape: "html" } |
4 |
{ $goods_name |escape: "url" } |
5 |
{ $goods_name |escape: "quotes" } |
6 |
{ $goods_name |escape: "input" } |
7 |
{ $goods_name |escape: "editor" } |
输出结果为
1 |
L'oreal/欧莱雅 "清润全日保湿乳霜" 50ml<br /><script> |
2 |
L'oreal/欧莱雅 "清润全日保湿乳霜" 50ml<br /><script> |
3 |
L'oreal/欧莱雅 "清润全日保湿乳霜" 50ml<br /><script> |
4 |
L%27oreal%2F%E6%AC%A7%E8%8E%B1%E9%9B%85%22%E6%B8%85%E6%B6%A6%E5%85%A8%E6%97%A5%E4%BF |
5 |
%9D%E6%B9%BF%E4%B9%B3%E9%9C%9C%2250ml%3Cbr+%2F%3E%3Cscript%3E |
6 |
L\'oreal/欧莱雅\"清润全日保湿乳霜\"50ml<br /><script> |
7 |
L'oreal/欧莱雅\"清润全日保湿乳霜\"50ml<br /><script> |
8 |
L'oreal/欧莱雅 "清润全日保湿乳霜" 50ml<br /><script> |
* nl2br
功能:将换行符替换成<br />
* default
功能:为变量设置一个默认值,当变量为空或者未分配的时候,将由默认值替代输出
1 |
{ $var | default : "no title" } |
* truncate
功能:字符串截取。从字符串开始处截取某长度的字符。默认会在末尾追加省略号。
* strip_tags
功能:去除<和>标签,包括在<和>之间的任何内容。
1 |
{assign var = "content" value= "<b>文章内容</b>" } |
* price
功能:格式化价格。
1 |
{assign var = "goods_price" value= "123456" } |
输出结果为:¥123,456.00
* date
功能:格式化本地时间和日期。
格式:{$var|date:format}
说明:变量$var必须是格林尼治标准时间,php中gmtime()和模板中$smarty.now得到的都是格林尼治标准时间,参数format可为simple、complete或自定义日期格式,缺省为simple。
2 |
{ $smarty .now| date :complete} |
3 |
{ $smarty .now| date :Y-m-d H:i} |
输出结果为:
* modifier
功能:调用php自定义函数。
格式:{$var|modifier:user_func}
流程控制标签
1. 条件判断(if,elseif,else)
模板中的 if 语句和 php 中的 if 语句一样灵活易用,并增加了几个特性以适宜模板引擎. if 必须于 /if 成对出现. 可以使用 else 和 elseif 子句. 可以使用以下条件修饰词:eq、ne/neq、gt、lt、lte/le、gte/ge、mod、not、==、!=、>、<、<=、>=、%、!使用这些修饰词时必须和变量或常量用空格格开.
多个条件之间用 and、or、&&、|| 连接,实现简单的逻辑运算
03 |
{ elseif $name eq "Wilma" } |
06 |
Welcome, whatever you are. |
10 |
{ if $name eq "Fred" or $name eq "Wilma" } |
15 |
{ if $name == "Fred" || $name == "Wilma" } |
19 |
{* 下面的语法无效,条件修饰符必须由空格跟其他元素分开 *} |
20 |
{ if $name == "Fred" || $name == "Wilma" } |
25 |
{ if ( $amount < 0 or $amount > 1000 ) and $volume >= #minVolAmt#} |
2. 数组遍历(foreach,foreachelse)
foreach 用于处理简单数组(数组中的元素的类型一致)。foreach 必须和 /foreach 成对使用,且必须指定 from 和 item 属性。foreach 可以嵌套,但必须保证嵌套中的 foreach 名称唯一。foreachelse 语句在 from 变量没有值的时候被执行。
from 属性:指定被循环的数组,数组长度决定了循环的次数。item属性:单个循环项目的变量名,在循环内部使用。name 属性为可选属性,可以任意指定(字母、数字和下划线的组合)。
name 属性如果指定,foreach循环体内会自动生成如下变量
- $smarty.foreach.foreach_name.index表示本次循环索引,从0开始递增的整数
- $smarty.foreach.foreach_name.iteration表示本次的循环次数,从1开始递增的整数
- $smarty.foreach.foreach_name.first表示是否是第一次循环
- $smarty.foreach.foreach_name.last表示是否是最后一次循环
- $smarty.foreach.foreach_name.show表示是否有数据
- $smarty.foreach.foreach_name.total表示循环总次数,也可在循环体外使用
1 |
{* 该例将输出数组 $custid 中的所有元素的值 *} |
2 |
{ foreach from= $custid item=curr_id} |
输出结果为:
2 |
$this ->assign( "contacts" , array ( |
3 |
array ( "phone" => "1" , "fax" => "2" , "cell" => "3" ), |
4 |
array ( "phone" => "555-4444" , "fax" => "555-3333" , "cell" => "760-1234" ) |
模板代码:
1 |
{* 键就是数组的下标,请参看关于数组的解释 *} |
3 |
{ foreach name=outer item=contact from= $contacts } |
4 |
{ foreach key=key item=item from= $contact } |
输出结果为:
3 |
{ foreach name=outer item=contact from= $contacts name=my_name} |
4 |
{ foreach key=key item=item from= $contact } |
5 |
{ $key }: { $item }{ if !smarty. foreach .my_name.last}<br />{/ if } |
显示标签
* cycle
cycle 用于轮转使用一组值。该特性使得在表格中交替输出颜色或轮转使用数组中的值变得很容易。
格式:{cycle values="val1,val2,val3..."}
1 |
{ foreach from= $data_list item=data} |
2 |
<tr bgcolor= "{cycle values=" #eeeeee,#d0d0d0 "}" > |
输出结果为:
* html_options
自定义函数 html_options 根据给定的数据创建选项组. 该函数可以指定哪些元素被选定. 要么必须指定 values 和 ouput 属性,要么指定 options 替代。
1 |
$this ->assign( 'cust_ids' , array (1000,1001,1002,1003)); |
2 |
$this ->assign( 'cust_names' , array ( 'Joe Schmoe' , 'Jack Smith' , 'Jane Johnson' , 'Carlie Brown' )); |
3 |
$this ->assign( 'customer_id' , 1001); |
模板代码:
2 |
{html_options values= $cust_ids selected= $customer_id output= $cust_names } |
1 |
$this ->assign( 'cust_options' , array ( |
4 |
1003 => 'Jane Johnson' , |
5 |
1004 => 'Charlie Brown' )); |
6 |
$this ->assign( 'customer_id' , 1001); |
模板代码:
2 |
{html_options options= $cust_options selected= $customer_id } |
实例1和实例2输出结果均为:
2 |
<option value= "1000" >Joe Schmoe</option> |
3 |
<option value= "1001" selected>Jack Smith</option> |
4 |
<option value= "1002" >Jane Johnson</option> |
5 |
<option value= "1003" >Carlie Brown</option> |
* html_radios
自定义函数 html_radios 根据给定的数据创建单选按钮组。该函数可以指定哪个元素被选定。要么必须指定 values 和 ouput 属性,要么指定 options 替代。与html_options不同的是html_radios有一个checked属性。
* html_checkbox
自定义函数 html_checkboxes 根据给定的数据创建复选按钮组。该函数可以指定哪些元素被选定。 要么必须指定 values 和 ouput 属性,要么指定 options 替代.。与html_options不同的是html_checkbox有一个checked属性。
* sprintf
说明: 对变量进行格式化。
格式{sprintf lang=my_lang var1=my_var1 var2=my_var2 ...}
在语言文件添加语言项:
3 |
'query_info' => '页面执行 %0.3f 秒, 查询 %d 次,在线 %d 人' |
模板中显示:
1 |
{sprintf lang=query_info var1=query_time var2=query_count var3=query_user_count} |
输出结果为:
1 |
页面执行 0.160 秒, 查询 3 次,在线 10 人 |
- ECMall2.x模板制作入门系列之2(模板标签/语法)
ECMall2.x模板制作入门系列之2(模板标签/语法) 今天给大家带来一个模板语法的教程.希望能为ECMall模板制作者提供一份参考资料.如有问题.建议和意见,欢迎提出. 在ECMall模板中,用& ...
- STM32入门系列-创建寄存器模板
介绍如何使用 KEIL5 软件创建寄存器模板, 方便之后使用寄存器方式来操作STM32开发板上的LED,让大家创建属于自己的寄存器工程模板. 获取工程模板的基础文件 首先我们在电脑任意位置创建一个文件 ...
- Flask入门系列(转载)
一.入门系列: Flask入门系列(一)–Hello World 项目开发中,经常要写一些小系统来辅助,比如监控系统,配置系统等等.用传统的Java写,太笨重了,连PHP都嫌麻烦.一直在寻找一个轻量级 ...
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
- ABP入门系列(1)——通过模板创建MAP版本项目
ABP入门系列目录--学习Abp框架之实操演练 一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包 ...
- Docker入门系列之三:如何将dockerfile制作好的镜像发布到Docker hub上
这个系列的前两篇文章,我们已经把我们的应用成功地在Docker里通过nginx运行了起来,并且用dockerfile里制作好了一个镜像. Docker入门系列之一:在一个Docker容器里运行指定的w ...
- vue 快速入门 系列 —— 模板
其他章节请看: vue 快速入门 系列 模板 前面提到 vue 中的虚拟 dom 主要做两件事: 提供与真实节点对应的 vNode 新旧 vNode 对比,寻找差异,然后更新视图 ①.vNode 从何 ...
- WPF快速入门系列(7)——深入解析WPF模板
一.引言 模板从字面意思理解是“具有一定规格的样板".在现实生活中,砖块都是方方正正的,那是因为制作砖块的模板是方方正正的,如果我们使模板为圆形的话,则制作出来的砖块就是圆形的,此时我们并不 ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
随机推荐
- 转:oracle ebs po模块一揽子采购协议小结
转自:http://yedward.net/?id=193 oracle ebs po模块一揽子采购协议小结 本文总结oracle ebs采购订单(po)模块一揽子采购协议的相关知识,总结如下: 1. ...
- OpenJDK1.8 安装
1. 安装JDK yum install -y java-1.8.0-openjdk-devel 2. 设置环境变量 /etc/profile文件增加 export JAVA_HOME=/usr/li ...
- (转)常用CSS优化总结——网络性能与语法性能建议
原文地址:http://www.cnblogs.com/dolphinX/p/3508657.html 在前端面试中最常见的问题就是页面优化和缓存(貌似也是页面优化),被问了几次后心虚的不行,平然平时 ...
- flash wmode="window&qu…
引用一段话:opaque和tranparent由于都是无窗口内渲染模式,能很好的实现各层的遮挡,和一般div元素没有太大区别,而window.direct模式在现在看来,是没有任何办法实现被DHTML ...
- 创建本地RPM源之更新系统旧版软件mysql
事情起因 系统版本为Centos6.6 ,因为之前同事没有采用最小化选择性安装,所以系统安装好后自带有mysql5.1的三个安装包: [root@test ~]# rpm -qa | grep mys ...
- 一步一步学NUnit
转载:http://tech.sina.com.cn/s/2009-07-17/1129988785.shtml 单元测试基础知识 单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的.很明 ...
- XMLHttpRequest cannot load的问题解决方法
在chrome中可以用--allow-file-access-from-files 命令来解决这个问题.右键点击chrome的快捷方式选择属性.在目标一栏中添加--allow-file-acces ...
- MVC小系列(十五)【MVC+ZTree实现对树的CURD及拖拽操作】
根据上一讲的可以加载一棵大树,这讲讲下如果操作这颗大树 <link href="../../Scripts/JQuery-zTree/css/zTreeStyle/zTreeStyle ...
- C# 的static与单例模式
C# 的static与单例模式 static是静态对象,在类被第一次使用,或者第一次被实例化时执行 /// <summary> /// 线程安全的单件模式 /// </summary ...
- HOOK函数(二)——全局HOOK
如果钩子函数定义于当前进程相关的线程中,则钩子函数只能处理当前进程的线程的消息,如果要想处理当前正在运行的所有进程的鼠标消息和键盘消息,那么安装钩子函数的代码必须实现在动态链接库中.所以如果想让安装的 ...