espocrm-development
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEspoCRM Development
EspoCRM开发
Overview
概述
EspoCRM is a metadata-driven CRM platform where configuration lives in JSON files, business logic belongs in Services, and data access happens through ORM EntityManager. This skill enforces architectural patterns to prevent common mistakes like passing Container dependencies, bypassing the service layer, or implementing business logic in hooks.
EspoCRM是一个元数据驱动的CRM平台,配置信息存储在JSON文件中,业务逻辑需在Service类中实现,数据访问通过ORM EntityManager完成。本技能会规范架构模式,避免传递Container依赖、绕过服务层或在钩子中实现业务逻辑等常见错误。
When to Use This Skill
何时使用本技能
Activate when developing custom EspoCRM modules, entities, relationships, hooks, services, API endpoints, or integrations. Use especially when: working with ORM (EntityManager required), implementing business logic (belongs in Services), creating hooks (use interfaces), modifying metadata (requires cache rebuild), building custom field types, creating complex queries with SelectBuilder, implementing custom API actions, or packaging extensions.
在开发自定义EspoCRM模块、实体、关联关系、钩子、服务、API端点或集成时启用。尤其适用于以下场景:使用ORM(必须通过EntityManager)、实现业务逻辑(需在Service中完成)、创建钩子(使用接口)、修改元数据(需重建缓存)、构建自定义字段类型、使用SelectBuilder创建复杂查询、实现自定义API操作,或打包扩展插件。
The Iron Law
铁律
BUSINESS LOGIC IN SERVICES, NOT HOOKS | DATA ACCESS VIA ENTITYMANAGER, NEVER DIRECT PDO | NEVER PASS CONTAINER AS DEPENDENCY
Accessing Container directly or writing business logic in hooks violates architecture.
业务逻辑在Service中实现,而非钩子 | 通过EntityManager访问数据,绝不能直接使用PDO | 绝不传递Container作为依赖
直接访问Container或在钩子中编写业务逻辑均违反架构规范。
Core Architecture Principles
核心架构原则
- Metadata-Driven: Entity definitions, layouts, field configs live in JSON
- Service Layer: All business logic implemented in Service classes
- ORM EntityManager: Central access point for all database operations
- Dependency Injection: Constructor injection, never pass Container
- Hook System: Lifecycle events for validation and side effects (not business logic)
- Repository Pattern: Entities accessed through repositories
- 元数据驱动:实体定义、布局、字段配置均存储在JSON文件中
- 服务层:所有业务逻辑需在Service类中实现
- ORM EntityManager:所有数据库操作的统一访问入口
- 依赖注入:使用构造函数注入,绝不传递Container
- 钩子系统:用于验证和副作用处理的生命周期事件(不处理业务逻辑)
- 仓库模式:通过仓库类访问实体
Quick Start
快速入门
-
Setup Development Environment - Use ext-template, work indirectory (EspoCRM 7.4+), understand metadata structure:
src/custom/Espo/Modules/{ModuleName}/Resources/metadata/ -
Access Data with EntityManagerphp
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(); -
Implement Business Logic in Servicesphp
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; } } -
Register Hooks for Lifecycle Eventsphp
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 } } } -
Rebuild Cache After Changesbash
bin/command rebuild
-
搭建开发环境 - 使用ext-template模板,在目录下工作(适用于EspoCRM 7.4+),熟悉元数据结构:
src/custom/Espo/Modules/{ModuleName}/Resources/metadata/ -
通过EntityManager访问数据php
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(); -
在Service中实现业务逻辑php
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; } } -
注册钩子处理生命周期事件php
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')) { // 响应变更 } } } -
修改后重建缓存bash
bin/command rebuild
Hook Types (Interfaces)
钩子类型(接口)
EspoCRM provides 7 hook types - ALWAYS use interfaces: (validation before save), (side effects after save), (validation before delete), (cleanup after delete), (relationship creation), (relationship removal), (bulk relationship operations).
BeforeSaveAfterSaveBeforeRemoveAfterRemoveAfterRelateAfterUnrelateAfterMassRelateEspoCRM提供7种钩子类型——务必使用接口:(保存前验证)、(保存后副作用处理)、(删除前验证)、(删除后清理)、(关联创建后处理)、(关联移除后处理)、(批量关联操作后处理)。
BeforeSaveAfterSaveBeforeRemoveAfterRemoveAfterRelateAfterUnrelateAfterMassRelateNavigation
导航目录
Core Concepts
核心概念
- Architecture: Metadata system, ORM, DI container, repository pattern, and core architectural patterns
- Development Workflow: Module creation, custom entities, fields, APIs, and extension development process
- Hooks and Services: Service layer implementation, hook types, dependency injection, and business logic patterns
- 架构:元数据系统、ORM、DI容器、仓库模式及核心架构模式
- 开发流程:模块创建、自定义实体、字段、API及扩展插件开发流程
- 钩子与服务:服务层实现、钩子类型、依赖注入及业务逻辑模式
Advanced Topics
进阶主题
- SelectBuilder: Advanced querying with SelectBuilder - complex queries, joins, aggregations, and query optimization
- API Actions: Creating custom API endpoints - action handlers, request/response patterns, and authentication
- Custom Field Types: Building custom field types - backend, frontend, metadata, and integration
- SelectBuilder:使用SelectBuilder进行高级查询——复杂查询、关联查询、聚合及查询优化
- API操作:创建自定义API端点——操作处理器、请求/响应模式及身份验证
- 自定义字段类型:构建自定义字段类型——后端、前端、元数据及集成
UI and Integration
UI与集成
- Frontend Customization: View system, client-side development, and UI customization
- Common Tasks: Scheduled jobs, emails, PDFs, ACL, workflows, and integration patterns
- Extension Packages: Packaging and distributing extensions - manifest files, installation, and versioning
- 前端定制:视图系统、客户端开发及UI定制
- 常见任务:定时任务、邮件、PDF、ACL、工作流及集成模式
- 扩展插件打包:打包与分发扩展插件——清单文件、安装及版本控制
Quality Assurance
质量保障
- Testing and Debugging: Unit tests, debugging techniques, performance optimization, and common pitfalls
- 测试与调试:单元测试、调试技巧、性能优化及常见陷阱
Key Patterns
关键模式
Correct Pattern:
php
✅ Service with injected dependencies
✅ EntityManager for data access
✅ Hooks using interfaces
✅ Type declarations on all methods
✅ Exceptions for error handlingIncorrect Patterns:
php
❌ Passing Container as dependency
❌ Direct PDO database access
❌ Business logic in hooks
❌ Hook base classes instead of interfaces
❌ Missing type declarations正确模式:
php
✅ 注入依赖的Service
✅ 使用EntityManager访问数据
✅ 使用接口的钩子
✅ 所有方法添加类型声明
✅ 使用异常处理错误错误模式:
php
❌ 传递Container作为依赖
❌ 直接使用PDO访问数据库
❌ 在钩子中编写业务逻辑
❌ 使用钩子基类而非接口
❌ 缺少类型声明Common Mistakes to Avoid
需避免的常见错误
- Never pass Container - Inject specific dependencies instead
- Don't bypass EntityManager - Use ORM, not raw queries
- Business logic doesn't belong in hooks - Use Services
- Always rebuild cache - After metadata changes ()
bin/command rebuild - Use interfaces for hooks - Not base classes
- Type everything - PHP 7.4+ requires type declarations
- Throw exceptions - Don't return booleans for errors
- 绝不传递Container - 改为注入具体依赖
- 不要绕过EntityManager - 使用ORM,而非原生查询
- 业务逻辑不应放在钩子中 - 使用Service处理
- 修改后务必重建缓存 - 元数据变更后执行
bin/command rebuild - 钩子使用接口 - 而非基类
- 所有代码添加类型声明 - PHP 7.4+要求类型声明
- 抛出异常 - 不要用布尔值返回错误
Integration with Other Skills
与其他技能的集成
- systematic-debugging: Debug EspoCRM issues using logs and step debugging
- verification-before-completion: Always test with cache rebuild before claiming complete
- test-driven-development: Write unit tests for Services and hooks
- systematic-debugging:通过日志和分步调试排查EspoCRM问题
- verification-before-completion:完成前务必重建缓存并测试
- test-driven-development:为Service和钩子编写单元测试
The Bottom Line
核心要点
EspoCRM is metadata-driven with a service layer architecture.
Understand the metadata system. Use EntityManager for data. Implement business logic in Services. Use hooks for lifecycle events only. Rebuild cache after changes.
This is the EspoCRM way.
EspoCRM是基于元数据驱动、服务层架构的系统。
理解元数据系统,使用EntityManager处理数据,在Service中实现业务逻辑,仅将钩子用于生命周期事件处理,修改后重建缓存。
这就是EspoCRM的正确开发方式。