Initial baseline: LaraBlog core with plugin commerce surface.
Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
This commit is contained in:
+111
@@ -0,0 +1,111 @@
|
||||
# 插件开发指南
|
||||
|
||||
## 目录格式
|
||||
```
|
||||
plugins/{vendor}/{name}/
|
||||
plugin.json
|
||||
README.md
|
||||
database/migrations/ # 可选
|
||||
resources/views/ # 可选
|
||||
src/PluginServiceProvider.php
|
||||
```
|
||||
|
||||
### plugin.json
|
||||
```json
|
||||
{
|
||||
"name": "vendor/my-plugin",
|
||||
"title": "显示名",
|
||||
"version": "1.0.0",
|
||||
"description": "说明",
|
||||
"provider": "Plugins\\Vendor\\MyPlugin\\PluginServiceProvider",
|
||||
"requires": ["larablog/payment"],
|
||||
"optional": [],
|
||||
"docs": "README.md"
|
||||
}
|
||||
```
|
||||
|
||||
- `requires`:硬依赖,未启用时 `PluginManager::enable` 会拒绝
|
||||
- `docs`:相对插件根目录的说明文件,后台卡片可查看;只允许指向插件目录内(`..`、绝对路径、软链越界会被拒绝)
|
||||
|
||||
在 `composer.json` → `autoload.psr-4` 注册命名空间,然后:
|
||||
|
||||
```bash
|
||||
composer dump-autoload
|
||||
php artisan plugins:sync
|
||||
# 启用后如有迁移:
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
## 生命周期
|
||||
1. `PluginManager::discover()` 扫描磁盘
|
||||
2. `plugins:sync` / 后台同步写入 `plugins` 表
|
||||
3. 启用后 `registerEnabledProviders()` 注册 Provider(Filament panel 构建前也会注册,以便 `Panel::configureUsing`)
|
||||
4. Provider `register()` / `boot()` 内挂 Hook、路由、Filament Resource、迁移
|
||||
|
||||
## Hook 类型
|
||||
| 方法 | 用途 |
|
||||
|---|---|
|
||||
| `listen` + `dispatch` | 事件通知(如 `comment.created`、`order.paid`) |
|
||||
| `gather` | 字符串管道(主题槽 `theme.*`) |
|
||||
| `collect` | 数组合并(Filament 组件/列/动作) |
|
||||
| `filter` | 值管道(表单 mutate 等;每个监听器可替换值) |
|
||||
| `listeners` | 取回监听器自行折叠(`article.access` 用它保证只许变严) |
|
||||
|
||||
```php
|
||||
use App\Domain\Plugin\Hook;
|
||||
|
||||
Hook::listen('comment.created', function (Comment $comment): void { /* ... */ });
|
||||
Hook::listen('theme.sidebar', function (string $html): string {
|
||||
return $html.'<p>侧栏注入</p>';
|
||||
});
|
||||
Hook::listen('filament.article.form', function (array $components): array {
|
||||
return [/* Section / Field */];
|
||||
});
|
||||
Hook::listen('article.access', function (AccessDecision $decision, array $ctx): AccessDecision {
|
||||
return $decision->tightenWith(/* 更严决策 */);
|
||||
});
|
||||
```
|
||||
|
||||
## 约定扩展点(首批)
|
||||
| 点 | 类型 | 用途 |
|
||||
|---|---|---|
|
||||
| `theme.*` | gather | 前台主题槽 |
|
||||
| `article.access` | fold | 收紧阅读权限;核心逐个 `tightenWith` 折叠,放宽无效、非 `AccessDecision` 返回值忽略 |
|
||||
| `filament.article.form` | collect | 文章表单追加组件 |
|
||||
| `filament.article.table.columns` | collect | 文章表追加列 |
|
||||
| `filament.article.actions` | collect | 文章动作 |
|
||||
| `filament.article.mutate_before_fill` | filter | 编辑回填 |
|
||||
| `filament.article.mutate_before_save` | filter | 保存前改/剥数据 |
|
||||
| `filament.article.after_save` | dispatch | 保存后写插件表 |
|
||||
| `order.paid` / `order.refunded` | dispatch | 支付插件发出 |
|
||||
|
||||
## 三类注入
|
||||
1. **UI**:前台主题槽 + 后台 Filament collect
|
||||
2. **功能**:access / lifecycle Hook
|
||||
3. **数据**:插件自有 migration/model,用外键或 `product_type`+`product_id` 关联
|
||||
|
||||
## Filament 页面/资源
|
||||
放在插件命名空间,于 `register()` 中:
|
||||
|
||||
```php
|
||||
Panel::configureUsing(function (Panel $panel): void {
|
||||
if ($panel->getId() !== 'admin') return;
|
||||
$panel->resources([OrderResource::class])->pages([SettingsPage::class]);
|
||||
});
|
||||
```
|
||||
|
||||
Resource / Page 需用 `canAccess` / `shouldRegisterNavigation` 检查插件已启用。
|
||||
|
||||
## 后台
|
||||
- 「插件」页:卡片启停、依赖展示、使用说明
|
||||
- 可选:继续用核心 `PluginSkeletonPage` 做极简占位
|
||||
|
||||
## 内置插件
|
||||
| 插件 | 状态 |
|
||||
|---|---|
|
||||
| `larablog/ai-comment-moderation` | 可运行 |
|
||||
| `larablog/payment` | Stub 订单/权益可跑通 |
|
||||
| `larablog/paid-content` | 文章付费(依赖 payment) |
|
||||
| `larablog/membership` | 骨架 |
|
||||
| `larablog/plugin-marketplace` | 骨架 |
|
||||
| `larablog/theme-marketplace` | 骨架 |
|
||||
Reference in New Issue
Block a user