docs: 插件/主题开发文档补全新能力

- plugins.md:requires 依赖强制校验行为、filament.post_form/post_table 后台注入(追加写法 + 示例)、Payment payable 商品化约定(payableLabel/payableUrl)、paywall 视图覆盖机制
- themes.md:新增付费墙覆盖章节(membership.paywall / paid-teaser,主题同名文件可覆盖)
- README:插件段落补充依赖校验、后台注入钩子、订单商品化说明
This commit is contained in:
ak
2026-08-12 01:23:37 +08:00
parent 7228a4f14a
commit 4d63c0c683
3 changed files with 80 additions and 3 deletions
+66 -2
View File
@@ -36,6 +36,15 @@ plugins/{vendor}.{name}/
| `requires` | 依赖的其他插件(如会员依赖支付),按 `vendor.name` 引用 |
| `filament_pages` / `filament_resources` | 注册到后台的页面/资源(由 `PluginPages` 汇总,统一归入「插件」导航分组) |
## 依赖管理(requires 强制校验)
- `enable()`:依赖未安装或未启用 → 拒绝启用并提示(后台弹错误通知)
- `disable()` / `uninstall()`:有已启用的插件依赖它 → 拒绝操作,需先停用上层插件
- 应用启动时依赖未满足的插件**跳过 boot**,避免运行时缺底层能力
- 后台插件卡片展示依赖链状态(徽章:✓ 已启用 / ✗ 未安装 / ✗ 未启用),依赖不满足的插件无法启用
插件分层示例:`payment`(支付)→ `membership`(会员,requires payment)→ 你的业务插件(requires membership 或 payment)。上层插件可放心假设底层能力存在。
## ServiceProvider
```php
@@ -74,16 +83,71 @@ class ServiceProvider extends PluginServiceProvider
| Hook | 参数 | 用途 |
|------|------|------|
| `comment.created` | `Comment` | 新评论创建(AI 审核在此监听) |
| `payment.paid` | `Payment` | 支付成功(订阅激活/解锁在此监听 |
| `payment.paid` | `Payment` | 支付成功(`$payment->payable` 分发:订阅激活/解锁) |
| `filament.post_form` | `Schema` | 文章编辑表单追加字段(会员付费设置在此注入) |
| `filament.post_table` | `Table` | 文章列表追加列/操作/过滤 |
### addFilter(hook, callback, priority) — 返回值传给下一个过滤器
| Hook | 签名 | 用途 |
|------|------|------|
| `post.rendered` | `(string $html, Post $post): string` | 文章渲染后处理(付费内容过滤) |
| `post.rendered` | `(string $html, Post $post): string` | 文章渲染后处理(付费内容过滤、paywall |
| `seo.structured_data` | `(array $data): array` | 扩展 JSON-LD 结构化数据 |
| `payment.gateway` | `(array $gateways): array` | 注册支付渠道 |
## 后台注入(Filament 表单 / 表格)
核心资源的表单/表格会触发 `filament.post_form` / `filament.post_table` 两个钩子,插件可追加自己的字段与列,停用插件后字段自动消失,核心零侵入。
> 注意:`Schema::components()``Table::columns()` 都是**整体替换**语义,追加要这样写:
> - 表单:`$schema->components([...$schema->getComponents(), Section::make(...)])`
> - 表格:`$table->pushColumns([...])`
示例(给文章加「付费设置」):
```php
$manager->addAction('filament.post_form', function (Schema $schema) {
$schema->components([
...$schema->getComponents(),
Section::make('付费设置')->columns(3)->collapsible()->schema([
TextInput::make('meta.price')->label('单篇价格(分)')->numeric()->default(0),
Toggle::make('meta.members_only')->label('会员专享'),
]),
]);
});
$manager->addAction('filament.post_table', function (Table $table) {
$table->pushColumns([
TextColumn::make('meta.price')->label('单篇价格'),
IconColumn::make('meta.members_only')->label('会员')->boolean(),
]);
});
```
字段用点号路径(`meta.price`)直接映射到 `Post``meta` JSON。核心保存时会把表单里的 meta 键与已有 meta **合并**,不会覆盖其他插件写入的键(如解锁用户)。
## 订单商品化(可购买实体)
`Payment` 用多态关联指向被购买的实体(`payable_type` / `payable_id`)。支付成功后的 `payment.paid` 钩子按 `$payment->payable` 分发(`instanceof` 判断),**不要**再用字符串解析业务类型。
订单后台的「商品」列与跳转链接由实体上的两个约定方法生成:
```php
public function payableLabel(): string { return '文章:'.$this->title; }
public function payableUrl(): ?string { return route('filament.admin.resources.posts.edit', $this); }
```
已实现:`App\Models\Post`(单篇解锁)、`MembershipPlan`(会员套餐)。新实体(皮肤授权、插件授权、打赏)实现同样两个方法即自动接入订单展示,支付插件零改动。
## 付费内容前台展示(paywall)
会员插件在 `post.rendered` 过滤器里处理两种付费形态:
- 整篇锁定(`meta.members_only`)→ 渲染 `membership.paywall`(封面 + 标题 + 价格 + 单篇解锁/开通会员按钮)
- `[paid]` 付费块 → 替换为 `membership.paid-teaser`(内嵌解锁按钮的提示块)
缺省视图在 `resources/views/membership/`,主题可覆盖:`themes/{name}/views/membership/paywall.blade.php`。视图内可用 `$post`,按钮沿用 `.btn` 类,`.paywall` / `.paid-teaser` 样式两套内置主题已带。
## 迁移
插件迁移放在 `database/migrations/``app/Providers/AppServiceProvider` 启动时自动注册,`php artisan migrate` 会一并执行(无需手动 --path)。