模板开发
CarefreeCMS 提供了丰富的自定义模板标签,让你可以轻松调用系统数据,快速开发前台页面模板。
模板概述
CarefreeCMS 使用自定义标签语法 {carefree:标签名} 来调用数据,模板文件位于 backend/templates/ 目录。
目录结构
backend/templates/
├── default/ # 默认主题
│ ├── layout/ # 布局文件
│ ├── index.html # 首页
│ ├── article.html # 文章详情
│ ├── category.html # 分类列表
│ └── ...
└── custom/ # 自定义主题
标签基本格式
成对标签(用于列表循环)
{carefree:articles limit="10" order="create_time desc"}
<div class="article">
<h3>{$article.title}</h3>
<p>{$article.summary}</p>
</div>
{/carefree:articles}
单标签(用于输出单个值)
{carefree:article id="1" field="title" /}
{carefree:site field="name" /}
站点信息标签
基本信息
标签: {carefree:site}
参数:
field- 字段名(必填)
字段列表:
name- 站点名称url- 站点URLlogo- 站点Logokeywords- 站点关键词description- 站点描述slogan- 站点标语email- 联系邮箱phone- 联系电话address- 联系地址
示例:
<!-- 站点名称 -->
{carefree:site field="name" /}
<!-- 站点Logo -->
<img src="{carefree:site field='logo' /}" alt="{carefree:site field='name' /}">
<!-- 站点关键词 -->
<meta name="keywords" content="{carefree:site field='keywords' /}">
<!-- 站点描述 -->
<meta name="description" content="{carefree:site field='description' /}">
统计信息
标签: {carefree:stats}
参数:
type- 统计类型(必填)
类型列表:
article_count- 文章总数user_count- 用户总数comment_count- 评论总数view_count- 浏览总数today_articles- 今日发布week_articles- 本周发布month_articles- 本月发布today_views- 今日浏览online_users- 在线用户
示例:
<div class="stats">
<span>文章总数:{carefree:stats type="article_count" /}</span>
<span>用户总数:{carefree:stats type="user_count" /}</span>
<span>今日发布:{carefree:stats type="today_articles" /}</span>
<span>在线用户:{carefree:stats type="online_users" /}</span>
</div>
文章标签
文章列表
标签: {carefree:articles}...{/carefree:articles}
参数:
| 参数 | 类型 | 说明 | 默认值 | 示例 |
|---|---|---|---|---|
| limit | integer | 数量限制 | 10 | limit="10" |
| offset | integer | 偏移量 | 0 | offset="0" |
| order | string | 排序方式 | create_time desc | order="view_count desc" |
| category_id | integer | 分类ID | - | category_id="1" |
| tag_id | integer | 标签ID | - | tag_id="5" |
| is_top | integer | 是否置顶 | - | is_top="1" |
| is_hot | integer | 是否热门 | - | is_hot="1" |
| is_recommend | integer | 是否推荐 | - | is_recommend="1" |
| keyword | string | 关键词搜索 | - | keyword="Vue" |
| exclude_id | integer | 排除的文章ID | - | exclude_id="10" |
可用变量:
{$article.id}- 文章ID{$article.title}- 标题{$article.summary}- 摘要{$article.content}- 内容{$article.cover}- 封面图{$article.author}- 作者{$article.create_time}- 发布时间{$article.update_time}- 更新时间{$article.view_count}- 浏览次数{$article.like_count}- 点赞数{$article.comment_count}- 评论数{$article.category}- 分类对象{$article.tags}- 标签数组{$article.url}- 文章URL
示例:
<!-- 最新文章 -->
{carefree:articles limit="10" order="create_time desc"}
<div class="article">
<h3><a href="{$article.url}">{$article.title}</a></h3>
<p>{$article.summary}</p>
<span>{$article.create_time|date:'Y-m-d'}</span>
<span>{$article.view_count} 次浏览</span>
</div>
{/carefree:articles}
<!-- 热门文章 -->
{carefree:articles limit="10" order="view_count desc"}
<li><a href="{$article.url}">{$article.title}</a></li>
{/carefree:articles}
<!-- 推荐文章 -->
{carefree:articles is_recommend="1" limit="6"}
<article class="card">
<img src="{$article.cover}" alt="{$article.title}">
<h4>{$article.title}</h4>
<p>{$article.summary|truncate:100}</p>
</article>
{/carefree:articles}
<!-- 指定分类文章 -->
{carefree:articles category_id="1" limit="10"}
<div>{$article.title}</div>
{/carefree:articles}
<!-- 相关文章(排除当前文章) -->
{carefree:articles category_id="{$current.category_id}" exclude_id="{$current.id}" limit="5"}
<li><a href="{$article.url}">{$article.title}</a></li>
{/carefree:articles}
单个文章
标签: {carefree:article}
参数:
id- 文章ID(必填)field- 字段名(选填,不填则返回整个文章对象)
示例:
<!-- 获取指定文章的标题 -->
{carefree:article id="1" field="title" /}
<!-- 获取整个文章对象 -->
{carefree:article id="1"}
<h1>{$article.title}</h1>
<div>{$article.content}</div>
{/carefree:article}
分类标签
分类列表
标签: {carefree:categories}...{/carefree:categories}
参数:
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| limit | integer | 数量限制 | 0(全部) |
| parent_id | integer | 父分类ID | - |
| is_nav | integer | 是否导航分类 | - |
| tree | boolean | 是否返回树形结构 | false |
可用变量:
{$category.id}- 分类ID{$category.name}- 分类名称{$category.alias}- 分类别名{$category.description}- 分类描述{$category.icon}- 分类图标{$category.cover}- 分类封面{$category.article_count}- 文章数量{$category.url}- 分类URL{$category.children}- 子分类数组(tree模式)
示例:
<!-- 所有分类 -->
{carefree:categories}
<li>
<a href="{$category.url}">
{$category.name} ({$category.article_count})
</a>
</li>
{/carefree:categories}
<!-- 顶级分类 -->
{carefree:categories parent_id="0"}
<li>{$category.name}</li>
{/carefree:categories}
<!-- 导航分类 -->
{carefree:categories is_nav="1"}
<li><a href="{$category.url}">{$category.name}</a></li>
{/carefree:categories}
<!-- 分类树 -->
{carefree:categories tree="true"}
<li>
<a href="{$category.url}">{$category.name}</a>
{if $category.children}
<ul>
{loop $category.children $child}
<li><a href="{$child.url}">{$child.name}</a></li>
{/loop}
</ul>
{/if}
</li>
{/carefree:categories}
单个分类
标签: {carefree:category}
参数:
id- 分类ID(与alias二选一)alias- 分类别名(与id二选一)field- 字段名(选填)
示例:
<!-- 通过ID获取 -->
{carefree:category id="1" field="name" /}
<!-- 通过别名获取 -->
{carefree:category alias="tech"}
<h1>{$category.name}</h1>
<p>{$category.description}</p>
{/carefree:category}
标签云
标签列表
标签: {carefree:tags}...{/carefree:tags}
参数:
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| limit | integer | 数量限制 | 0(全部) |
| order | string | 排序方式 | article_count desc |
可用变量:
{$tag.id}- 标签ID{$tag.name}- 标签名称{$tag.alias}- 标签别名{$tag.article_count}- 文章数量{$tag.url}- 标签URL
示例:
<!-- 热门标签 -->
{carefree:tags limit="20" order="article_count desc"}
<a href="{$tag.url}" class="tag">{$tag.name}</a>
{/carefree:tags}
<!-- 标签云(大小不同) -->
{carefree:tags limit="30"}
<a href="{$tag.url}" style="font-size: {12 + $tag.article_count / 10}px">
{$tag.name}
</a>
{/carefree:tags}
友情链接标签
标签: {carefree:links}...{/carefree:links}
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| limit | integer | 数量限制 |
| group_id | integer | 分组ID |
| position | string | 位置标识 |
可用变量:
{$link.name}- 链接名称{$link.url}- 链接地址{$link.logo}- Logo图片{$link.description}- 描述
示例:
{carefree:links limit="10"}
<li>
<a href="{$link.url}" target="_blank" rel="nofollow">
{if $link.logo}
<img src="{$link.logo}" alt="{$link.name}">
{else}
{$link.name}
{/if}
</a>
</li>
{/carefree:links}
轮播图标签
标签: {carefree:sliders}...{/carefree:sliders}
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| limit | integer | 数量限制 |
| position | string | 位置标识 |
可用变量:
{$slider.title}- 标题{$slider.image}- 图片{$slider.url}- 链接地址{$slider.description}- 描述
示例:
<div class="slider">
{carefree:sliders position="home" limit="5"}
<div class="slide">
<a href="{$slider.url}">
<img src="{$slider.image}" alt="{$slider.title}">
<div class="caption">
<h3>{$slider.title}</h3>
<p>{$slider.description}</p>
</div>
</a>
</div>
{/carefree:sliders}
</div>
广告标签
标签: {carefree:ad}
参数:
position- 广告位标识(必填)
可用变量:
{$ad.title}- 标题{$ad.type}- 类型(image/code){$ad.image}- 图片{$ad.url}- 链接{$ad.code}- 代码
示例:
{carefree:ad position="header"}
{if $ad.type == 'image'}
<a href="{$ad.url}" target="_blank">
<img src="{$ad.image}" alt="{$ad.title}">
</a>
{else}
{$ad.code}
{/if}
{/carefree:ad}
单页标签
标签: {carefree:page}
参数:
id- 单页ID(与alias二选一)alias- 单页别名(与id二选一)field- 字段名(选填)
可用变量:
{$page.title}- 标题{$page.content}- 内容{$page.url}- URL
示例:
<!-- 关于我们页面 -->
{carefree:page alias="about"}
<h1>{$page.title}</h1>
<div>{$page.content}</div>
{/carefree:page}
<!-- 仅获取标题 -->
{carefree:page alias="about" field="title" /}
评论标签
标签: {carefree:comments}...{/carefree:comments}
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| limit | integer | 数量限制 |
| article_id | integer | 文章ID |
| order | string | 排序方式 |
可用变量:
{$comment.user}- 用户信息{$comment.content}- 评论内容{$comment.create_time}- 评论时间{$comment.like_count}- 点赞数{$comment.article}- 文章信息
示例:
<!-- 最新评论 -->
{carefree:comments limit="10"}
<div class="comment">
<div class="user">{$comment.user.nickname}</div>
<div class="content">{$comment.content}</div>
<div class="time">{$comment.create_time|timeago}</div>
</div>
{/carefree:comments}
<!-- 文章评论 -->
{carefree:comments article_id="{$article.id}" limit="20"}
<div class="comment-item">
{$comment.content}
</div>
{/carefree:comments}
用户标签
当前用户
标签: {carefree:current_user}
可用变量:
{$user.id}- 用户ID{$user.username}- 用户名{$user.nickname}- 昵称{$user.avatar}- 头像{$user.email}- 邮箱
示例:
{carefree:current_user}
<div class="user-info">
<img src="{$user.avatar}" alt="{$user.nickname}">
<span>{$user.nickname}</span>
</div>
{/carefree:current_user}
活跃用户
标签: {carefree:users}...{/carefree:users}
参数:
limit- 数量限制order- 排序方式
示例:
{carefree:users limit="10" order="article_count desc"}
<div class="user">
<img src="{$user.avatar}" alt="{$user.nickname}">
<span>{$user.nickname}</span>
<small>{$user.article_count} 篇文章</small>
</div>
{/carefree:users}
导航标签
标签: {carefree:navigation}...{/carefree:navigation}
参数:
position- 位置标识(main/footer等)
可用变量:
{$nav.name}- 名称{$nav.url}- 链接{$nav.icon}- 图标{$nav.target}- 打开方式{$nav.children}- 子菜单{$nav.active}- 是否当前
示例:
<nav>
<ul>
{carefree:navigation position="main"}
<li class="{if $nav.active}active{/if}">
<a href="{$nav.url}" target="{$nav.target}">
{if $nav.icon}<i class="{$nav.icon}"></i>{/if}
{$nav.name}
</a>
{if $nav.children}
<ul class="sub-menu">
{loop $nav.children $child}
<li><a href="{$child.url}">{$child.name}</a></li>
{/loop}
</ul>
{/if}
</li>
{/carefree:navigation}
</ul>
</nav>
搜索标签
标签: {carefree:hot_search}...{/carefree:hot_search}
参数:
limit- 数量限制
示例:
<div class="hot-search">
<h4>热门搜索</h4>
{carefree:hot_search limit="10"}
<a href="/search?keyword={$keyword}">{$keyword}</a>
{/carefree:hot_search}
</div>
辅助标签
URL生成
<!-- 生成文章URL -->
{url type="article" id="1" /}
<!-- 生成分类URL -->
{url type="category" alias="tech" /}
<!-- 生成资源URL -->
{asset path="css/style.css" /}
条件判断
<!-- 是否登录 -->
{if is_login()}
<a href="/user/profile">个人中心</a>
{else}
<a href="/login">登录</a>
{/if}
<!-- 是否有权限 -->
{if has_permission('article.create')}
<a href="/article/create">发布文章</a>
{/if}
<!-- 是否收藏 -->
{if is_favorited($article.id)}
<button class="favorited">已收藏</button>
{else}
<button class="favorite">收藏</button>
{/if}
过滤器
时间格式化
<!-- 日期格式化 -->
{$article.create_time|date:'Y-m-d H:i:s'}
<!-- 友好时间 -->
{$article.create_time|timeago}
<!-- 输出:3分钟前、2小时前、1天前 -->
文本处理
<!-- 截取文本 -->
{$article.content|truncate:100}
<!-- 去除HTML -->
{$article.content|strip_tags}
<!-- 高亮关键词 -->
{$article.title|highlight:$keyword}
<!-- 换行转br -->
{$article.content|nl2br}
数字格式化
<!-- 数字格式化 -->
{$article.view_count|number_format}
<!-- 1234 → 1,234 -->
<!-- 友好数字 -->
{$article.view_count|friendly}
<!-- 1234 → 1.2k -->
<!-- 12345 → 1.2w -->
完整模板示例
首页模板
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{carefree:site field="name" /} - {carefree:site field="slogan" /}</title>
<meta name="keywords" content="{carefree:site field='keywords' /}">
<meta name="description" content="{carefree:site field='description' /}">
<link rel="stylesheet" href="{asset path='css/style.css' /}">
</head>
<body>
<!-- 头部 -->
<header>
<div class="logo">
<a href="/">
<img src="{carefree:site field='logo' /}" alt="{carefree:site field='name' /}">
</a>
</div>
<nav>
<ul>
{carefree:navigation position="main"}
<li><a href="{$nav.url}">{$nav.name}</a></li>
{/carefree:navigation}
</ul>
</nav>
</header>
<!-- 轮播图 -->
<div class="slider">
{carefree:sliders position="home" limit="5"}
<div class="slide">
<img src="{$slider.image}" alt="{$slider.title}">
</div>
{/carefree:sliders}
</div>
<!-- 推荐文章 -->
<section class="recommend">
<h2>推荐阅读</h2>
<div class="article-grid">
{carefree:articles is_recommend="1" limit="6"}
<article>
<img src="{$article.cover}" alt="{$article.title}">
<h3>{$article.title}</h3>
<p>{$article.summary|truncate:80}</p>
<div class="meta">
<span>{$article.create_time|timeago}</span>
<span>{$article.view_count|friendly} 阅读</span>
</div>
</article>
{/carefree:articles}
</div>
</section>
<!-- 最新文章 -->
<section class="latest">
<h2>最新发布</h2>
{carefree:articles limit="10"}
<article class="list-item">
<h3><a href="{$article.url}">{$article.title}</a></h3>
<p>{$article.summary}</p>
<div class="tags">
{loop $article.tags $tag}
<a href="{$tag.url}">#{$tag.name}</a>
{/loop}
</div>
</article>
{/carefree:articles}
</section>
<!-- 侧边栏 -->
<aside class="sidebar">
<!-- 分类 -->
<div class="widget">
<h3>文章分类</h3>
<ul>
{carefree:categories limit="10"}
<li>
<a href="{$category.url}">
{$category.name} ({$category.article_count})
</a>
</li>
{/carefree:categories}
</ul>
</div>
<!-- 标签云 -->
<div class="widget">
<h3>热门标签</h3>
<div class="tag-cloud">
{carefree:tags limit="20"}
<a href="{$tag.url}">{$tag.name}</a>
{/carefree:tags}
</div>
</div>
<!-- 友情链接 -->
<div class="widget">
<h3>友情链接</h3>
<ul>
{carefree:links limit="10"}
<li><a href="{$link.url}" target="_blank">{$link.name}</a></li>
{/carefree:links}
</ul>
</div>
</aside>
<!-- 底部 -->
<footer>
<p>© {date('Y')} {carefree:site field="name" /}. All rights reserved.</p>
</footer>
</body>
</html>
文章详情模板
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{$article.title} - {carefree:site field="name" /}</title>
<meta name="keywords" content="{$article.seo_keywords}">
<meta name="description" content="{$article.seo_description}">
</head>
<body>
<article class="article-detail">
<!-- 面包屑 -->
<nav class="breadcrumb">
<a href="/">首页</a> /
<a href="{$article.category.url}">{$article.category.name}</a> /
<span>{$article.title}</span>
</nav>
<!-- 文章标题 -->
<h1>{$article.title}</h1>
<!-- 文章信息 -->
<div class="meta">
<span>作者:{$article.author.nickname}</span>
<span>发布时间:{$article.create_time|date:'Y-m-d H:i'}</span>
<span>浏览:{$article.view_count} 次</span>
<span>分类:<a href="{$article.category.url}">
{$article.category.name}
</a></span>
</div>
<!-- 封面图 -->
{if $article.cover}
<div class="cover">
<img src="{$article.cover}" alt="{$article.title}">
</div>
{/if}
<!-- 文章内容 -->
<div class="content">
{$article.content}
</div>
<!-- 标签 -->
{if $article.tags}
<div class="tags">
<span>标签:</span>
{loop $article.tags $tag}
<a href="{$tag.url}" class="tag">#{$tag.name}</a>
{/loop}
</div>
{/if}
<!-- 相关文章 -->
<div class="related">
<h3>相关文章</h3>
<ul>
{carefree:articles category_id="{$article.category_id}" exclude_id="{$article.id}" limit="5"}
<li><a href="{$article.url}">{$article.title}</a></li>
{/carefree:articles}
</ul>
</div>
<!-- 评论 -->
{if $article.allow_comment}
<div class="comments">
<h3>评论 ({$article.comment_count})</h3>
{carefree:comments article_id="{$article.id}" limit="20"}
<div class="comment-item">
<div class="user">{$comment.user.nickname}</div>
<div class="content">{$comment.content}</div>
<div class="time">{$comment.create_time|timeago}</div>
</div>
{/carefree:comments}
</div>
{/if}
</article>
</body>
</html>
PHP 实现标签
在 backend/app/service/TagService.php 中实现标签解析:
<?php
namespace app\service;
class TagService
{
/**
* 解析文章列表标签
*/
public function parseArticles($params, $content)
{
$query = \app\model\Article::where('status', 1);
// 分类筛选
if (isset($params['category_id'])) {
$query->where('category_id', $params['category_id']);
}
// 置顶筛选
if (isset($params['is_top'])) {
$query->where('is_top', $params['is_top']);
}
// 推荐筛选
if (isset($params['is_recommend'])) {
$query->where('is_recommend', $params['is_recommend']);
}
// 排除文章
if (isset($params['exclude_id'])) {
$query->where('id', '<>', $params['exclude_id']);
}
// 排序和限制
$limit = $params['limit'] ?? 10;
$order = $params['order'] ?? 'create_time desc';
$articles = $query->order($order)->limit($limit)->select();
// 渲染模板
$html = '';
foreach ($articles as $article) {
// 替换变量
$item = str_replace(
['{$article.title}', '{$article.url}', '{$article.summary}'],
[$article->title, $article->url, $article->summary],
$content
);
$html .= $item;
}
return $html;
}
/**
* 解析分类列表标签
*/
public function parseCategories($params, $content)
{
$query = \app\model\Category::where('status', 1);
if (isset($params['parent_id'])) {
$query->where('parent_id', $params['parent_id']);
}
$limit = $params['limit'] ?? 0;
if ($limit > 0) {
$query->limit($limit);
}
$categories = $query->order('sort', 'asc')->select();
$html = '';
foreach ($categories as $category) {
$item = str_replace(
['{$category.name}', '{$category.url}', '{$category.article_count}'],
[$category->name, $category->url, $category->article_count],
$content
);
$html .= $item;
}
return $html;
}
}
最佳实践
1. 合理使用缓存
<!-- 缓存热门文章 -->
{cache key="hot_articles" time="3600"}
{carefree:articles order="view_count desc" limit="10"}
<li>{$article.title}</li>
{/carefree:articles}
{/cache}
2. 避免过度查询
<!-- ✓ 好的做法:在控制器中预加载 -->
{loop $articles $article}
{$article.category.name}
{/loop}
<!-- ✗ 坏的做法:在循环中查询 -->
{loop $articles $article}
{carefree:category id="{$article.category_id}" field="name" /}
{/loop}
3. 模块化组织
templates/
├── layout/
│ ├── header.html
│ ├── footer.html
│ └── sidebar.html
├── components/
│ ├── article-card.html
│ └── category-tree.html
└── pages/
├── index.html
└── article.html
