安全(P0) - 发布包签名:新增 scripts/package_keygen.php、scripts/package_verify.php、 ywxapp\service\PackageVerifier;FrameworkService::apply() 解压前强制验签 (ywxapp.framework_package_verify,默认开启) - JWT 收紧:config/jwt.php 移除公开默认密钥,JwtService::assertStrongSecret() 校验非空 / 长度≥32 / 已知弱值;.env.production.example 键名由 JWT_SECRET_KEY 修正为 JWT_SECRET - /api/v1/Article:免登录白名单收窄为只读接口,写操作字段白名单 + assertOwner() 越权校验 - 开发者令牌:查找接口不再回显明文、统一失败文案 + 限流 - TemplateInstaller:文件名白名单 + realpath 归一化 + 目录内断言,修复 Zip Slip;补 use ZipArchive - 后台登录:接入验证码、失败锁定与登录限流(config/ratelimit.php) - 缓存 / Session 驱动可由 .env 覆盖(CACHE_DRIVER / SESSION_TYPE),集群部署改 redis - paycenter 支付日志开关改为 PAY_LOG,不再跟随 APP_DEBUG 工程化 / 交付 - 新增 CHANGELOG.md 与 .env.production.example;composer.lock 入库锁定依赖版本 - 插件离线安装 CLI 增加 --uid,后台上传安装透传 uid,付费插件授权校验可通过 - 授权拒绝文案区分「未携带 uid」与「未找到有效授权」,便于排障 - .gitignore 放行 .env.production.example / .env.addon.example / .gitattributes / public/.htaccess 结构 - appmall 由 addon/appmall 迁移为独立应用 app/appmall(市场 / 开发者中心 / 审核 / 分润)
YwxApp 企业级应用框架
基于 ThinkPHP 6 的多应用 + 插件化企业建站/应用市场框架。框架免费,通过插件与模板商业化变现(Discuz! 式闭环:提交 → 审核 → 上架 → 购买 → 支付 → 授权 → 域名绑定 → 运行期巡检 → 分润提现)。
- 版本:
1.1.1 - 版本单一事实源:
config/ywxapp.php的version(scripts/package_framework.php按它递增并写回)。 修改 README 这里的数字不会改变实际版本,发布前请以配置文件为准,并同步更新CHANGELOG.md。 - 官网:https://www.ywxapp.cn
- 运行环境:PHP >= 8.0(与
composer.json的 require 一致)、MySQL >= 5.7、Redis(可选,用于缓存/队列)
一、特性
| 特性 | 说明 |
|---|---|
| 多应用架构 | frontend(企业站/官网,默认首页)、backend(后台,入口 /admin)、member(会员中心,入口 /user)、api(接口,入口 /api) |
| 插件化体系 | 业务功能以插件形式存在(addon/<name>/),支持在线安装、离线包安装、热重载、一键修复 |
| 应用市场 | 内置 appmall 插件(中心站),对接自托管市场,支持购买、授权、域名绑定、升级巡检 |
| 数据库自愈 | 模型壳内置 ensureSchema(),缺表建表、缺列补列,部署无需手跑 SQL |
| 可视化设计器 | 开发模式下后台「设计插件」可可视化生成插件骨架、配置项、菜单、路由、页面 |
| 前后台皮肤 | 支持模板/皮肤叠加(SkinOverlay),核心后台布局与业务视图分离 |
| 命令行工具 | 插件管理、脚手架生成、健康检测、授权校验、框架升级等全套 CLI |
二、环境要求与准备
- PHP 7.4+(推荐 8.0+),需开启扩展:
pdo_mysql、mbstring、curl、openssl、fileinfo、redis(可选) - MySQL 5.7+ / MariaDB 10.2+
- Composer 2.x
- Web 服务器:Nginx / Apache(推荐 Nginx,已内置伪静态规则)
目录权限
部署后请确保以下目录可写(Linux 下建议 755,运行时目录 777):
runtime/ 运行时缓存、日志
public/static/ 插件静态资源发布目录(安装/重载时写入)
addon/ 插件源码目录
三、安装部署
方式一:Web 安装器(推荐)
项目内置 Web 安装向导,访问站点根目录即可进入:
http://your-domain.com/install/
安装器位于 public/install/,流程:
- 环境检测(PHP 版本、扩展、目录权限)
- 配置数据库连接(读取/生成
.env) - 导入
public/install/install.sql初始化数据表与管理员账号 - 安装完成,务必删除
public/install/目录以防被重复触发
注意:
.env含数据库敏感配置,请勿将其整体覆盖或提交到公开仓库;修改配置请用局部replace_in_file。
方式二:手动部署(已有数据库)
# 1. 安装依赖
composer install --no-dev -o
# 2. 复制环境变量模板并填写
cp .env.example .env # 如无模板则手动创建 .env
# 3. 导入数据库(自行执行 install.sql 或已有库)
# 4. 生成应用密钥并设置运行时权限
php think key:generate # 如支持
chmod -R 755 runtime addon public/static
伪静态(Nginx 示例)
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=/$1 last;
break;
}
}
Apache 已内置 .htaccess。
四、目录结构
ywxapp_dev/
├── addon/ # 插件目录(核心业务以插件交付,共 14 个)
│ ├── appmall/ # 应用市场(中心站:购买/授权/分润/审核/开发者中心)
│ ├── articles/ # 内容管理(CMS)插件
│ ├── blog/ # 博客插件
│ ├── demo/ # 演示插件(脚手架样例,仅供学习)
│ ├── docs/ # 站内文档插件(在前台展示 docs/ 下的文档)
│ ├── download/ # 下载中心插件
│ ├── forum/ # 论坛插件
│ ├── haonav/ # 网址导航插件
│ ├── iot/ # IoT/MQTT 代理插件
│ ├── mqpay/ # 免签支付插件(聚合码 + 商户轮询)
│ ├── seo/ # SEO 优化插件(sitemap/伪静态/路由/内链建议)
│ ├── smsbao/ # 短信宝网关(短信用途)
│ ├── smssend/ # 短信发送插件(聚合发送/日志/成本统计)
│ └── wxchat/ # 微信客服插件
├── scripts/ # 构建工具链(随仓库入库)
│ ├── package_framework.php # 框架整站包(自动排除 config/.env/addon/static)
│ ├── package_addon.php # 单插件包(版本号自动递增)
│ ├── package_all_addons.php # 批量打包插件
│ ├── package_template.php # 模板包
│ ├── submit_template.php # 提交模板
│ ├── framework_files.php # 框架文件清单工具
│ └── framework_files_list.php # 框架文件清单生成器
├── app/ # 多应用(系统级)
│ ├── frontend/ # 企业站/官网(默认首页)
│ ├── backend/ # 后台管理(入口 /admin)
│ ├── member/ # 会员中心(入口 /user)
│ └── api/ # 接口应用(入口 /api)
├── ywxapp/ # 框架核心库
│ ├── AddonBase.php # 插件基类(插件控制器须 use ywxapp\AddonBase)
│ ├── service/ # AppService(启动/命令注册/路由加载)、AddonService、MarketService…
│ ├── model/ # BaseModel(数据库自愈引擎)
│ ├── command/ # 命令行(addon:manage / repair / make / health / license-check / ywxapp:upgrade)
│ └── controller/ # BackendBase / FrontendBase / MemberBase 基类
├── config/ # 全局配置
│ ├── ywxapp.php # 框架主配置(验证码/多语言/API地址/插件开关…)
│ ├── app.php # 多应用配置(default_app / app_map)
│ ├── route.php # 路由
│ └── database.php # 数据库
├── public/ # Web 根目录
│ ├── install/ # Web 安装器(安装后删除)
│ ├── static/ # 静态资源(插件资源发布到此)
│ └── index.php # 入口(已通过 .htaccess DirectoryIndex 锁定)
├── docs/ # 项目文档与 SQL(插件开发指南/打包发布/应用市场商业化等)
├── runtime/ # 运行时(缓存/日志,可写)
├── extend/ # Composer 第三方扩展(框架外引用的库放这里,不走 addon)
├── composer.json
└── README.md
旧版
addons/(复数)已重命名为addon/(单数),核心基类ywxapp/Addons.php已重命名为AddonBase.php,请勿再使用旧的use ywxapp\Addons。
五、多应用与访问入口
config/app.php 配置多应用映射(app_map):
| 访问入口 | 应用目录 | 说明 |
|---|---|---|
/(默认) |
app/frontend |
企业站/官网,default_app=frontend |
/admin/* |
app/backend |
后台管理(登录页 /admin/login/index) |
/user/* |
app/member |
会员中心(登录页 /user/login/index) |
/api/* |
app/api |
接口应用 |
后台升级相关控制器使用 framework 前缀路由(如 framework/check、framework/upgrade),请勿改回 upgrade。
六、插件开发
6.1 插件目录约定
addon/<name>/
├── info.php # 插件元信息(name/title/version/state/config…)
├── menu.json # 后台/会员/前台菜单(backend/member/frontend 三段)
├── route/
│ └── app.php # 路由(写相对组名,由 AppService 自动补全插件前缀)
├── controller/
│ ├── Index.php # 前台控制器
│ ├── backend/Article.php # 后台控制器
│ └── member/Article.php # 会员控制器
├── model/ # 模型(含 ensureSchema() 自愈)
├── service/ # 业务服务
├── view/ # 模板
├── install.sql # 安装 SQL(CREATE TABLE + 种子;禁 -- 注释、禁 \' 转义)
├── upgrade.sql # 升级 SQL
└── config.php # 插件配置(支持 .env 覆盖)
6.2 插件元信息 info.php
return [
'name' => 'blog',
'title' => '博客应用',
'version' => '1.0.2',
'state' => 1, // 1=启用
'url' => '/blog',
'config' => [], // 插件配置项
];
6.3 控制器基类
插件控制器继承框架基类,后台控制器绑定 AdminAuth 须用 static::class:
<?php
namespace addon\blog\controller\backend; // 注意:是 addon\<name>(单数),不是 addons\(复数)
use ywxapp\AddonBase; // 注意:是 AddonBase,不是 Addons
use ywxapp\controller\BackendBase;
class Article extends BackendBase
{
// 禁止无参 fetch(),须 fetch('backend/article/index')
}
6.4 路由与菜单
- 插件
route/app.php写相对组名,由AppService::loadAddonRoutes()的Route::group('<插件名>')补全,不要加前缀或->prefix('api/')。 - 后台 URL 必须用「带点」形式(
blog/backend.article/index),因为Route::group下出现backend层级 TP 会拼成点分隔;斜杠形式恒 404。 - 修改
menu.json后执行php think addon:repair <name> --menu重载菜单。 - 改完路由务必清路由缓存:
Remove-Item runtime/route_list.php,否则旧规则导致 404/500。
6.5 模型与数据库自愈
每个模型壳内置静态 ensureSchema() 自建表,BaseModel 提供 ensureTable/ensureColumn/tableExists/ensureAutoIncrementPk/currentPrefix/ensureTableFromInstall。部署时缺表缺列会自动补齐,无需手跑 SQL。
时间字段统一:
create_at/update_at/delete_at(软删除 int 时间戳,0=未删)。 后台表admin_*→backend_*;用户中心user_*→member_*。
七、命令行工具
命令在 ywxapp/service/AppService.php 的 boot() 中显式注册(config/console.php 的 commands 不生效)。
| 命令 | 说明 |
|---|---|
php think addon:manage <name> -a develop |
开发者模式安装(源码已在 addon/<name>,原地建表/注入菜单/启用,免打包) |
php think addon:manage <name> -a install [--local=<zip>] [--force] |
在线/离线安装插件 |
php think addon:manage [<name>] -a reload [--force] [--status] |
热重载插件(重导菜单/资源) |
php think addon:repair <name> [--menu|--db|--config] |
一键修复:菜单重载 + 数据库自愈 + 配置补全;<name> 可为 all |
php think addon:make <name> -a <action> [--name=<类>] |
脚手架:生成 controller/model/middleware/validate/event/listener/service/subscribe |
php think addon:crud <name> -t <表名> [--name=<类>] |
按数据表一键生成后台 CRUD(model/controller/view/js + 路由 + 菜单权限) |
php think addon:crud --app=backend -t <表名> |
同样生成,但落到核心后台 app/backend(权限直写 backend_power) |
php think db:backup [-t <表名>] [--keep=<N>] |
数据库备份(纯 PHP 实现,可挂定时任务) |
php think attachment:clean [--delete] |
清理没有附件记录的孤儿文件(默认只统计) |
php think addon:health |
插件健康检测(依赖/表/菜单完整性) |
php think addon:license-check |
运行期授权校验 |
php think ywxapp:upgrade |
框架在线升级(framework 路由配套) |
php think app |
应用生成器(生成多应用骨架:frontend/backend/member/api) |
php think workerman:gateway |
Workerman GatewayWorker(配合 addon/wxchat 客服通道) |
php think iot / iot:acltest / iot:probe |
addon/iot 套件命令(综合 / ACL 自检 / 链路探测) |
php think haonav:checklinks |
addon/haonav 死链/健康度巡检 |
php think wxchat:server |
addon/wxchat GatewayWorker 长连服务(-a start/stop/status/reload) |
命令通过
ywxapp/service/AppService.php::boot()的commands()注册, 插件级命令在其自身addon/<name>/command/*.php中声明setName(...), AppService 启动时统一由Console::starting()回调加载并校验类名(坏类名/非 Command 子类会被addCommands自动跳过,单个插件出错不影响整体)。 早期(≤4.0)的config/console.php注册表为空数组[[]],无效。
# 安装 blog 插件(开发者模式)
php think addon:manage blog -a develop
# 修复所有插件的菜单与数据库
php think addon:repair all
# 用脚手架生成一个后台控制器
php think addon:make blog -a controller --name=backend/Stat
八、后台使用与配置
- 后台入口:
/admin(映射app/backend),登录页/admin/login/index - 会员中心:
/user,登录页/user/login/index - 主配置:
config/ywxapp.phpusercenter:是否开启前台会员中心login_captcha/user_register_captcha:登录/注册验证码api_url:应用市场 API 地址(中心站留空或market_mode=center,客户机指向中心站域名)addon_developer:开发模式开关(开启后后台出现「设计插件」入口)addon_license_check:运行期授权校验开关lang_switch_on:多语言开关
中心站 / 客户机模式
由 config/ywxapp.php 的 market_mode(auto/center/client)决定,auto 时按 api_url 推导(空=中心站,指向他机=客户机)。解耦设计:中心站逻辑全在 app/appmall/(原 addon/appmall 已迁为普通应用,URL 前缀 /appmall 不变),ywxapp/ 及 app/ 下其它应用禁直读 appmall_* 表;核心控制器只做分发(客户机 → 远程服务,中心站 → MarketService,缺失 → 503)。
九、打包与分发
构建工具链全部位于 scripts/(随仓库入库,请勿加入 .gitignore):
- 单插件包:
scripts/package_addon.php(版本号自动递增) - 批量插件包:
scripts/package_all_addons.php(一次性把全部 enabled 插件打成 zip) - 框架整站包:
scripts/package_framework.php(排除config/、.env、addon/、public/static/<插件名>/) - 模板包:
scripts/package_template.php - 模板提交:
scripts/submit_template.php - 文件清单:
scripts/framework_files.php/scripts/framework_files_list.php
升级流程:AddonService::onlineUpgrade($version);importsql 仅放行 CREATE TABLE/INSERT,拒绝 ALTER/DROP(旧库迁移须手动 RENAME TABLE)。
十、常见问题(FAQ)
Q1:后台菜单点了 404?
先确认 menu.json 的 jump/路由用的是「带点」形式(blog/backend.article/index),再 php think addon:repair <name> --menu,最后清路由缓存 Remove-Item runtime/route_list.php。
Q2:插件装完页面破图 / 资源 404?
执行 php think addon:manage <name> -a reload 重新发布静态资源到 public/static/<name>/。
Q3:数据库表不存在报错?
模型壳的 ensureSchema() 通常会自动建表;若仍报错执行 php think addon:repair <name> --db。
Q4:改了插件代码不生效?
多半是路由缓存。Remove-Item runtime/route_list.php 后重试;生产环境关闭 APP_DEBUG 前请先清缓存。
Q5:PHP 文件上传后报「已发送头」/ 乱码?
write_to_file 可能产生 UTF-8 BOM,上线前请去 BOM(或 php -l 校验)。
十一、许可与商业化
- 框架核心基于 ThinkPHP 协议,免费使用。
- 商业化通过
app/appmall应用市场分发插件与模板,支持购买、授权、域名绑定、分润提现。 - 详细商业化与运营文档见
docs/。
上线与运维文档索引
| 文档 | 用途 |
|---|---|
docs/生产部署清单.md |
生产环境部署必读:Nginx/PHP 配置、.env 安全项、目录权限、定时任务、常驻进程、多副本注意事项、上线后 10 分钟自检 |
docs/打包与发布指南.md |
发版流程:三种产物(整包/补丁/安装包)、发布包签名、热点补丁模式、发版 Checklist |
CHANGELOG.md |
版本变更记录与 Breaking 变更说明 |
发布前必做:
php scripts/package_keygen.php(一次)→php scripts/package_framework.php <版本>→ 确认三个包的sign均为「已签名」→php scripts/package_verify.php <zip> <版本>验签。
© 2026-2036 YwxApp. All rights reserved. https://www.ywxapp.cn