- 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 通过
86 lines
4.9 KiB
Markdown
86 lines
4.9 KiB
Markdown
# 开发规范
|
||
|
||
面向所有为 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 前置到全局视图路径,同名覆盖、缺失回退
|
||
- 语义化 HTML(header/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
|
||
```
|