CarefreeCMS 文档CarefreeCMS 文档
指南
  • 内容管理
  • 多站点管理
  • AI文章生成
  • SEO优化
  • 静态化生成
API
  • FAQ
  • 更新日志
  • 贡献指南
  • v1.3.0
  • v1.2.0
  • v1.1.0
GitHub
指南
  • 内容管理
  • 多站点管理
  • AI文章生成
  • SEO优化
  • 静态化生成
API
  • FAQ
  • 更新日志
  • 贡献指南
  • v1.3.0
  • v1.2.0
  • v1.1.0
GitHub
  • 开始使用

    • 介绍
    • 安装指南
    • 快速开始
    • 系统配置
  • 基础功能

    • 文章管理
    • 分类管理
    • 标签管理
    • 单页管理
    • 媒体库
  • 高级功能

    • 模板开发
    • 静态化生成
    • 搜索功能
    • 权限管理
    • 用户管理
  • AI 功能

    • AI 服务商配置
    • AI 模型配置
    • 提示词工程
  • 系统管理

    • 定时任务
    • 日志管理
    • 安全指南
    • 性能优化

模板开发

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 - 站点URL
  • logo - 站点Logo
  • keywords - 站点关键词
  • 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}

参数:

参数类型说明默认值示例
limitinteger数量限制10limit="10"
offsetinteger偏移量0offset="0"
orderstring排序方式create_time descorder="view_count desc"
category_idinteger分类ID-category_id="1"
tag_idinteger标签ID-tag_id="5"
is_topinteger是否置顶-is_top="1"
is_hotinteger是否热门-is_hot="1"
is_recommendinteger是否推荐-is_recommend="1"
keywordstring关键词搜索-keyword="Vue"
exclude_idinteger排除的文章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}

参数:

参数类型说明默认值
limitinteger数量限制0(全部)
parent_idinteger父分类ID-
is_navinteger是否导航分类-
treeboolean是否返回树形结构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}

参数:

参数类型说明默认值
limitinteger数量限制0(全部)
orderstring排序方式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}

参数:

参数类型说明
limitinteger数量限制
group_idinteger分组ID
positionstring位置标识

可用变量:

  • {$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}

参数:

参数类型说明
limitinteger数量限制
positionstring位置标识

可用变量:

  • {$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}

参数:

参数类型说明
limitinteger数量限制
article_idinteger文章ID
orderstring排序方式

可用变量:

  • {$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>&copy; {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

相关资源

  • 静态化生成
  • 系统配置
  • API文档
在 GitHub 上编辑此页
Next
静态化生成