Files
ak 8fdf8dbb4b docs: 开发规范/教程/demo 全套 + 修复插件运行期自动加载缺口
- demo 插件 plugins/demo.hello-world:演示短代码过滤器、comment.created 钩子、路由+命名空间视图、迁移+模型、后台设置页、filament.post_form 表单注入
- demo 主题 themes/demo:最小可运行主题(覆盖 partials + 绿色系样式)
- 教程 docs/tutorial-plugin.md / docs/tutorial-theme.md(10 分钟上手);规范 docs/development.md(代码/插件/主题/队列/测试/提交)
- README 增加开发者文档导航与上手示例
- 修复关键缺口:插件类原来靠 composer.json 硬编码加载,第三方 ZIP 安装的插件无法加载;现改为启动时扫描 plugins/*/src 运行期注册 PSR-4(register 阶段,保证 Filament 面板解析插件页面前就绪),composer.json 移除硬编码
- 测试:demo 插件 3 个用例 + demo 主题渲染;全量 89 通过
2026-08-12 17:26:34 +08:00

86 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 开发规范
面向所有为 LaraLog 写代码的人(核心 / 插件 / 主题作者)。教程见 `tutorial-plugin.md``tutorial-theme.md`,配套示例见 `plugins/demo.hello-world/``themes/demo/`
## 1. 代码规范
- **PHP 8.2+**,所有文件以 `declare(strict_types=1);` 开头
- 命名空间:核心 `App\...`;插件 `Plugins\{Vendor}\{Name}\...`Vendor/Name 用 `Str::studly` 规则)
- 文件命名:类文件与类名一致(PSR-4 自动加载)
- 方法/属性/变量:`camelCase`;常量:`UPPER_SNAKE`;数据库表:`snake_case`
- 中文文案直接写在代码/语言包中(本项目默认中文,不硬编码英文 UI)
- 不写无意义注释;只在「为什么」不明显处加一行注释
- **安全红线**:不提交 `.env`、密钥、证书;用户输入一律 `e()` 转义或框架验证;数据库操作用 Eloquent/查询构造器(防注入)
## 2. 目录约定
```
app/Blog/ # 前台域模块:Controllers / Jobs / Services / Support / View
app/Filament/ # 后台资源与页面
plugins/ # 插件,目录名 vendor.name
themes/ # 主题,目录名即主题名
routes/web.php # 前台规范路由;routes/legacy.php 老 URL 301(新增老入口兼容放这里)
```
## 3. 插件规范(详见 docs/plugins.md
- 目录 `plugins/{vendor}.{name}/`**目录名是插件唯一标识**
- 类自动加载:系统启动时扫描 `plugins/*/src` 注册 PSR-4`Plugins\{Vendor}\{Name}`),**无需改 composer.json**
- `plugin.json` 必填:`title/version/description/author/type/provider`;可选 `usage/requires/filament_pages/filament_resources`
- 入口类 `src/ServiceProvider.php` 继承 `App\Blog\Support\PluginServiceProvider`**不要命名为 PluginServiceProvider**
- 依赖声明在 `requires``vendor.name`),系统强制校验:依赖未启用不能启用本插件;停用/卸载被依赖者阻止
- 后台扩展**一律走钩子注入**`filament.post_form` / `filament.post_table`),禁止改核心资源文件
- 可购买实体约定:实现 `payableLabel(): string``payableUrl(): ?string` 即接入订单展示(支付插件零改动)
- 插件视图放插件目录并用 `loadViews()` 注册命名空间;前台页面用 `@include('partials.header')` 复用主题公共片段
### 钩子清单
| Hook | 类型 | 参数 | 用途 |
|------|------|------|------|
| `post.rendered` | filter | `(string $html, Post): string` | 文章渲染后处理 |
| `comment.created` | action | `Comment` | 新评论创建 |
| `payment.paid` | action | `Payment` | 支付成功分发 |
| `filament.post_form` | action | `Schema` | 文章表单注入 |
| `filament.post_table` | action | `Table` | 文章表格注入 |
| `seo.structured_data` | filter | `(array): array` | JSON-LD 扩展 |
| `theme.inject.{point}` | filter | `(string): string` | 注入点追加 HTML |
> `Schema::components()` / `Table::columns()` 是**替换**语义:表单用 `[...$schema->getComponents(), Section::make(...)]` 合并,表格用 `pushColumns()`。
## 4. 主题规范(详见 docs/themes.md
- 目录 `themes/{name}/``theme.json` 必填;views 前置到全局视图路径,同名覆盖、缺失回退
- 语义化 HTMLheader/nav/main/aside/footer/article/time)是 SEO 要求,不是可选项
- 保留注入点 `@stack('theme:xxx')`,并尽量在 theme.json 声明 `inject_points`
- 必须有移动端断点(≤768px 两栏改单栏)
- 资产开发期流式返回、生产 `theme:publish`
## 5. 队列任务规范
- 实现 `App\Blog\Jobs\AiJob` 接口(`handle(LlmClient)` 由容器注入)+ `ShouldQueue`
- 入队 `dispatch(new XxxJob($id))->onQueue('ai')`
- 消费者二选一:`php artisan workerman:serve`(常驻+WS)或 `php artisan queue:work --queue=default,ai`(等价,见 docs/deploy.md
- LLM 一律走 `LlmClient`OpenAI 兼容,base_url/key/model 可配),不要直连第三方 SDK
## 6. 测试规范
- 新增功能必须配 Feature 测试(`tests/Feature/`),跑 `php artisan test` 全绿再提交
- 示例参照:`PluginDependencyTest`(依赖校验)、`PostFormInjectionTest`(表单注入)、`MarketPurchaseTest`(商城购买流)、`MembershipFlowTest`(会员/支付流)
- 测试用 RefreshDatabase + 沙箱,**不触碰真实支付/真实 LLM 凭据**
## 7. 提交规范
- 一次提交一件事,信息用中文描述「做了什么 + 为什么」
- 不提交:`.env`、密钥/证书、`storage/media-library/temp/`、构建产物
- 完成后更新对应 `docs/` 文档
## 8. 常用命令速查
```bash
php artisan test # 全量测试
php artisan dev:watch # 开发热重载(改插件/核心代码自动重启 workerman)
php artisan migrate # 插件迁移自动加载
php artisan workerman:serve start # 队列消费者 + WebSocket
php artisan theme:publish # 主题资产发布到 public
```