Entity API

The Entity API is the set of Drupal core classes and interfaces for creating, loading, querying, saving and deleting entities such as nodes and users.

Learn DrupalDrupal glossary

The Entity API is the part of Drupal core that lets code create, load, query, save and delete entities in one consistent way, whatever the entity type. It also covers how entity types are defined, how access to an entity is checked and which hooks fire around saving and loading. Its central service is the entity type manager.

How the Entity API works in Drupal 11

Four pieces do most of the work.

  • The entity type manager (service entity_type.manager, interface EntityTypeManagerInterface). It returns the definition of an entity type with getDefinition() and builds its handlers: getStorage(), getViewBuilder(), getAccessControlHandler(), getListBuilder() and getFormObject().
  • The storage handler (EntityStorageInterface). create() builds an entity in memory without saving it. load(), loadMultiple() and loadByProperties() read entities, save() and delete() write, and getQuery() starts an entity query. loadByProperties() runs no access checks.
  • The entity (EntityInterface). Every entity has id(), uuid(), bundle(), label(), save(), delete() and toUrl(), and access() checks an operation for a user.
  • Hooks. Core documents hooks such as hook_entity_presave(), hook_entity_insert(), hook_entity_update(), hook_entity_delete() and hook_entity_access(), each with a variant for one entity type that follows the pattern hook_ENTITY_TYPE_presave(). See hook system.

Access results can be allowed, forbidden or neutral, and a forbidden result overrides an allowed one from another module. Drupal.org describes the system as the way to run create, read, update and delete operations on entities with generic methods shared across types, plus type-specific methods such as getTitle() on a node.

Example

A class that uses dependency injection stores the manager and asks it for the node storage:

$storage = $this->entityTypeManager->getStorage('node');
        $ids = $storage->getQuery()
          ->condition('status', 1)
          ->condition('type', 'article')
          ->accessCheck(TRUE)
          ->execute();
        $articles = $storage->loadMultiple($ids);

This finds published articles, then loads them. The query returns IDs only; loadMultiple() turns them into entities.

Common mistakes

  • Leaving out accessCheck(). The SQL entity query throws a QueryException that says queries must explicitly set whether they are access checked.
  • Forgetting save(). A created entity is not stored until you call it.
  • Using static calls in classes. Drupal.org advises against Node::load() in object-oriented code, because injected storage keeps the code decoupled and testable.
  • Expecting loadByProperties() to respect permissions. It runs without access checks, so check access yourself before showing results.

For marketing and content teams

The Entity API has no screen of its own. Editors work in the forms of each entity type, such as the node edit form. Developers use the API to build custom features that read or write the same content, users and terms.

Sources

Questions about Entity API

Get the storage for the node entity type from the entity type manager, then call load() with the ID. In object-oriented code, Drupal.org advises injecting the entity type manager (service entity_type.manager) rather than calling static methods such as Node::load().

The SQL entity query implementation throws a QueryException when the query does not say whether it is access checked. Add accessCheck(TRUE) to respect the current user's permissions, or accessCheck(FALSE) to skip them.

No. The entity type manager is one service in the Entity API. It hands out the storage, view builder, access control handler and other handlers for each entity type, while the API as a whole also covers the entity interfaces, queries, access checks and hooks.

Related terms

All Drupal terms from A to Z