系统公告数据需自行定义数据源,通常来自数据库表(如system_notice)、缓存或配置文件;首页控制器中推荐用NoticeModel模型查询最新5条有效公告,并启用时间自动转换;模板中用{not empty}判断+{volist}循环安全展示,链接使用{:url()}生成,HTML内容需过滤XSS;高频场景应加缓存并设置合理键名,后台发布后须主动清除对应缓存。

系统公告数据该从哪来
ThinkPHP6 本身不内置“系统公告”模型或接口,所谓“调用公告”,本质是读取你项目中已定义的数据源——通常是数据库表(如 system_notice),也可能是缓存(cache('notice_list'))或配置文件(config('notice'))。别指望框架自动给你吐公告,得先有数据载体。
在首页控制器里查公告的常规写法
假设你已建好 system_notice 表,字段含 id、title、content、status、create_time,且启用软删除和时间自动填充:
- 在
app/index/controller/Index.php的index方法里,用 Db 或模型查最新 5 条有效公告:$notices = Db::name('system_notice') ->where('status', 1) ->order('create_time', 'desc') ->limit(5) ->select(); - 或者用模型(推荐):
$notices = NoticeModel::where('status', 1) ->order('create_time', 'desc') ->limit(5) ->select();注意类名要正确声明:use app\model\NoticeModel; - 务必检查模型是否启用时间自动转换:在
NoticeModel中设置protected $type = ['create_time' => 'datetime'];,否则模板里{$item.create_time|date='Y-m-d'}可能出错
模板里怎么安全展示
传到模板后,别直接 {$notices} 打印数组,容易报错或暴露结构。用空值判断 + 循环最稳妥:
{not empty $notices}
{volist name="notices" id="item"}
<div class="notice-item">
<a href="{:url('notice/detail', ['id'=>$item.id])}">{$item.title}</a>
<span class="time">{$item.create_time|date='m-d'}</span>
</div>
{/volist}
{else /}
<p class="empty">暂无公告</p>
{/not empty}
-
{not empty $notices}比{if $notices}更可靠,后者对空数组也返回 true - 链接用
{:url('notice/detail', ...)}而非硬编码/notice/detail?id=1,避免路由变动时全站失效 - 如果公告内容含 HTML(比如富文本编辑器录入),模板中要用
{$item.content|htmlspecialchars_decode},但必须确保入库前已过滤 XSS,否则有安全风险
公告频繁更新时要不要加缓存
首页每次请求都查库,公告又不常变,纯属浪费。TP6 缓存开箱即用,加一层非常简单:
立即学习“PHP免费学习笔记(深入)”;
- 把查库逻辑包进缓存读写:
$notices = cache('home_notices'); if (false === $notices) { $notices = Db::name('system_notice')->where('status', 1)->order('create_time', 'desc')->limit(5)->select(); cache('home_notices', $notices, 3600); // 缓存 1 小时 } - 注意缓存键名别用太泛的
'notices',多个页面共用会互相覆盖;加前缀如'home_notices'或带版本号'home_notices_v2' - 后台发布新公告时,记得删缓存:
cache('home_notices', null);,否则用户看不到更新 - 若用 Redis 驱动,确认
config/cache.php中'default' => 'redis'已生效,且 Redis 连接正常,否则cache()会静默退化为 file 驱动,可能卡在 runtime/cache 目录权限问题上
真正容易被忽略的是缓存穿透和后台同步时机——比如管理员刚点发布,前端刷新还看到旧公告,不是代码错了,而是缓存没删干净,或者删缓存那行代码根本没执行(比如事务回滚导致跳过)。上线前务必手动测一遍“发公告 → 刷新首页 → 看是否实时出现”。



















