名称: espocrm-development 描述: EspoCRM开发综合指南 - 基于元数据驱动和业务逻辑服务层架构的CRM 版本: 1.0.0 类别: 开发 作者: Claude MPM 团队 许可证: MIT 逐步披露: 入口点: 概要: “使用服务层、ORM EntityManager和基于钩子的业务逻辑进行元数据驱动的CRM开发” 何时使用: “在为EspoCRM开发自定义模块、实体、钩子或集成时” 快速开始: “1. 理解元数据驱动架构 2. 使用EntityManager进行数据访问 3. 在服务中实现业务逻辑 4. 注册钩子以处理生命周期事件 5. 更改后重建缓存” 参考文献: - 架构.md - 开发工作流.md - 钩子与服务.md - 前端定制.md - 常见任务.md - 测试与调试.md 上下文限制: 800 标签:
- espocrm
- php
- crm
- 元数据驱动
- orm 所需工具: []
EspoCRM开发
概述
EspoCRM是一个元数据驱动的CRM平台,其中配置存储在JSON文件中,业务逻辑属于服务层,数据访问通过ORM EntityManager进行。本技能强制执行架构模式,以防止常见错误,如传递容器依赖、绕过服务层或在钩子中实现业务逻辑。
何时使用此技能
在开发自定义EspoCRM模块、实体、关系、钩子、服务、API端点或集成时激活。尤其在以下情况下使用: 使用ORM(需要EntityManager)、实现业务逻辑(应在服务中)、创建钩子(使用接口)、修改元数据(需要重建缓存)或构建自定义字段类型时。
铁律
业务逻辑在服务中,不在钩子中 | 数据访问通过EntityManager,绝不直接使用PDO | 绝不传递容器作为依赖
如果您直接访问容器或在钩子中编写业务逻辑,您就违反了架构。
核心架构原则
- 元数据驱动: 实体定义、布局、字段配置存储在JSON中
- 服务层: 所有业务逻辑在服务类中实现
- ORM EntityManager: 所有数据库操作的中央访问点
- 依赖注入: 构造函数注入,绝不传递容器
- 钩子系统: 生命周期事件用于验证和副作用(而非业务逻辑)
- 仓库模式: 实体通过仓库访问
快速开始
-
设置开发环境 - 使用扩展模板,在
src/目录中工作(EspoCRM 7.4+),理解元数据结构:custom/Espo/Modules/{模块名称}/Resources/metadata/ -
使用EntityManager访问数据
use Espo\ORM\EntityManager; public function __construct(private EntityManager $entityManager) {} // 查找实体 $account = $this->entityManager->getEntityById('Account', $id); // 条件查询 $collection = $this->entityManager ->getRDBRepository('Contact') ->where(['accountId' => $accountId]) ->find(); -
在服务中实现业务逻辑
namespace Espo\Modules\MyModule\Services; use Espo\Services\Record; class MyEntity extends Record { public function customAction(string $id, object $data): object { // 业务逻辑在此 $entity = $this->entityManager->getEntityById($this->entityType, $id); // ... 处理 ... $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 { // 仅用于验证或副作用 if ($entity->isAttributeChanged('status')) { // 响应更改 } } } -
更改后重建缓存
bin/command rebuild
钩子类型(接口)
EspoCRM提供7种钩子类型 - 始终使用接口:BeforeSave(保存前验证)、AfterSave(保存后副作用)、BeforeRemove(删除前验证)、AfterRemove(删除后清理)、AfterRelate(关系创建)、AfterUnrelate(关系移除)、AfterMassRelate(批量关系操作)。
导航
详细信息请参考:
- 架构: 元数据系统、ORM、DI容器、仓库模式和核心架构模式
- 开发工作流: 模块创建、自定义实体、字段、API和扩展开发流程
- 钩子与服务: 服务层实现、钩子类型、依赖注入和业务逻辑模式
- 前端定制: 视图系统、客户端开发和UI定制
- 常见任务: 计划作业、电子邮件、PDF、ACL、工作流和集成模式
- 测试与调试: 单元测试、调试技巧、性能优化和常见陷阱
关键模式
正确模式:
✅ 注入依赖的服务
✅ 使用EntityManager进行数据访问
✅ 使用接口的钩子
✅ 所有方法的类型声明
✅ 异常处理错误
错误模式:
❌ 传递容器作为依赖
❌ 直接PDO数据库访问
❌ 钩子中的业务逻辑
❌ 使用钩子基类而非接口
❌ 缺少类型声明
应避免的常见错误
- 绝不传递容器 - 取而代之注入具体依赖
- 不要绕过EntityManager - 使用ORM,而非原始查询
- 业务逻辑不属于钩子 - 使用服务
- 始终重建缓存 - 在元数据更改后(
bin/command rebuild) - 为钩子使用接口 - 而非基类
- 类型化一切 - PHP 7.4+要求类型声明
- 抛出异常 - 不返回布尔值表示错误
与其他技能的集成
- systematic-debugging: 使用日志和步进调试解决EspoCRM问题
- verification-before-completion: 在声称完成前始终通过缓存重建进行测试
- test-driven-development: 为服务和钩子编写单元测试
总结
EspoCRM是一个基于元数据驱动和服务层架构的CRM。
理解元数据系统。使用EntityManager进行数据操作。在服务中实现业务逻辑。仅将钩子用于生命周期事件。更改后重建缓存。
这就是EspoCRM的方式。