关于 phoenix-contexts
这是一项用于规划 Phoenix context 结构与数据访问边界的参考技能,涵盖 scope 感知 API、跨 context 引用和事务副作用,并提供拆分或合并 context 的判断依据。
主要功能
- 01定义 context 边界与模块结构
- 02在 Phoenix 1.8+ context API 中使用 scope
- 03保持 controller 和 LiveView 精简
- 04通过 ID 处理跨 context 引用
- 05使用 Ecto.Multi 管理副作用
适用场景
- 01围绕有界上下文规划数据访问
- 02为 context 函数添加调用者 scope
- 03协调带副作用的事务
- 04判断是否拆分 context
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oliver-kriska/ claude-elixir-phoenix --skill phoenix-contexts安装后在 Claude Code 中输入/phoenix-contexts确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/context-patterns.mdjson-api-patterns.mdplug-patterns.mdrouting-patterns.mdscopes-auth.md详细介绍
Phoenix 上下文参考
Ash 项目:
Ash.Domain可替代 Phoenix 上下文,用于数据访问——请使用ash-framework技能。上下文边界和 PubSub 模式仍然适用。
设计和实现 Phoenix 上下文(有界上下文)的参考。
铁律——绝不可违反
- 上下文拥有自己的数据——绝不可通过 Repo 直接查询其他上下文的 schema
- 必须使用作用域(Phoenix 1.8+)——每个上下文函数都必须将 scope 作为第一个参数
- 控制器和 LiveView 必须精简——控制器负责转换 HTTP,业务逻辑留在上下文中
- schema 中不得有副作用——使用
Ecto.Multi执行包含副作用的事务
上下文结构
lib/my_app/
├── accounts/ # Context directory
│ ├── user.ex # Schema
│ ├── scope.ex # Scope struct (Phoenix 1.8+)
├── accounts.ex # Context module (public API)
Phoenix 1.8+ 作用域(至关重要)
上下文函数将 scope 作为第一个参数,以便查询根据调用方进行筛选:
def list_posts(%Scope{} = scope) do
from(p in Post, where: p.user_id == ^scope.user.id)
|> Repo.all()
end
def create_post(%Scope{} = scope, attrs) do
%Post{user_id: scope.user.id}
|> Post.changeset(attrs)
|> Repo.insert()
|> broadcast(scope, :created)
end
快速决策
何时拆分上下文?
- 模块超过约 400 行
- 函数不共享领域术语
- 理论上可以成为独立的微服务
- 团队成员可以独立负责
何时保留在一起?
- 资源共享词汇和领域概念
- 函数经常一起操作相同数据
- 拆分会导致过多的跨上下文调用
跨上下文引用
# ✅ Reference by ID, convert at boundary
def create_order(%Scope{} = scope, user_id, product_ids) do
with {:ok, user} <- Accounts.fetch_user(scope, user_id) do
do_create_order(scope, user.id, product_ids)
end
end
# ❌ Reaching into other context's internals
alias MyApp.Accounts.User # Don't do this
Repo.all(from o in Order, join: u in User, ...) # Don't query other schemas
反模式
| 错误 | 正确 |
|---|---|
服务对象(UserCreationService) | 上下文函数(Accounts.create_user/2) |
| 用于包装 Repo 的仓储模式 | Repo 本身就是仓储 |
| 在控制器中直接调用 Repo | 委托给上下文 |
| 带有副作用的 schema 回调 | 使用 Ecto.Multi |
版本说明
- Phoenix 1.8+:使用内置的
%Scope{}结构体作为授权上下文 - Phoenix 1.7:需要手动设置授权上下文(参见
${CLAUDE_SKILL_DIR}/references/scopes-auth.md中的 “Pre-Scopes Patterns”)
参考资料
详细模式请参见:
${CLAUDE_SKILL_DIR}/references/context-patterns.md- 完整的上下文模块、PubSub、Multi 和跨边界模式${CLAUDE_SKILL_DIR}/references/scopes-auth.md- Scope 结构体、多租户、授权和 plugs${CLAUDE_SKILL_DIR}/references/routing-patterns.md- 已验证路由、管道和 API 身份验证${CLAUDE_SKILL_DIR}/references/plug-patterns.md- 函数/模块 plugs、放置位置和守卫${CLAUDE_SKILL_DIR}/references/json-api-patterns.md- JSON 控制器、FallbackController 和 API 身份验证
评论
支持 Markdown