把 {list}、{if}、{each}、{include}、过滤器、分类循环和可用函数一次说全,含可直接复制的写法。
前台所有页面都是 application/template/模板名/pc/*.html。后台「模板设置」切换模板,改的就是模板名。
每个模板目录里固定的东西有三样:pc/ 放页面与片段、public/pc/ 放 css/js/img、
info.php 声明模板名与广告位、set.php 声明可调参数(首页模块顺序、开关、主色)。
模板第一次访问时编译成 php 存进 application/cache/,之后按源文件的修改时间自动重编译,
改完 .html 直接刷新页面就生效,不用清缓存。缓存目录不可写只会变慢,不会报错。
随包四套模板,首页、列表页、详情页的布局各不相同,不是同一套页面换配色,共用的是同一套标签、函数与变量:
laoli 资源下载站风(首页特效画布 + 卡片陈列 + 详情页左右三栏,5 个广告位)、
jian 极简导航风(顶部横向频道条 + 密集表格榜单 + 一行一类的分类目录,详情页也是一行一字段,零图片零图标,4 个广告位)、
hei 极夜终端风(频道轨道 + 各频道收录数状态条 + 首页双列卡片流,详情页主内容与侧栏两栏并排 + 等宽数字,配色全走 CSS 变量,4 个广告位)、
zazhi 纸间杂志风(居中大字刊头 + 期号行 + 发丝双线 + 频道横排,首页「本期要览」导语区 + 正文边栏双栏,列表页两栏摘要流,详情页通栏大标题带题记,宋体标题配纸色底,4 个广告位)。
四套的自适应断点都是 1024 / 768 / 560 / 400。后台「模板设置」点卡片切换,数据与子系统不用动;
每套各自带一份 pc/ 根目录的公共片段(含 sub_unlock.html 积分解锁)与样式表,新增一套就是复制目录改 info.php、set.php 和样式脚本。
读参数用 {:cmspc('键名')},后台「模板设置」里保存的同名键会加 tpl_ 前缀写进配置表并覆盖 set.php 的默认值;
开关类参数配合条件标签用,例:{if cmspc('hero_kg') eq 1}…{/if}。
{$title} —— 输出路由传给模板的变量。裸变量名必须带 $,写成 {title} 是不认的。{$v.name} 或 {v.name} —— 点语法取数组元素,编译成 isset 保护后的取值,取不到输出空字符串,不会报 Notice。
点可以连着写:{$user.avatar.url}。{:h(guojiz('title'))} —— {:…} 里写一句 php 表达式,结果直接 echo。函数调用、拼地址、判断都靠它。h() 转义,只有加 |raw 才原样吐 HTML。正文、广告代码、统计代码这三类才需要 |raw。写法 {v.addtime|date=Y-m-d H:i}。竖号后面的名字如果不是内置过滤器,会当成 php 函数调用,
所以 {v.title|mb_substr=0,6} 这类系统函数也能直接用。
| 过滤器 | 作用 | 写法 |
|---|---|---|
| raw | 不加 h() 转义,原样输出 HTML | 正文、广告位、统计代码这类本来就是 HTML 的用它 |
| cut=值 | 按字数截断,默认 20,中文不会截半 | 写成 cut=…,例 {v.title|cut=10} |
| date=值 | 时间戳格式化,默认 Y-m-d | 写成 date=…,例 {v.title|date=10} |
| time | 转成「3 分钟前」这类相对时间 | 写成 time,例 {v.title|time} |
| num | 强转整数 | 写成 num,例 {v.title|num} |
| count | 数组元素个数 | 写成 count,例 {v.title|count} |
| html | strip_tags 去掉所有标签 | 写成 html,例 {v.title|html} |
| upper | 转大写 | 写成 upper,例 {v.title|upper} |
| lower | 转小写 | 写成 lower,例 {v.title|lower} |
| json | 数组转 JSON 文本 | 写成 json,例 {v.title|json} |
| urlencode | URL 编码,拼查询串用 | 写成 urlencode,例 {v.title|urlencode} |
| url | uploads 里的文件转成可访问地址 | 写成 url,例 {v.title|url} |
| default=值 | 值为空时给一个默认值 | 写成 default=…,例 {v.title|default=10} |
串联示例:{v.intro|html|cut=30}(先去标签再截断)。
{list cms open=1 cat=$sort order="view desc" num=12 page=$page as v key=k}
<a href="{:h(arcurl('cms',$v['id']))}">{v.name|cut=30}</a>
{v.addtime|date=Y-m-d} 浏览 {v.view|num} 第 {v.i} 条
{empty}<div class="w-empty">这一分类还没有内容</div>{/empty}
{/list}
{page}
第一个不带等号的词是「数据源」,三种写法都行:子系统标识(cms、html、doc…)、
不带前缀的表名(content_cms)、或一个 php 变量($list)。
子系统标识就是它的表名,所以后台新建一个子系统,{list 新标识 open=1} 立刻能用,模板一行都不用改。
| 参数 | 作用 |
|---|---|
数据源(第一个不带等号的词) | 子系统标识(cms/doc/…)、不带前缀的表名(content_cms)或一个 $变量,必填 |
as=v | 循环变量名,默认 v,{v.title} 里的 v 就是它;嵌套循环每层换一个别名 |
key=k | 键名变量,默认 k,配合 {v.k} 用;as/key 也能写成不带等号:as v |
num=10 | 取几条,默认 10;limit 是它的别名 |
order=… | 排序,预设词或「列名 方向」,见下一节;默认 id desc |
page=$page | 传页码即启用偏移量,配套 {page} 出分页条;不写就一次取完 |
cat=5 / sort=5 / sortid=5 | 按分类取,三个是同义词,会自动把子分类的内容一起取 |
id=8 | 只取这一条 |
not=8 / notid=8 | 排除这一条,相关推荐里甩掉当前文章 |
in=1,2,3 | 只取这几个 ID |
where=status=1,uid=2 | 一次塞多个「列=值」,等价于分开写 |
| 条件写法 | 含义 |
|---|---|
open=1 / show=1 / status=1 | 只取已审核上架的(status 列) |
tid=0 / pid=0 | 按 parent_id 取,分类列表用 tid=0 拿一级 |
sid=5 | 按 sort_id 取,等于直接指定分类 |
tui=1 / top=1 | 精选、置顶;论坛表里叫 is_essence / is_top 会自动认别名 |
today=1 / day=1 / month=1 / mid=1 | 时间窗:今天或本月入库的,认 addtime / time / create_time 任一列 |
dai=1 | 待审(status=0),不用自己记 0 和 1 谁是谁 |
keyword=词 / ks=词 / q=词 | 在字段配置里勾了「参与搜索」的列上 LIKE |
like=词 | 只在标题列上 LIKE(要数据源写的是子系统标识,纯表名不认) |
notid=8 / not=8 | 排除某一条,做相关推荐时甩掉自己 |
in=1,2,3 | 只取这几条 |
ids=1,2,3 | 不要这几条(NOT IN) |
列名_min=1 / 列名_max=9 | 数值上下限,例如 in_hits_min=1 滤掉没统计过的行 |
任意真实列名=值 | 直接等值匹配;值写成数组就是 IN;表里没有这一列会被静默忽略 |
这些条件之外,任何「真实列名=值」都会直接拼进 WHERE;列不存在时这一条被丢弃,不报错、不过滤, 所以「明明写了却没生效」先去后台字段配置里确认列名有没有拼错。
order= 可以写预设词,也可以写「列名 方向」,多个用逗号分隔。预设词编译时先查表里有没有这一列,
论坛这类列名不同的表会自动认别名(view → views、addtime → create_time),都没有的那段丢掉。
| 预设词 | 实际排序 | 说明 |
|---|---|---|
| new | addtime desc,id desc', /* 最新 */ | 最新 |
| hot | view desc,id desc', /* 热门 */ | 热门 |
| rand | rand', /* 随机 */ | 随机 |
| best | tui desc,view desc,id desc',/* 精选 */ | 精选 |
| top | top desc,id desc', /* 置顶优先 */ | 置顶优先 |
| like | likes desc,id desc', /* 点赞最多 */ | 点赞最多 |
| star | dj desc,view desc,id desc', /* 星级最高 */ | 星级最高 |
| fav | favorite_count desc,view desc,id desc', /* 收藏最多 */ | 收藏最多 |
| score | star desc,dj desc,score desc,view desc,id desc', /* 评分最高,各子系统这一列叫法不一,表里没有的那段自动丢掉 */ | 评分最高,各子系统这一列叫法不一,表里没有的那段自动丢掉 |
| day | day7 desc,view desc,id desc', /* 今日浏览最多(配合 day_time_min=今天 才是今日榜) */ | 今日浏览最多(配合 day_time_min=今天 才是今日榜) |
| in | in_hits desc', /* 点入最多(只有开了本站跳转的站点表里有这列) */ | 点入最多(只有开了本站跳转的站点表里有这列) |
| out | out_hits desc', /* 点出最多(同上) */ | 点出最多(同上) |
例:{list cms open=1 order="top desc,sort asc,id desc" num=9}。
{each $fav_rows as r}
<a href="{:h(arcurl($r['sys'],$r['id']))}">{r.title|cut=24}</a> 第 {r.i} 条
{empty}还没有收藏过内容{/empty}
{/each}
路由直接传给模板的数组(收藏列表、跨表拼出来的榜单)用 {each};
传进来的是分页对象时,{page} 照样能出分页条,还会多一个 last_page 键。
{if v.top eq 1}<span class="w-badge">置顶</span>{elseif v.tui eq 1}精选{else}普通{/if}
{if $sort gt 0}当前分类:{$sortname}{/if}
{:form_field()}{:form_trap()}
比较词只在这两个标签里转换:eq = 、neq != 、gt > 、egt >= 、
lt < 、elt <= 、heq === 、nheq !==。
注意:这些词只在 {if}/{elseif} 里转换,写在 {:…} 里不生效,
那里请直接写 php 的 !==、>。
点语法在条件里同样可用:{if v.top eq 1}、{if count(sortlist($sys,$tp['id'])) gt 0}。
{else} 与 {else /} 两种写法都认。
{include head} 引入 pc/head.html,和当前页共享变量;片段可以放子目录:{include daohang/card}。{include user/peer_list} 同理,用户中心的片段在 pc/user/ 下。{include @plugin/插件目录名},解析到 application/plugin/插件/pc/名.html。pc/sub_unlock.html(积分解锁区块,laoli、jian、hei、zazhi 各有一份,类名前缀不同);
新复制一套模板时忘了它,后台扣积分照扣,前台却看不到解锁入口。页面顶部自己放了「直达」按钮的,在引它之前写 {php $ul_nodown=1;},片段里的解锁下载地址那条就不出,隐藏内容那条照出。{page} 输出上一条带 page= 的 {list} 的分页条,地址自己带 ?page=N。{php $a=1} 塞一小段 php(给片段准备数组、算个计数),里面不能再出现右花括号,多行 php 请拆成函数调用。分类都存在同一张 sort 表里,按 sys 区分,parent_id=0 是一级;
内容表用 sort_id 挂到分类上。取分类有三种姿势,按页面要的效果选。
{list category sys=$sys tid=0 order="sort asc,id asc" num=50 as ct}
<a href="{:h(sorturl($sys,$ct['id']))}">{ct.name}</a>
{/list}
同一件事也能写成 php:{php $tops = sortlist($sys);} 然后 {each $tops as c}。
外层取一级,内层用 tid=$tp.id 取它的二级。每层必须起不同的 as 别名,
判空用 sortlist() 再数一遍,比在内层套 {empty} 稳。
{list category sys=$sys tid=0 order="sort asc,id asc" num=50 as tp}
<div class="cat">
<h3><a href="{:h(sorturl($sys,$tp['id']))}">{tp.name}</a></h3>
{if count(sortlist($sys,$tp['id'])) gt 0}
{list category tid=$tp.id sys=$sys status=1 order="sort asc,id asc" num=20 as sc}
<a href="{:h(sorturl($sys,$sc['id']))}">{sc.name}</a>
{/list}
{/if}
{list $sys open=1 cat=$tp.id order="sort asc,id desc" num=8 as cs}
<a href="{:h(arcurl($sys,$cs['id']))}">{cs.title|cut=20}</a>
{/list}
</div>
{/list}
不想嵌套就别嵌套:cat=一级ID 会自动把这一级下面所有子分类的内容一起取出来,
这是最常用的写法,列表页顶部的「本页共 N 条」也是这么统计的。
{* 只要一个列表,把整棵子树的内容混在一起按时间排 *}{list $sys open=1 cat=$sort order='new' num=$per page=$page as v}
<a href="{:h(arcurl($sys,$v['id']))}">{v.title|cut=24}</a>
{/list}
{page}
cat= 换成 tid= 就变成「只取直接挂在这一级下的内容」,两者的区别就在子分类的内容要不要混进来。
分页统计条数用的 funnum($sys,['open'=>1],['cat'=>$sort]) 也是同一套规则。
相关函数:sortlist($sys,$tid=0) 取某级的子分类数组、sort_children($sys,$id)、
sortname($sys,$id) 直接拿名字、func('category',$id) 拿一整行分类。
下面按源码里的小节顺序列出 application/inc/fun.php 的全部函数,模板里最常碰的是取数据、地址、字段和在线工具四组;
最后两组 按字段配置取值、摘要·地址与详情区块 来自 application/inc/common.php,
同样是模板在调的函数,只是和路由放在同一个文件里。
| 函数 | 作用 |
|---|---|
h($v) | HTML 转义,模板里所有默认输出都走它 |
get($k,$d='') | 取 GPC 参数 |
post($k,$d='') | 取 POST 参数,字符串自动 trim |
gpc($k,$d='') | 取全部请求参数(含 GET/POST) |
cookie($k,$v=null,$exp=0) | cookie 读写:cookie('sn') 读,cookie('sn','x',3600) 写 |
siteurl($path='') | 站点根地址:后台「站点网址」→ config.php 的 url → 按当前请求自动推导,保证不为空 |
url($path='') | siteurl 的短别名,模板里写 url('xxx') 也能拿到站点绝对地址 |
tpl($p='') | 模板资源地址:tpl($p) 拼出本模板 public/pc 下的文件地址 |
upurl($p) | 上传文件地址 |
cut($str,$len=20,$dot='…') | 中文安全截断 |
time_ago($ts) | 时间戳转「3 分钟前」这类相对时间,空值返回 — |
num_ago($n) | 数字缩写:12800 → 1.28万 |
size_fnum($b) | 字节数转可读大小:1536 → 1.50 KB |
| 函数 | 作用 |
|---|---|
config($k=null,$d='') | 数据库配置(application/config.php) |
guojiz($k=null,$d='') | 站点设置:guojiz('title')。不传参数返回全部 |
cmspc($k=null,$d='') | 模板设置:cmspc('ys1'),站点设置里 tpl_ 前缀的键可覆盖模板默认值 |
cmsinfo($k=null,$d='') | 模板信息文件(名称/作者/版本) |
tpl_css() | 把模板配色生成 CSS 变量 |
| 函数 | 作用 |
|---|---|
seo_set($k,$v) | 路由或页面自己设置当前页的 title / keywords / description |
seo_title() | 当前页 seo 标题:页面标题在前,站点名在后 |
seo_keywords() | 当前页 seo 关键词,页面没设就回落站点设置 |
seo_description() | 当前页 seo 描述,页面没设就回落站点设置 |
| 函数 | 作用 |
|---|---|
sys_all($force=false) | 全部子系统配置(sys 标识与 url 别名都能取到) |
sys_get($sys) | 子系统配置 |
sys_name($sys) | 子系统中文名,查不到就原样返回标识 |
sys_builtin($sys=null) | 内置功能占用的子系统标识:程序自带页面与后台菜单,不在「子系统管理」里当栏目列出来 |
sys_own($sys=null) | 数据表和页面都由程序自带的子系统(论坛):在子系统管理里能改名字、地址、开关和每页条数, 但没有字段配置,内容也不走通用内容页,走它自己的菜单。 / |
sys_on($sys) | 子系统开没开。sys_all() 只缓存 status=1 的行,分不出「登记过但停用」和「压根没登记」, 所以这里直接查库:停用返回 false,没登记过按 true 算(老库升级前后的行为要一致)。 / |
fields($sys,$force=false) | 子系统字段配置 |
field($sys,$field) | 取单个字段的配置行,没有该字段返回空数组 |
field_label($sys,$field,$d='') | 字段标签 |
table_of($src) | 表名解析:category/sort → 分类表;nav/user/… → 同名表;子系统标识 → 内容表 |
columns($table) | 表的列清单 |
| 函数 | 作用 |
|---|---|
funa($src,$arg=[],$order='iddesc',$limit=10,$page=0) | 通用列表:funa('rj', array('open'=>1), 'id desc', 10, 1) @param string $src 子系统标识 / 表标识(category、nav、html…) @param array $arg 条件数组,键就是表里的列名,数组值自动转 IN @param string $order 排序,如 id desc / view desc / rand @param int $limit 每页条数 @param int $page 页码;传 0 只返回数组,传 >=1 返回可 ->render() 的分页对象 / |
cond_of($src,$arg=[]) | 条件解析:把 funa 的 $arg 编译成 where + 绑定参数 返回 ['table','cols','where'=>[...],'bind'=>[...]] / |
funb($src,$arg=[],$sortid=0,$order='iddesc',$limit=10,$page=0) | 按分类取列表:funb('html', array('open'=>1), $v['id'], 'id desc', 8, 1) 自动带上该分类的子分类 / |
func($src,$id) | 单条:func('html', $id) |
funone($src,$arg=[],$order='iddesc') | 按条件取单条:funone('html', array('id'=>1)) |
funnum($src,$arg=[]) | 条数:funnum('html', array('open'=>1)) |
funtj($src,$what='all') | 统计:每个子系统同一句函数,表里缺哪一列就自动退成能算的那个,不报错。 funtj('html','all') 总数量(含待审的) funtj('html','open') 已收录数量(站点数、软件数…) funtj('html','wait') 待审数量 funtj('html','today') 今天入库数量 funtj('html','month') 这个月入库数量 funtj('html','cat') 分类数量 模板里这样用:{:funtj('html','today')} / |
key_col($cols) | 表的主键列:多数表是 id,会员表是 uid,收藏一类的可能是 item_id |
time_col($cols) | 这张表用哪个列记入库时间(新老表列名不一样,认不出来就不按时间筛) |
order_preset($order) | 排序预设:模板里写 order=hot / new / rand / best 就够了,不用记列名。 表里没有对应列时 order_sql 会把这些丢掉,最后退回主键倒序,不会报错。 / |
order_alias($col,$cols) | 同一层意思的列各张表叫法不同(论坛用 views/create_time/is_top),排序时按别名退一步认 |
order_sql($order,$cols) | 排序白名单 |
| 函数 | 作用 |
|---|---|
sortlist($sys='',$tid=0) | 分类列表(含子分类) |
sortname($sys,$id) | 分类名 |
sort_children($sys,$id) | 子分类 ID 列表 |
sorturl($sys,$sort=0) | 分类地址 |
arcurl($sys,$id) | 内容地址 |
listurl($sys,$sort=0,$order='') | 列表页地址(可以带排序):/频道/ 是版式完全不同的频道首页,全部内容的列表页是 /频道/page-1/, 分类列表页才是 /频道/分类ID/。排序短名在这里写成 ?order=out 这种,带下划线的列名用短名才不会串。 / |
sys_url($sys) | 子系统 url 别名 |
rankurl($sys='',$by='',$page=0) | 排行榜地址:不带子系统就是全站聚合榜,带了就是这一个子系统自己的榜。 榜型用旧站那套短名(view/day/month/new/in/out/like/fav/star/tui/hot/rand)。 / |
pageurl($page='{page}') | 分页地址 pageurl() → 模板用的地址样式(含 {page} 占位) pageurl(3) → 第 3 页的真实地址 带查询串(搜索词、筛选条件)时自动保留,用 ?page=N 的形式 / |
| 函数 | 作用 |
|---|---|
ad_slots($dir='') | 这套模板自带的广告位:读模板 info.php 里的 ads(位置标识 => 位置名称)。 位置由模板自己声明,程序不内置任何位置:换一套模板就是另一套位置。 / |
ad_on($slot) | 广告位开关:模板设置里可以逐个位置关掉,键名 ad_<位置标识>,默认开着 |
ad($id) | 广告位:ad('top') 返回当前模板这个位置全部启用广告的 html;模板没声明这个位置就不出东西 |
nav($tid=0) | 导航:nav() 返回顶级导航及其子项 |
nav_url($u) | 导航链接地址:外部网址原样,站内路径补上站点根 |
nav_menu($rows=null) | 顶部「更多」下拉:直接吃后台「导航菜单」里的数据,有子项的渲染成子下拉 模板里一句 {:nav_menu()} 就出全部,导航表为空时返回空字符串 / |
links($limit=30) | 友情链接 |
| 函数 | 作用 |
|---|---|
home_list() | 首页三栏模块清单:模板 set.php 的 home_modules 提供样式,home_order 决定顺序 后台可用站点设置里的 tpl_home_order 覆盖顺序;没排到但开关开着的子系统追加到末尾 / |
home_modules() | 首页各子系统三栏模块 html(模板里一句 {:home_modules()} 就按后台顺序输出) |
home_side() | 左侧悬浮锚点里跟随首页模块顺序的那一段 |
dingyi($sn=0,$d=0) | 站群标识(单站固定返回默认值) |
myuser($k=null,$d='') | 当前登录会员:myuser() 取整行,myuser('nickname') 取某个字段 |
islogin() | 前台是否已登录会员(后台登录不算) |
isadmin() | 是否管理员(前台判断) |
json_get($v,$d=[]) | JSON 读取 |
imgs($v,$limit=0) | 图片列表字段(截图/多图) |
tags($v,$sys='',$sep='') | 标签 |
pv_track() | 访问统计:每渲染一个前台页面算一次 PV,同一 IP 当天第一次算 UV。 数据存在 visit 表(day/pv/uv/ips),后台「数据统计」用它画柱状图。 / |
report_mail() | 联系/举报邮箱:后台没填邮箱时用 QQ 号拼 qq.com |
out_domain($url) | 外链的域名:out_domain('https://www.a.com/x') → www.a.com |
tag_words($sys,$row,$limit=30) | 一条内容的关键词/标签词组(读该子系统所有 tags 类型字段,兼容 gjz/keywords/tags) |
star_html($v,$show_num=true) | 星级显示:0-5 渲染成五颗星(前台列表与详情共用) |
tag_plain($sys,$row,$sep='') | 关键词标签(详情页用的小圆角 chip) |
tag_cloud($sys,$row,$num=20) | 3D 标签云的 a 标签:词不足时用同分类内容标题补齐 |
is_collected($sys,$id,$uid=0) | 是否已收藏(会员) |
collect_num($sys,$id) | 收藏数 |
breadcrumb($sys,$sort=0) | 面包屑 |
| 函数 | 作用 |
|---|---|
tool_type_of($sys,$row) | 在线工具的打开方式(其他子系统返回空串) |
tool_code_plain($row) | 代码类型是不是「纯文本」(兼容旧站的 html / text) |
tool_dir() | 本地工具文件放哪个目录:后台上传、贴代码保存、前台执行都只认这一个目录 |
tool_file_name($raw) | 字段里的写法五花八门(jiami.php、tool/jiami.php、uploads/tool/jiami.php、完整网址、旧站 /public/tool/jiami.php), 一律只取最后的文件名,文件名里的非法字符和不认识的扩展名直接判空,杜绝越出 uploads/tool 目录 / |
tool_file_of($sys,$row) | 这条工具要用哪个本地文件:先看「本地工具文件」,没填再退回旧站留在「工具地址」里的路径 |
tool_file_path($sys,$row) | 本地工具文件的绝对路径;文件不存在或不在这个目录里返回空串 |
tool_local_url($sys,$row) | 本地工具文件的网址:站外 iframe 调用这一份也用得上 |
tool_local($sys,$row) | 本地文件型工具的运行区:php 就 include 出来,html 就整份读出来原样显示。 文件不在的时候不报错,给出该怎么补的说明,和旧站的内页一个意思。 / |
tool_embed($sys,$row) | 内嵌网页型工具的 iframe;zg 是容器高度,di 是把被嵌页面自己的页头顶出去的高度 |
tool_target($sys,$row) | 直达按钮的打开方式:内嵌、本地文件和自有代码都留在本页,跳转链接开新窗口 |
| 函数 | 作用 |
|---|---|
data($src,$where=[],$order='iddesc',$num=10,$page=0) | 取数据({list} 的底层):返回行数组;传了 page 则返回分页对象 |
datacat($src,$cat=0,$where=[],$order='iddesc',$num=10,$page=0) | 按分类取数据({list} 里写 cat=分类ID) |
datacol($src,$field,$arg=[],$limit=30) | 按字段聚合取值分布:datacol('gzh','suoshudiqu',['open'=>1]) 返回 [['value'=>'四川','num'=>3],…],按数量从多到少。字段不在这张表里就返回空数组,模板不会报错。 用于地区、来源这类「不是分类但想筛选」的字段,配合 {list … 字段=$var} 用。 / |
page_bar($page=null,$cls='daishen-pagination') | 分页条 html:{page} 用默认样式,需要换样式时 {:page_bar(null,'sousuo-pagination')} |
application/inc/common.php 里)| 函数 | 作用 |
|---|---|
title_field($sys) | 标题字段(由字段配置决定,旧站多为 name) |
cover_field($sys) | — |
body_field($sys) | — |
title_of($sys,$row) | 模板里按配置取标题/封面/正文,不需要知道每个子系统的字段名 |
cover_of($sys,$row) | — |
body_of($sys,$row) | — |
view_of($sys,$row) | 浏览数和时间:各张表叫法不一样(论坛是 views/create_time),模板里统一用这两个函数取, 免得每套模板各自写 {mi.view} 在新子系统上取到空值。 / |
time_of($sys,$row) | — |
body_html($sys,$row) | 正文输出:字段配了「代码类型=纯文本」时转义并保留换行,富文本按原样输出。 没有正文就回空串,模板自己决定显示介绍。 / |
application/inc/common.php 里)| 函数 | 作用 |
|---|---|
intro_of($sys,$row,$len=60) | 摘要:优先 introduce/description,没有就截正文 |
url_of($sys,$row) | 内容页地址 |
out_of($sys,$row) | 跳转地址:外链字段优先,没有就用内容页 |
near_row($sys,$id,$way='prev') | 上一篇 / 下一篇 |
like_rows($sys,$row,$limit=8) | 相关推荐:同分类优先,不足再补热门 |
views_days() | 七天趋势的列名:day1 是最早一天,day7 是今天 |
views_seven($table,$id,$row,$track=false) | 详情页取七天浏览趋势;$track 为真时顺手把这一笔浏览写进库。 记账规则:同一天只加 day7;跨天先把旧数据整体往前挪,中间断掉的天补 0,今天记 1。 老库没这几列时只返回空,模板里的趋势区块自然就不出。 / |
trend_csv($trend,$key) | 趋势数据给模板用的逗号串(没数据时返回空串,模板据此隐藏区块) |
field_html($sys,$row,$except=[]) | 详情页字段渲染:按字段配置输出「标签:值」列表 |
lock_out_col($sys,$row,$field) | 这条内容开了扣积分又没解锁时,地址类字段不给真地址 |
cell_html($sys,$row,$field) | 列表单元格:按字段配置输出(通用列表模板用),第三个参数可传列名或整行字段配置 |
「在线工具」子系统(标识 gongju)的一条工具有四种打开方式,后台填的「打开方式」存在 tool_type 字段,
模板里别自己比对字符串,用 tool_type_of($sys,$v) 取(旧站导入的 0/1/2 也会认回中文标签)。
内页要显示的三种区块:{:tool_embed($sys,$v)} 出内嵌网页的 iframe(高度取 zg、顶部偏移取 di,自带全屏按钮),
{:tool_local($sys,$v)} 执行 uploads/tool/ 里的本地工具文件(php 就 include、html 就整份输出,
都包在 .tool-local-run 里;文件不在时输出「怎么补」的提示而不是报错),
自有代码直接把正文字段 {:body_html($sys,$v)} 打出来(纯文本会自动转义并保留换行)。
三个函数返回的都是真标签,模板里必须写成 {:…} 或者给变量加 |raw,
写成 {$var} 会被转义成一段文本,工具就跑不起来。
详情页兜底模板 view.html 全程不写死列名,字段由后台「字段配置」驱动:
{list fields sys=$sys in_detail=1 is_title=0 is_cover=0 is_body=0 order="sort asc,id asc" num=40 as fi}
<li><span>{fi.label}</span>{:cell_html($sys,$v,$fi)}</li>
{/list}
于是「新建一个子系统 → 配字段 → 传模板」这条路不用改一行模板代码:tpl_list / tpl_detail
在后台子系统设置里指定版式名,没指定就回落到 lists.html / view.html。
取字段值用 field_html($sys,$row,数组)(输出 li 列表)与 cell_html($sys,$row,$字段行)(输出单个值),
图片/图集字段自动拼 upurl(),链接字段自动带 target=_blank,其余一律转义。
{list} / {each} 的标签头里不能出现尖括号、花括号和换行,属性值里有这些字符会被切断匹配。$v 不会被 as v 顶掉。eq 只认比较词,别写 {if $a = 1};带等号的 php 赋值不是条件。page= 参数:忘了写就没有 {page},也不会报错。order=day 配合 day_time_min=今天零点,只写 order=day 拿到的是七天浏览量榜。