Entity Adapter Brings Interface-Based Domain Logic to Drupal 11
Developers working with Drupal 11 can use the new Entity Adapter module to put domain-specific behaviour behind interfaces without subclassing entities or replacing their classes. Luca Lusso, lead developer at SparkFabrik and creator of the module, describes the approach in an article on separating domain logic from entity storage details. His central argument is that calling code can depend on methods such as getGroups() rather than knowing which Drupal field, bundle class, or storage mechanism currently supplies the value.
Developers declare an interface and implement it in a plain PHP class marked with the #[AsEntityAdapter] attribute. Adapter classes under src/Entity/Adapter/ are discovered when Drupal's service container is compiled and registered as autowired, non-shared services, allowing constructor injection while avoiding state being carried from one adapted object to another. Calling code requests the required interface through AdapterManager::adapt(); adapters can target a concrete class or an interface such as NodeInterface, and newly added adapters become available after a cache rebuild.
Lusso presents the pattern as useful where the same domain question appears across controllers, templates, access logic, exports, or other services and would otherwise expose field names throughout the codebase. He notes that a conventional injected service can provide the same underlying capability; Entity Adapter instead makes the domain interface the lookup boundary and allows several small behaviours to be attached independently to the same object type. The manager is not technically limited to Drupal entities and can adapt other PHP objects as well. Entity Adapter requires Drupal 11 and PHP 8.3; Lusso provides the architecture, compiler-pass details, examples, and trade-offs in the full technical post.


