Entity API

Describes how to define and manipulate content and configuration entities.

Entities, in Drupal, are objects that are used for persistent storage of content and configuration information. See the Information types topic for an overview of the different types of information, and the Configuration API topic for more about the configuration API.

Each entity is an instance of a particular "entity type". Some content entity types have sub-types, which are known as "bundles", while for other entity types, there is only a single bundle. For example, the Node content entity type, which is used for the main content pages in Drupal, has bundles that are known as "content types", while the User content type, which is used for user accounts, has only one bundle.

The sections below have more information about entities and the Entity API; for more detailed information, see https://drupal.org/developing/api/entity

Defining an entity type

Entity types are defined by modules, using Drupal's Plugin API (see the Plugin API topic for more information about plugins in general). Here are the steps to follow to define a new entity type:

  • Choose a unique machine name, or ID, for your entity type. This normally starts with (or is the same as) your module's machine name. It should be as short as possible, and may not exceed 32 characters.
  • Define an interface for your entity's get/set methods, extending either \Drupal\Core\Config\Entity\ConfigEntityInterface or \Drupal\Core\Entity\ContentEntityInterface.
  • Define a class for your entity, implementing your interface and extending either \Drupal\Core\Config\Entity\ConfigEntityBase or \Drupal\Core\Entity\ContentEntityBase, with annotation for @ConfigEntityType or @ContentEntityType in its documentation block.
  • The 'id' annotation gives the entity type ID, and the 'label' annotation gives the human-readable name of the entity type. If you are defining a content entity type that uses bundles, the 'bundle_label' annotation gives the human-readable name to use for a bundle of this entity type (for example, "Content type" for the Node entity).
  • The annotation will refer to several controller classes, which you will also need to define:

  • For content entities, the annotation will refer to a number of database tables and their fields. These annotation properties, such as 'base_table', 'data_table', 'entity_keys', etc., are documented on \Drupal\Core\Entity\EntityType. Your module will also need to set up its database tables using hook_schema().
  • For content entities that are displayed on their own pages, the annotation will refer to a 'uri_callback' function, which takes an object of the entity interface you have defined as its parameter, and returns routing information for the entity page; see node_uri() for an example. You will also need to add a corresponding route to your module's routing.yml file; see the node.view route in node.routing.yml for an example, and see Entity routes below for some notes.
  • Define routing and links for the various URLs associated with the entity. These go into the 'links' annotation, with the link type as the key, and the route machine name (defined in your module's routing.yml file) as the value; see Entity routes below for some routing notes. Typical link types are:

    • canonical: Default link, either to view (if entities are viewed on their own pages) or edit the entity.
    • delete-form: Confirmation form to delete the entity.
    • edit-form: Editing form.
    • admin-form: Form for editing bundle or entity type settings.
    • Other link types specific to your entity type can also be defined.
  • If your content entity has bundles, you will also need to define a second plugin to handle the bundles. This plugin is itself a configuration entity type, so follow the steps here to define it. The machine name ('id' annotation) of this configuration entity class goes into the 'bundle_entity_type' annotation on the entity type class. For example, for the Node entity, the bundle class is \Drupal\node\Entity\NodeType, whose machine name is 'node_type'. This is the annotation value for 'bundle_entity_type' on the \Drupal\node\Entity\Node class. Also, the bundle config entity type annotation must have a 'bundle_of' entry, giving the machine name of the entity type it is acting as a bundle for.
  • Additional annotations can be seen on entity class examples such as \Drupal\node\Entity\Node (content) and \Drupal\user\Entity\Role (configuration). These annotations are documented on \Drupal\Core\Entity\EntityType.

Entity routes

Entity routes, like other routes, are defined in *.routing.yml files; see the Menu and routing topic for more information. Here is a typical entry, for the block configure form:

block.admin_edit:
  path: '/admin/structure/block/manage/{block}'
  defaults:
    _entity_form: 'block.default'
    _title: 'Configure block'
  requirements:
    _entity_access: 'block.update'

Some notes:

  • path: The {block} in the path is a placeholder, which (for an entity) must always take the form of {machine_name_of_entity_type}. In the URL, the placeholder value will be the ID of an entity item. When the route is used, the entity system will load the corresponding entity item and pass it in as an object to the controller for the route.
  • defaults: For entity form routes, use _entity_form rather than the generic _content or _form. The value is composed of the entity type machine name and a form controller type from the entity annotation (see Defining an entity type above more more on controllers and annotation). So, in this example, block.default refers to the 'default' form controller on the block entity type, whose annotation contains:
  controllers = {
    "form" = {
      "default" = "Drupal\block\BlockForm",
  

Defining a content entity bundle

For entity types that use bundles, such as Node (bundles are content types) and Taxonomy (bundles are vocabularies), modules and install profiles can define bundles by supplying default configuration in their config/install directories. (See the Configuration API topic for general information about configuration.)

There are several good examples of this in Drupal Core:

Loading, querying, and rendering entities

To load entities, use the entity storage manager, which is an object implementing \Drupal\Core\Entity\EntityStorageInterface that you can retrieve with:

$storage = \Drupal::entityManager()->getStorage('your_entity_type');
// Or if you have a $container variable:
$storage = $container->get('entity.manager')->getStorage('your_entity_type');

Here, 'your_entity_type' is the machine name of your entity type ('id' annotation on the entity class), and note that you should use dependency injection to retrieve this object if possible. See the Services and Dependency Injection topic for more about how to properly retrieve services.

To query to find entities to load, use an entity query, which is a object implementing \Drupal\Core\Entity\Query\QueryInterface that you can retrieve with:

// Simple query:
$query = \Drupal::entityQuery('your_entity_type');
// Or, if you have a $container variable:
$query_service = $container->get('entity.query');
$query = $query_service->get('your_entity_type');

If you need aggregation, there is an aggregate query avaialable, which implements \Drupal\Core\Entity\Query\QueryAggregateInterface:

$query \Drupal::entityQueryAggregate('your_entity_type');
// Or:
$query = $query_service->getAggregate('your_entity_type');

Also, you should use dependency injection to get this object if possible; the service you need is entity.query, and its methods getQuery() or getAggregateQuery() will get the query object.

In either case, you can then add conditions to your query, using methods like condition(), exists(), etc. on $query; add sorting, pager, and range if needed, and execute the query to return a list of entity IDs that match the query.

Here is an example, using the core File entity:

$fids = Drupal::entityQuery('file')
  ->condition('status', FILE_STATUS_PERMANENT, '<>')
  ->condition('changed', REQUEST_TIME - $age, '<')
  ->range(0, 100)
  ->execute();
$files = $storage->loadMultiple($fids);

The normal way of viewing entities is by using a route, as described in the sections above. If for some reason you need to render an entity in code in a particular view mode, you can use an entity view builder, which is an object implementing \Drupal\Core\Entity\EntityViewBuilderInterface that you can retrieve with:

$view_builder = \Drupal::entityManager()->getViewBuilder('your_entity_type');
// Or if you have a $container variable:
$view_builder = $container->get('entity.manager')->getViewBuilder('your_entity_type');

Then, to build and render the entity:

// You can omit the language ID if the default language is being used.
$build = $view_builder->view($entity, 'view_mode_name', $language->id);
// $build is a render array.
$rendered = drupal_render($build);

Access checking on entities

Entity types define their access permission scheme in their annotation. Access permissions can be quite complex, so you should not assume any particular permission scheme. Instead, once you have an entity object loaded, you can check for permission for a particular operation (such as 'view') at the entity or field level by calling:

$entity->access($operation);
$entity->nameOfField->access($operation);

The interface related to access checking in entities and fields is \Drupal\Core\Access\AccessibleInterface.

The default entity access controller invokes two hooks while checking access on a single entity: hook_entity_access() is invoked first, and then hook_ENTITY_TYPE_access() (where ENTITY_TYPE is the machine name of the entity type). If no module returns a TRUE or FALSE value from either of these hooks, then the entity's default access checking takes place. For create operations (creating a new entity), the hooks that are invoked are hook_entity_create_access() and hook_ENTITY_TYPE_create_access() instead.

The Node entity type has a complex system for determining access, which developers can interact with. This is described in the Node access topic.

See also

Internationalization

Entity CRUD, editing, and view hooks

Functions

Namesort descending Location Description
hook_entity_access drupal/core/modules/system/entity.api.php Control entity operation access.
hook_entity_create_access drupal/core/modules/system/entity.api.php Control entity create access.
hook_ENTITY_TYPE_access drupal/core/modules/system/entity.api.php Control entity operation access for a specific entity type.
hook_ENTITY_TYPE_create_access drupal/core/modules/system/entity.api.php Control entity create access for a specific entity type.

Classes

Namesort descending Location Description
ConfigEntityBase drupal/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php Defines a base configuration entity class.
ConfigEntityListBuilder drupal/core/lib/Drupal/Core/Config/Entity/ConfigEntityListBuilder.php Defines the default class to build a listing of configuration entities.
ConfigEntityStorage drupal/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php Defines the storage class for configuration entities.
ConfigEntityType drupal/core/lib/Drupal/Core/Entity/Annotation/ConfigEntityType.php Defines a config entity type annotation object.
ContentEntityBase drupal/core/lib/Drupal/Core/Entity/ContentEntityBase.php Implements Entity Field API specific enhancements to the Entity class.
ContentEntityDatabaseStorage drupal/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php Defines a base entity controller class.
ContentEntityType drupal/core/lib/Drupal/Core/Entity/Annotation/ContentEntityType.php Defines a content entity type annotation object.
ContentTranslationHandler drupal/core/modules/content_translation/src/ContentTranslationHandler.php Base class for content translation handlers.
EntityConfirmFormBase drupal/core/lib/Drupal/Core/Entity/EntityConfirmFormBase.php Provides a generic base class for an entity-based confirmation form.
EntityForm drupal/core/lib/Drupal/Core/Entity/EntityForm.php Base class for entity forms.
EntityListBuilder drupal/core/lib/Drupal/Core/Entity/EntityListBuilder.php Defines a generic implementation to build a listing of entities.
EntityType drupal/core/lib/Drupal/Core/Entity/Annotation/EntityType.php Defines an Entity type annotation object.
EntityType drupal/core/lib/Drupal/Core/Entity/EntityType.php Provides an implementation of an entity type and its metadata.
EntityViewBuilder drupal/core/lib/Drupal/Core/Entity/EntityViewBuilder.php Base class for entity view controllers.

Interfaces

Namesort descending Location Description
AccessibleInterface drupal/core/lib/Drupal/Core/Access/AccessibleInterface.php Interface for checking access.
ConfigEntityInterface drupal/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php Defines the interface common for all configuration entities.
ContentEntityInterface drupal/core/lib/Drupal/Core/Entity/ContentEntityInterface.php Defines a common interface for all content entity objects.
EntityStorageInterface drupal/core/lib/Drupal/Core/Entity/EntityStorageInterface.php Defines a common interface for entity storage classes.
EntityViewBuilderInterface drupal/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php Defines a common interface for entity view controller classes.

File

drupal/core/modules/system/core.api.php, line 344
Documentation landing page and topics, plus core library hooks.