ThinkWo 开发文档DOCS v1.0.45
快速开始
文档首页 / 模板开发 / 栏目自定义字段

栏目自定义字段

内置字段不够用时(交期、是否推荐、规格表、按钮文案…),不需要改表、也不需要改程序:在栏目上定义几个字段,内容编辑页就多几个输入框,模板按字段键直接取值。

一、它是什么:一条数据的三个位置

整套机制只有三块,理解了这三块就不会用错:

① 字段定义  →  表 tw_sort_field
   「哪个栏目、有哪些字段、各是什么类型」
   一个栏目可以定义任意多个字段(建议 10 个以内)

② 字段的值  →  表 tw_content 的 meta 列(JSON)
   {"delivery":"7 天","recommend":"1","spec":"尺寸 20×30mm"}

③ 模板取值  →  {$list.字段键} / {$content.字段键}
   程序在取数据时自动把 JSON 展开成字段,模板当普通字段用
和内置字段的关系

内置字段(标题、摘要、正文、价格…)是表里真实存在的列,谁都能用;自定义字段是「存在一个 JSON 列里的键值对」,只对定义了它的栏目生效。两者在模板里的写法完全一样,都是 {$list.xxx}。

二、四步做出一个字段

第 1 步 · 定义字段

后台 → 栏目管理 → 找到目标栏目那一行 → 点「字段」按钮(也可以直接访问 /admin.php/sort/fields?sort_id=栏目ID)。

项怎么填
字段名称中文标签,只影响后台显示,如「交期」
字段键模板里用的变量名,只允许小写字母、数字、下划线,如 delivery。留空会自动生成 cf_ + 拼音
类型单行文本 / 多行文本 / 下拉选择 / 开关
选项只有下拉选择要填,一行一个,如「3 天 / 7 天 / 15 天」
默认值新增内容时预填,可留空

保存后立刻生效,不需要清缓存、不需要改代码。要几个字段就重复几次。

第 2 步 · 填值

内容管理 → 添加 / 编辑该栏目下的内容 → 字段输入框自动出现。切换栏目时字段区实时跟着换。

「扩展」框会消失

栏目一旦定义了自定义字段,内容编辑页原来那个「扩展」文本框就会隐藏,因为两者共用 meta 列。已经写过的纯文本不会被删,只是不再显示——取消全部字段定义后会重新出现。

第 3 步 · 模板取值

{* 列表页 *}
{tw:list sort="products" limit="12" alias="item"}
  <h3>{$item.title}</h3>
  <p>交期:{$item.delivery}</p>
  {if $item.recommend == '1'}<em>推荐</em>{/if}
{/tw:list}

{* 详情页 *}
<p>交期:{$content.delivery}</p>

第 4 步 · 清缓存看效果

静态化开着时要清一次缓存(后台右上角),否则前台还是旧 HTML。开发期建议先把静态化关掉。

三、四种类型:存什么、怎么写

类型后台控件实际存的值模板写法
text 单行输入框 纯文本,超长截断到 500 字 {$list.键}
textarea 多行文本框 带换行的纯文本 {$list.键|nl2br} 才会换行
select 下拉(选项一行一个) 选中的那行文字,不是序号 {if $list.键 == '7 天'}
switch 开关 '1' 开 / '0' 关(字符串) {if $list.键 == '1'}
为什么下拉存文字而不是 1/2/3

存值就是模板里要比对的值,改选项文字时前台判断也跟着改,不用记序号。代价是改了选项文字,已在用的旧内容不会自动变——要么保持文字稳定,要么事后批量改内容。

四、完整例子:给产品加三个字段

目标:产品详情页显示「交期」「是否推荐」「规格说明」三项。

① 定义(后台操作,等价 SQL 如下)

-- 假设栏目 ID = 10
INSERT INTO `tw_sort_field`
  (`sort_id`,`name`,`fkey`,`type`,`options`,`defval`,`sort`,`status`)
VALUES
  (10,'交期',    'delivery',  'select','3 天\n7 天\n15 天','7 天',1,1),
  (10,'是否推荐','recommend', 'switch','','0',  2,1),
  (10,'规格说明','spec',      'textarea','','', 3,1);

② 填值后,meta 列里是这段 JSON

{"delivery":"7 天","recommend":"1","spec":"尺寸 20×30mm\n厚度 5mm\n材质 钕铁硼"}

③ 详情页模板

<div class="spec">
  <h2>产品参数</h2>
  <dl>
    {if $content.delivery}
      <dt>交期</dt><dd>{$content.delivery}</dd>
    {/if}

    <dt>推荐</dt>
    <dd>{if $content.recommend == '1'}是{else /}否{/if}</dd>

    {if $content.spec}
      <dt>规格</dt><dd>{$content.spec|nl2br}</dd>
    {/if}
  </dl>
</div>

④ 列表页带「推荐」角标

{tw:list sort="products" limit="12" alias="item"}
  <a href="{$item.url}" class="card">
    {if $item.recommend == '1'}<span class="tag">推荐</span>{/if}
    <h3>{$item.title}</h3>
    <p>交期 {$item.delivery}</p>
  </a>
{/tw:list}

⑤ 想把所有字段一次性铺出来

{* 注意:必须用 foreach,不能用 volist *}
{foreach name="list.cf" item="val" key="fkey"}
  <li><b>{$fkey}</b>:{$val}</li>
{/foreach}

字段的中文名不在 cf 里(cf 只有键和值)。要中文标签,最省事的做法是在模板里写死一份映射:

{php}
$labels = ['delivery' => '交期', 'recommend' => '推荐', 'spec' => '规格说明'];
{/php}

{foreach name="list.cf" item="val" key="fkey"}
  <li><b>{$labels[$fkey] ?? $fkey}</b>:{$val}</li>
{/foreach}

五、值是怎么被展开的

程序在取列表与详情数据时会解析 meta,规则很简单:

meta 的内容解析结果
合法 JSON 对象,如 {"a":"1"}展开成 $row['a'] = '1',同时保留 $row['cf'] = ['a'=>'1']
纯文本,如 ¥4800原样保留,$row['meta'] 就是这段文字,cf 为空数组
空什么都不加,模板取 {$list.键} 得到空串
两种用法不要混

同一个 meta 列既可能装纯文本也可能装 JSON。判断方法:后台内容编辑页里「扩展」框还在不在——在,说明该栏目没定义字段,{$list.meta} 是原文;不在,说明已定义字段,要改用 {$list.字段键},否则前台会输出一整段 JSON。

六、边界与限制

限制说明 / 应对
字段键不能用系统保留名title、subtitle、summary、content、meta、url、date、lines、cf、sort 等会被拒绝。换一个名字即可
同一栏目内字段键唯一不同栏目可以同名,互不影响
meta 列上限 1000 字所有字段的值合计要控制在这个长度内。字段多、内容长时改用「正文」或单独建栏目存
改字段键 = 老值失联值是按旧键名存的,改键名后旧值还在 JSON 里但模板取不到。要么别改,要么批量更新内容
删字段不删值删掉定义后,JSON 里那段值仍保留;重新用同名键定义即可恢复
遍历必须用 foreach{volist} 的 key 输出的是序号 1、2、3,不是字段键
停用的字段不回填把字段设为停用后,内容表单不再显示它,但已存的值不会丢

七、什么时候该用自定义字段

需求推荐做法
产品要多一个「交期」✅ 自定义字段,最合适
某一类内容要一段长图文用「正文」,别塞字段(会撞 1000 字上限)
全站都要显示公司电话用站点设置,不是字段
首页要维护三张卡片建一个隐藏栏目,一张卡一条内容,字段做卡片上的小按钮
同一个值要在多个栏目共享字段是「栏目私有」的,共享需求改用站点设置或独立栏目
隐藏栏目的用法

把栏目的 status 设为 0,它就不出现在导航和列表里,但仍然能用 {tw:list sort="它的slug"} 取内容。适合首页版块、价格卡、常见问题这类「只给模板取数、不对外当页面」的数据。这类栏目的字段和普通栏目完全一样。

八、排查清单

现象原因
栏目列表里没有「字段」按钮程序版本低于 v1.0.44;或升级时没有执行数据库变更(表 tw_sort_field 不存在)
字段页能打开,但表格是空的这个栏目确实还没定义字段
内容编辑页没有出现字段输入框① 内容选中的栏目不对;② 字段被设为停用;③ 浏览器缓存,强刷一次
模板输出 {"delivery":"7 天"}用了 {$list.meta},改成 {$list.delivery}
模板取值为空但后台明明填了① 字段键拼错(大小写、下划线);② 静态化缓存没清;③ 在列表页取了详情才有的东西
保存时报 Data too longmeta 超过 1000 字,减少字段或缩短内容

字段与内置字段的完整对照见 后台 ↔ 变量对照;标签用法见 标签与函数。

ThinkWo CMS v1.0.45 开发文档 · 基于 ThinkPHP 8.1.4 + LayUI 2.12 · 文档随代码更新