开发文档

面向扩展与主题开发的技术说明

SHOPAGG 使用纯 PHP MVC、SQLite3、版本化迁移和前后台分离主题机制。本文档整理源码结构、扩展流程、模板规范和上线前技术验收点。

技术摘要
  • 运行环境:PHP 8.1+,需要 sqlite3mbstringfileinfo
  • 架构:index.php 单入口,PSR-4 自动加载,app/routes.php 集中注册路由。
  • 数据:SQLite 文件数据库,迁移文件按时间戳自动执行。
  • 主题:themes/{theme} 目录隔离,blocks.php 暴露后台可编辑字段。

技术栈

项目坚持零框架、零构建的部署体验,但内部仍然按清晰层次组织代码,便于后续扩展。

层次 技术 说明
后端 PHP 8.1+ 纯 PHP 实现,不依赖 Composer 包。
数据库 SQLite3 文件数据库,默认存储在 storage/site.db,支持 WAL 模式。
架构 MVC + Router 控制器、模型、视图分层,集中路由注册。
前台主题 Tailwind CSS CDN 主题模板优先使用 Tailwind 类名,避免重样式侵入核心。
后台编辑 Jodit / SortableJS / Font Awesome 富文本、拖拽排序、图标和后台界面能力按需加载。

系统架构

请求从 Web 服务器重写到 index.php,入口文件完成环境初始化、自动加载、辅助函数加载、数据库连接和路由分发。

入口与路由

index.php 是唯一入口;app/routes.php 注册前台、后台、媒体、更新、主题、区块、菜单和轮播图路由。

核心模块

RouterControllerDatabaseMigratorAuthManagerMediaManager 构成系统基础层。

模型层

模型继承 BaseModel,封装 SQLite 操作。产品、文章、分类、询盘、留言、用户、菜单、轮播图等均有独立模型。

视图层

前台视图位于 themes/default/,后台视图位于 app/views/admin/,主题与后台管理界面互相隔离。

HTTP 请求
  -> Apache/Nginx 重写到 index.php
  -> 定义常量、Session、错误处理
  -> PSR-4 自动加载 App\ 命名空间
  -> 加载 app/Helpers/Helpers.php
  -> Database::getInstance() 并执行待处理迁移
  -> Router 匹配 app/routes.php
  -> Controller 调用 Model
  -> 渲染后台视图或 themes/{theme} 前台模板

路由与页面扩展

新增前台页面通常只需要注册路由、增加控制器方法和创建主题模板。不要把页面逻辑直接写进入口文件。

// 1. app/routes.php 注册路由
$router->add('GET', '/faq', [SiteController::class, 'faq']);

// 2. SiteController 添加方法
public function faq(): void
{
    $this->renderSite('faq', [
        'seo' => ['title' => 'FAQ']
    ]);
}

// 3. themes/default/faq.php 创建模板
// 使用 h()、url()、asset_url() 输出动态内容
扩展原则:前台路由放在 SiteController,后台管理路由放在 AdminController;共用数据访问逻辑放入 Model;重复渲染逻辑放入主题 functions.php

数据库迁移

数据库结构演进通过 app/Migrations/ 下的时间戳文件管理。系统初始化数据库或发现新迁移时会自动执行,避免手动导入 SQL。

// app/Migrations/20260412120000_create_faqs_table.php
return new class {
    public function up(SQLite3 $db): void
    {
        $db->exec('CREATE TABLE IF NOT EXISTS faqs (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            question TEXT NOT NULL,
            answer TEXT NOT NULL,
            sort_order INTEGER DEFAULT 0,
            created_at TEXT NOT NULL
        )');
    }

    public function down(SQLite3 $db): void
    {
        $db->exec('DROP TABLE IF EXISTS faqs');
    }
};

命名方式

文件名使用时间戳前缀,保证迁移执行顺序稳定,例如 20260617000000_create_app_store_theme_installs_table.php

更新维护

后台程序更新页可查看迁移状态,必要时手动触发待处理迁移。

数据模型

系统围绕外贸官网常见业务建模:用户、站点设置、产品、内容、询盘、留言、媒体、菜单、轮播和更新记录。

模型 / 表 用途 扩展提示
User / users 后台管理员与 Staff 账号,包含角色和权限。 新增后台模块时同步检查权限映射。
Product / products 产品标题、Slug、分类、图片、摘要、SEO 等。 价格区间使用 product_prices 独立表。
PostModel / posts 文章、案例、自定义页面共用内容表。 通过 post_type 区分 postcasepage
Inquiry / inquiries 产品询盘、状态流转、导出和详情查看。 接 CRM 时优先从这里对接。
Slider / sliders 轮播图区块和轮播图片管理。 主题首屏轮播应读取此模型,不要在区块里逐张硬编码。
Menu / menus 多菜单、多级菜单和拖拽排序。 常用 Slug 包括 main-navfooter

主题开发

主题是 SHOPAGG 的主要扩展面。主题目录只负责前台展示和可配置区块,不应修改核心表结构或破坏用户数据。

目录结构

完整主题建议包含 header.phpfooter.phphome.php、产品/文章/案例/页面模板、blocks.phpfunctions.phpstyle.cssscreenshot.jpg

区块系统

blocks.php 返回区块定义,后台用户值保存在 storage/blocks/{theme}.php,用户值覆盖主题默认值。

产品选择器

所有产品展示区块应使用 product_picker,不要让用户在文本框手填产品 ID。

媒体选择器

图片、视频、文件使用 imagemedia 字段;轮播使用 select 选择后台轮播图。

/*
Theme Name: Furniture
Theme URI: https://example.com
Author: Your Name
Description: B2B furniture website theme.
Version: 1.0.0
License: MIT
*/

// blocks.php
return [
    'home_featured' => [
        'label' => '首页 - 热销产品',
        'description' => '使用产品选择器勾选展示商品。',
        'fields' => [
            'heading' => ['type' => 'text', 'label' => '标题', 'default' => 'Hot Products'],
            'product_ids' => [
                'type' => 'product_picker',
                'label' => '勾选商品列表',
                'default' => '',
                'limit' => 8,
                'status' => 'active',
            ],
        ],
    ],
];

安全规范

模板和扩展代码必须尊重系统的安全边界,尤其是后台配置值、媒体路径、URL 和上传文件。

输出转义

文本和属性使用 h(),多行文本使用 nl2br(h(...)),避免直接输出后台配置值。

URL 与媒体

站内链接使用 url('/path'),上传文件或相对路径使用 asset_url($path)

数据操作

不要在主题代码中写数据库、删文件、重置配置或执行破坏性操作。

上传校验

主题 zip 必须包含合法 style.css 元数据和必需模板文件,上传媒体由 MediaManager 统一处理。

<h2><?= h(block('home_about', 'heading')) ?></h2>
<p><?= nl2br(h(block('home_about', 'text'))) ?></p>
<a href="<?= h(url('/products')) ?>">Products</a>
<img src="<?= h(asset_url($image)) ?>" alt="<?= h($title) ?>">

验收清单

新增功能或主题交付前,至少完成语法、字段、数据和响应式检查。以下命令来自项目文档中的主题质量要求。

# PHP 语法检查
find themes/{theme_name} -name '*.php' -print0 | xargs -0 -n1 php -l

# 检查产品选择器、媒体字段和轮播下拉
rg "product_picker|media_type_key|slider_slug|type' => 'select'" themes/{theme_name}/blocks.php

# 检查是否存在可疑静态产品字段
rg "item[0-9]+_(title|image|url)" themes/{theme_name}/blocks.php
主题目录包含必需模板文件,style.css 有主题元数据,screenshot.jpg 存在。
产品展示使用 product_picker,未选择产品时有真实数据兜底或空状态。
图片、视频、文件使用 imagemedia 字段,轮播使用后台轮播数据。
所有动态文本、链接和媒体路径经过转义或辅助函数处理。
移动端、平板、桌面布局不重叠、不溢出,空数据状态不报错。
不删除或覆盖用户已有的 storage/blocks/{theme}.php 配置。