主题系统
主题目录位于 themes/{theme}。主题只负责前台展示和可配置内容,不应修改核心控制器、模型或数据库结构。
主题目录规范
themes/default/
├── style.css
├── screenshot.jpg
├── functions.php
├── blocks.php
├── header.php
├── footer.php
├── home.php
├── product_list.php
├── product_detail.php
├── post_list.php
├── post_detail.php
├── case_list.php
├── case_detail.php
└── page_detail.phpstyle.css 顶部必须包含主题元数据:
/*
Theme Name: Default
Theme URI: https://shopagg.org
Author: Lighthouse CMS
Version: 1.0.0
Description: Default Lighthouse CMS B2B theme.
*/主题渲染机制
Controller::render() 会根据系统设置中的当前主题加载模板。如果目标主题不存在,系统回退到 themes/default/。
模板可调用:
- 全局辅助函数,例如
h()、url()、asset_url()。 - 主题辅助函数,例如产品卡片、媒体渲染、轮播读取。
- 主题区块函数,例如
block()和block_all()。
模板区块系统
模板区块是主题可维护能力的核心。开发主题时,凡是客户需要改的文字、图片、按钮、颜色、产品、轮播、显示数量,都应暴露到 blocks.php。
blocks.php 基本结构
return [
'home_hero' => [
'label' => '首页 - 首屏',
'group' => 'home',
'group_label' => '首页',
'fields' => [
'label' => [
'type' => 'text',
'label' => '区块小标签',
'default' => 'B2B Manufacturer'
],
'title' => [
'type' => 'text',
'label' => '主标题',
'default' => 'Premium Quality Industrial Products'
],
'featured_products' => [
'type' => 'product_picker',
'label' => '推荐产品',
'default' => []
]
]
]
];模板读取:
$title = block('home_hero', 'title', 'Premium Quality Industrial Products');
$products = block('home_hero', 'featured_products', []);字段类型规范
| 字段类型 | 用途 | 建议 |
|---|---|---|
text | 标题、按钮文字、短文案。 | 单行文本。 |
textarea | 简介、多行说明。 | 不要放复杂 HTML。 |
richtext | 需要格式的正文。 | 用于关于、服务等长内容。 |
image | 单张图片。 | 输出前用 asset_url()。 |
media | 图片或视频。 | 适合 Banner、背景媒体。 |
product_picker | 产品选择弹窗。 | 产品展示区块必须优先使用。 |
select | 下拉选项。 | 适合布局、开关、轮播图选择。 |
hidden | 技术兜底字段。 | 不作为运营主要配置项。 |
产品区块规则
产品展示区块必须使用 product_picker,不要用 item1_title、item1_image、item1_url 伪造产品卡片。
原因:
- 后台无法复用产品选择弹窗。
- 产品详情、价格、图片、分类和询盘入口会与真实数据脱节。
- 运营改产品时需要同时改多处假数据。
- SEO 和前台详情链接不稳定。
轮播区块规则
首页首屏轮播、Banner 轮播等模块应读取「外观区块 → 轮播图」里的真实轮播图数据。模板区块只配置使用哪个轮播图 Slug。
'hero_slider_slug' => [
'type' => 'select',
'label' => '选择轮播图区块',
'default' => 'home-hero',
'options' => $sliderOptions
]禁止在 blocks.php 中逐张配置:
'slide1_image' => ['type' => 'image'],
'slide2_image' => ['type' => 'image'],
'slide3_image' => ['type' => 'image'],旧主题为了兼容可以保留隐藏字段,但后台可见维护入口应使用轮播图管理。
主题代码规范
安全输出
模板输出必须转义:
<h1><?= h($product['title'] ?? '') ?></h1>
<a href="<?= h(url('/products')) ?>">Products</a>
<img src="<?= h(asset_url($image)) ?>" alt="<?= h($product['title'] ?? '') ?>">规则:
- 普通文本和属性使用
h()。 - 系统内部链接使用
url()。 - 上传文件路径使用
asset_url()。 - 富文本只输出经过后台编辑器保存、可控来源的字段。
- 不把
$_GET、$_POST原始值直接输出到页面。
主题辅助函数
重复逻辑放在 functions.php:
- 产品卡片。
- 媒体渲染。
- 轮播读取。
- 图片兜底。
- 价格展示。
- 菜单渲染。
不要在多个模板复制同一段产品卡片 HTML,后续改版会很难维护。
Tailwind 使用建议
默认主题使用 Tailwind CDN。新主题应尽量用 Tailwind 类名完成布局和响应式,style.css 保留:
- 主题元数据。
- Tailwind 不方便表达的少量补充样式。
- 特定动画或第三方组件覆盖。
不要把整个主题视觉都堆进 style.css,否则后台切换主题和后续维护成本会变高。
菜单与轮播模型
菜单
前台主题通常通过 Menu 模型读取菜单:
$menuModel = new \App\Models\Menu();
$navItems = $menuModel->getMenuItems('main-nav');
$footerLinks = $menuModel->getMenuItems('footer');常用菜单 Slug:
| Slug | 用途 |
|---|---|
main-nav | 头部主导航。 |
footer | 页脚菜单。 |
product-nav | 产品中心或分类菜单。 |
轮播
轮播数据由 sliders 和 slider_items 管理。主题应读取激活轮播项,不要硬编码轮播图片。
建议主题辅助函数返回统一结构:
[
'title' => 'Slide title',
'description' => 'Slide description',
'image' => '/uploads/...',
'button_text' => 'Learn More',
'button_url' => '/products'
]