TanzCMS开源CMS系统

资源路径

TanzCMS 官方文档示例,展示模板标签、开放 API、内容管理和部署说明。

更新:2026-05-30 23:44:05 浏览:4

模板资源路径与渲染顺序说明

更新时间:2026-05-26

本文记录模板资源路径、URL 地址标签和模板引擎渲染顺序,供主题模板开发、标签生成器维护和后续问题排查使用。

一、资源路径常量

普通主题模板优先使用路径常量,写法接近传统 CMS,简单直接。

{THEME_PATH}   当前主题公开资源路径,例如 /themes/xin001/
{ASSETS_PATH}  公共资源路径,例如 /assets/
{UPLOAD_PATH}  上传文件路径,例如 /uploads/

示例:

<link rel="stylesheet" href="{THEME_PATH}css/style.css">
<script src="{THEME_PATH}js/app.js"></script>
<script src="{ASSETS_PATH}vendor/layui/layui.js"></script>

如果主题自己把资源放在子目录,也可以继续拼接:

<script src="{THEME_PATH}assets/global/plugins/jquery.min.js"></script>

{THEME_PATH} 只是当前主题公开资源前缀,不强制主题必须有 assets/ 目录。

二、资源路径标签

资源路径标签属于高级能力,用于自动版本号、插件资源、上传文件、Storage 文件、缩略图等场景。普通 CSS/JS 不强制使用资源标签。

主题资源标签

用于当前主题公开资源目录。

<link rel="stylesheet" href="{theme_asset path='css/style.css' version=2026050702}">
<script src="{theme_asset path='js/app.js' version=mtime}"></script>

公共资源标签

用于 public/ 下的公共静态资源。

<link rel="stylesheet" href="{public_asset path='assets/vendor/layui/css/layui.css' version=2.13.6}">
<script src="{public_asset path='assets/vendor/layui/layui.js' version=2.13.6}"></script>

插件资源

用于已经发布到 public/assets/plugins/{plugin_code}/ 的插件静态资源。

<link rel="stylesheet" href="{plugin_asset code=template_tag_generator path='admin.css' version=mtime}">
<script src="{plugin_asset code=template_tag_generator path='admin.js' version=mtime}"></script>

注意:

  • code 是插件代码。
  • path 相对于 public/assets/plugins/{code}/
  • 插件后台页面仍应优先使用插件自己的资源发布机制;前台模板需要引用插件展示资源时再使用该标签。

上传与 Storage 资源

用于站内上传文件和 Laravel storage 公开文件。

<a href="{upload_url path='files/manual.pdf'}">下载附件</a>
<img src="{storage_url path='avatars/demo.png'}" alt="">

输出示例:

/uploads/files/manual.pdf
/storage/avatars/demo.png

图片与附件输出

图片和附件不建议混用一个标签。图片用图片标签,附件用附件标签:

{image_url url=$thumb width=300 height=200}
{image_img url=$thumb width=300 height=200 alt=$title loading=lazy}
{file_url url=$file}
{file_link url=$file text="下载附件" target=_blank}

说明:

  • image_url 只输出图片地址,适合写在 srcdata-src 等属性里。
  • image_img 输出完整 <img> 标签,会自动处理 altwidthheightloading 等属性。
  • file_url 只输出附件地址。
  • file_link 输出完整 <a> 链接,target=_blank 时会自动补 rel="noopener"

二、默认主题资源写法

默认主题普通 CSS/JS 应优先使用路径常量:

  • themes/default/header.html:官网 CSS 使用 {THEME_PATH}
  • themes/default/footer.html:官网 JS 使用 {THEME_PATH}
  • themes/default/member/header.html:会员中心主体页加载 css/member.css
  • themes/default/member/auth-header.html:登录、注册、找回密码等认证页加载 css/login.css
  • themes/default/member/qq-complete.html:QQ 账号补全页是独立认证页,也加载 css/login.css
  • themes/default/member/footer.htmllogin.htmlregister.html:Layui JS 使用 {ASSETS_PATH}public_asset 标签。

默认主题会员资源边界:

  • member.css 只放登录后会员中心通用样式,例如资料、订单、投稿、资产、充值、提现和会员中心首页。
  • login.css 只放认证链路样式,例如登录、注册、忘记密码、找回密码、快捷登录和第三方账号补全。
  • 认证页样式不要重新写回 member.css,避免登录页加载会员中心完整样式,也避免会员中心主体页被认证页样式影响。

后续新增默认模板时也应沿用路径常量,不要回退到固定 /themes/default/...。需要自动版本号、插件资源或生成器示例时,再使用资源标签。

三、URL 地址标签

资源路径标签只负责 CSS、JS、图片、附件等静态或上传资源;页面跳转地址使用前端 URL 标签。两类标签不要混用。

<a href="{category_url slug=downloads}">产品下载</a>
<a href="{page_url slug=contact}">联系我们</a>
<a href="{content_url slug=hello-world}">内容详情</a>
<a href="{member_url path=login}">会员登录</a>
<a href="{member_url path=orders id=$order.order_no}">订单详情</a>
<a href="{module_url code=order path=query}">游客查单</a>

说明:

  • 列表循环、栏目循环、搜索循环中,优先使用数据自带的 {$t.url}{$c.url}{$rs.url}
  • 通用片段需要显式生成地址时,按用途使用 {category_url}{page_url}{content_url}{member_url}{module_url}{plugin_url}
  • 会员详情类页面可以用 {member_url path=orders id=$order.order_no} 追加路径段,不需要在模板里拼 /member/... 前缀。
  • 模块前台页面使用 {module_url code=模块代码 path=路径};增强型插件前台页面使用 {plugin_url code=插件代码 path=路径},会员作用域可写 scope=member

默认主题首页、头部和底部的栏目入口,以及会员中心低风险页面跳转,已改为前端 URL 标签。表单 action 和 JS fetch 接口属于业务提交入口,暂时保持固定路由。

四、渲染顺序

当前模板渲染顺序可以理解为:

  1. 外层 {if}{loop} 先处理页面结构。
  2. {content}{category}{search}{table} 等数据标签建立数据上下文;{module} 作为兼容别名。
  3. 数据标签循环体内部再渲染 {if}{loop}、资源路径标签、图片/文件标签和变量。
  4. 最后输出普通变量和 {html $content}

这样既能让外层条件控制整个数据标签,也能让数据标签内部安全读取循环变量。

五、推荐写法

列表中按缩略图判断:

{content model=article catid=$catid num=10}
  {if $t.thumb}
    {thumb_img url=$t.thumb width=240 height=160 alt=$t.title class=cover}
  {else}
    <span>{$t.title}</span>
  {/if}
{/content}

外层条件包住数据标签:

{if $category.id}
  {content model=article catid=$category.id num=10}
    <a href="{$t.url}">{$t.title}</a>
  {/content}
{else}
  <p>栏目不存在</p>
{/if}

空数据分支:

{content model=article catid=$catid num=10}
  <a href="{$t.url}">{$t.title}</a>
{empty}
  <p>暂无内容</p>
{/empty}
{/content}

六、仍需注意

  • 当前已支持数据标签内部的 {if} 和行内资源/图片/文件标签,但更复杂的多层组合仍需要继续补测试。
  • {elseif} 还未作为独立语法完成,复杂分支先使用嵌套 {if}{else}
  • 前端 URL 推荐使用 {category_url}{page_url}{content_url}{member_url}{plugin_url} 这类直观标签;{url to=...} 只作为兼容写法保留。
  • 后台管理页面不要复用前台主题标签;前台主题也不要调用后台管理能力。

七、模板异常诊断

模板诊断默认跟随 APP_DEBUG。如果线上临时排查模板问题,但不想打开完整调试模式,可以单独设置:

TANZCMS_TEMPLATE_DIAGNOSTICS=true

开启后,模板页面会显示中文诊断块,覆盖以下常见问题:

  • 模板文件不存在:提示 themes/{theme}/{template},并提醒检查后台栏目模板设置或主题文件同步。
  • 模板标签未注册:例如 {related}{prev}{next} 这类尚未落地或插件未启用的标签,会提示标签名称和处理建议。
  • 模板标签执行失败:已注册标签内部报错时,不再静默输出空白,而是显示标签名、参数和异常原因。
  • 变量写法无法解析:例如 {$article..title} 会提示变量写法错误。

关闭诊断时,前台保持面向访客的稳定输出:缺失页面仍走主题 404;标签内部异常不会直接暴露给访客。

八、栏目模板路径规则

栏目模板选择不应该只限制在主题根目录。模板作者可以用目录区分不同栏目、模型或插件场景。

完整目录作用域见:主题目录与模板作用域规范.md。本文只说明与渲染和标签调用直接相关的规则。

例如新闻网站可以这样组织:

themes/default/
├─ header.html
├─ index.html
├─ footer.html
├─ list.html
├─ show.html
└─ 456/
   ├─ list.html
   ├─ list_news.html
   └─ show.html

后台栏目保存的模板值应该是相对主题目录的模板路径,例如:

list.html
list_news.html
456/list.html
456/list_news.html

规则:

  • list.htmlshow.htmlpage.htmlcategory.html 是可选通用模板,不是强制模板。
  • list_*.htmlshow_*.htmlpage_*.htmlcategory_*.html 是同类型专用模板。
  • 目录只是命名空间,用来区分栏目、模型、插件或业务场景,不改变模板类型。
  • 列表栏目只有最终保存的 list_template 存在即可,不要求根目录必须有 list.html
  • 栏目封面模板 category.html/category_*.html 只在栏目需要先展示下级栏目封面时使用;普通最终列表栏目可以完全不用。
  • 插件需要模板文件时,也可以按插件需求建立目录或模板页面,但应通过插件配置、标签或模板选择接入,不应在普通前台控制器里硬编码。

八、验证命令

修改模板引擎或默认主题后,至少执行:

php artisan tanzcms:template-clear
php artisan tanzcms:template-compile default
php artisan test --filter=TemplateEngineTest
php artisan test --filter=ExampleTest

同步到验证站后也要执行同样的缓存清理和关键测试。

九、前台业务标签

第一批通用业务标签已经注册到核心前台模板标签体系:

{breadcrumb article=1 return=nav}
  <a class="{$nav.active}" href="{$nav.url}">{$nav.name}</a>
{/breadcrumb}

{prev_next return=nav}
  {if $nav.has_prev}<a href="{$nav.prev.url}">上一篇:{$nav.prev.title}</a>{/if}
  {if $nav.has_next}<a href="{$nav.next.url}">下一篇:{$nav.next.title}</a>{/if}
{/prev_next}

{related module=article num=6 order=new return=t}
  <a href="{$t.url}">{$t.title}</a>
{/related}

{member_status return=m}
  <a href="{$m.center_url}">{$m.nickname}</a>
{empty}
  <a href="{$m.login_url}">登录</a>
{/empty}
{/member_status}

这些标签只处理前台通用展示逻辑。模块或插件自己的业务按钮、交易流程和页面入口继续通过各自服务提供者注册的标签实现,例如订单模块的 {member_order} / {order_buy}