关于 espocrm
espocrm 是面向 EspoCRM 扩展开发者的开发技能指南,说明元数据、ORM 与服务层的架构规范。重点包括通过 EntityManager 访问数据,并将业务逻辑放在 Services 中。
主要功能
- 01JSON 元数据驱动配置
- 02EntityManager ORM 数据访问
- 03Service 层承载业务逻辑
- 04通过接口实现生命周期 Hooks
- 05缓存重建与扩展开发流程
适用场景
- 01开发自定义 EspoCRM 模块和实体
- 02创建服务、Hooks 与 API 端点
- 03实现复杂查询和自定义字段
- 04打包并分发扩展
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill espocrm安装后在 Claude Code 中输入/espocrm确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonreferences/api-actions.mdarchitecture.mdcommon-tasks.mdcustom-field-types.mddevelopment-workflow.mdextension-packages.mdfrontend-customization.mdhooks-and-services.mdphp-quality-antipatterns.mdselect-builder.mdtesting-debugging.md详细介绍
EspoCRM 开发
概述
EspoCRM 是一个由元数据驱动的 CRM 平台,配置存储在 JSON 文件中,业务逻辑属于 Service,数据访问通过 ORM EntityManager 完成。本技能旨在强制遵循架构模式,避免传递 Container 依赖、绕过服务层或在钩子中实现业务逻辑等常见错误。
何时使用此技能
开发自定义 EspoCRM 模块、实体、关系、钩子、服务、API 端点或集成时启用。**尤其适用于:**使用 ORM(必须使用 EntityManager)、实现业务逻辑(应放在 Service 中)、创建钩子(使用接口)、修改元数据(需要重建缓存)、构建自定义字段类型、使用 SelectBuilder 创建复杂查询、实现自定义 API 操作或打包扩展。
铁律
业务逻辑放在 Service 中,而非钩子中 | 通过 ENTITYMANAGER 访问数据,绝不直接使用 PDO | 绝不将 Container 作为依赖传递
直接访问 Container 或在钩子中编写业务逻辑都违反了架构要求。
核心架构原则
- 元数据驱动:实体定义、布局和字段配置存储在 JSON 中
- 服务层:所有业务逻辑均在 Service 类中实现
- ORM EntityManager:所有数据库操作的集中访问点
- 依赖注入:通过构造函数注入,绝不传递 Container
- 钩子系统:用于验证和副作用的生命周期事件(不用于业务逻辑)
- 仓储模式:通过仓储访问实体
快速入门
-
设置开发环境 - 使用 ext-template,在
src/目录中开发(EspoCRM 7.4+),了解元数据结构:custom/Espo/Modules/{ModuleName}/Resources/metadata/ -
使用 EntityManager 访问数据
use Espo\ORM\EntityManager; public function __construct(private EntityManager $entityManager) {} // Find entity $account = $this->entityManager->getEntityById('Account', $id); // Query with conditions $collection = $this->entityManager ->getRDBRepository('Contact') ->where(['accountId' => $accountId]) ->find(); -
在 Service 中实现业务逻辑
namespace Espo\Modules\MyModule\Services; use Espo\Services\Record; class MyEntity extends Record { public function customAction(string $id, object $data): object { // Business logic here $entity = $this->entityManager->getEntityById($this->entityType, $id); // ... process ... $this->entityManager->saveEntity($entity); return $entity; } } -
为生命周期事件注册钩子
namespace Espo\Modules\MyModule\Hooks\Account; use Espo\ORM\Entity; use Espo\Core\Hook\Hook\BeforeSave; class MyHook implements BeforeSave { public function beforeSave(Entity $entity, array $options): void { // Validation or side effects only if ($entity->isAttributeChanged('status')) { // React to changes } } } -
更改后重建缓存
bin/command rebuild
钩子类型(接口)
EspoCRM 提供 7 种钩子类型——始终使用接口:BeforeSave(保存前验证)、AfterSave(保存后执行副作用)、BeforeRemove(删除前验证)、AfterRemove(删除后清理)、AfterRelate(创建关系)、AfterUnrelate(移除关系)、AfterMassRelate(批量关系操作)。
导航
核心概念
高级主题
- SelectBuilder:使用 SelectBuilder 进行高级查询——复杂查询、联接、聚合和查询优化
- API 操作:创建自定义 API 端点——操作处理程序、请求/响应模式和身份验证
- 自定义字段类型:构建自定义字段类型——后端、前端、元数据和集成
UI 和集成
质量保障
- 测试与调试:单元测试、调试技巧、性能优化和常见陷阱
- PHP 质量反模式:语言层面的健壮性/可变更性缺陷——PHP4 构造函数命名、全大写控制关键字、
goto和空catch块,并附有合规示例(基于 CAST Highlight 代码质量指标,https://doc.casthighlight.com/)
关键模式
正确模式:
✅ Service with injected dependencies
✅ EntityManager for data access
✅ Hooks using interfaces
✅ Type declarations on all methods
✅ Exceptions for error handling
错误模式:
❌ Passing Container as dependency
❌ Direct PDO database access
❌ Business logic in hooks
❌ Hook base classes instead of interfaces
❌ Missing type declarations
应避免的常见错误
- 切勿传递 Container——应注入特定依赖
- 不要绕过 EntityManager——使用 ORM,而不是原始查询
- 业务逻辑不应放在钩子中——应使用 Services
- 始终重建缓存——更改元数据后执行(
bin/command rebuild) - 钩子应使用接口——而不是基类
- 为所有内容声明类型——PHP 7.4+ 要求进行类型声明
- 抛出异常——不要在出错时返回布尔值
与其他技能集成
- systematic-debugging:使用日志和单步调试来调试 EspoCRM 问题
- verification-before-completion:声称已完成前,始终通过重建缓存进行测试
- test-driven-development:为 Services 和钩子编写单元测试
总结
EspoCRM 采用元数据驱动的服务层架构。
了解元数据系统。使用 EntityManager 处理数据。在 Services 中实现业务逻辑。仅使用钩子处理生命周期事件。更改后重建缓存。
这就是 EspoCRM 的做法。