Series Overview & ToC | Previous Article | Next Article


Today we will take a step back from reviewing the Migrate API. Instead, we will have an overview of content and configuration entities in Drupal 10. This is important for two reasons. First, the Migrate API leverages the Entity API to create configuration and store content in Drupal via the destination plugins. Second, in the context of a migration, we will be creating Drupal 10 content and configuration entities based on Drupal 7 data, so having a high-level overview of how Drupal entities work will be very useful when we need to write custom migrations.

Configuration Entities

Drupal 10 configuration entities define the site structure. Some configuration entities included in Drupal core are:

In the contributed modules space we also have:

As part of Drupal commerce, some of the available configuration entities are:

Configuration entities are managed by the Configuration API. This will become important to understand when we work on migrating configuration. In a nutshell, Drupal’s active configuration is stored in the database, namely the config table. For version control and deployment, configuration is exported to and imported from YAML files. This can be done via the administrative interface or using Drush configuration commands.

As we discussed in the first article, there are multiple migration strategies. An automated migration of configuration is optional. If not done automatically using the Migrate API, the configuration will have to be created manually. This is often the case when the site structure is going to be significantly different between the Drupal 7 and Drupal 10 sites.

A good way to imagine configuration entities is as a bucket you can put data into. For example, you can create nodes (content entities) of type article (configuration entity). While not strictly necessary, it is possible to have a site configuration complete before adding any content. However, that is rarely the case as, even when there is a clear plan of action in the beginning, project requirements often change and the site configuration needs to be modified.

For large projects in particular, it is not feasible to wait for all the site configuration to be completed before content migrations begin. In cases like this, it is common to have a group of developers building the site’s configuration. As configuration is added to the site, another group of developers start working on migrating the content. Communication is key during this process. If changes are introduced to the content model, the migrations need to be updated accordingly.

Content Entities

Drupal 10 content entities store data to be displayed on the site. Some content entities included in Drupal core are:

In the contributed modules space we have:

As part of Drupal commerce, some of the available configuration entities are:

Each content entity has a set of properties, known as base field definitions, to hold data. For instance, the node entity has the nid property to store the node id, vid to store the revision id, type to store the node type it belongs to, status to indicate whether the node is published or not, uid to store a reference to the user who created the node, and title to store the node’s title. Note that while some property names might be the same across entities, they can be used to store different information. For example, in the case of the taxonomy term entity, the vid property stores the vocabulary the term belongs to. And in the user entity, the status property indicates whether a user account is active or blocked.

Technical note: Knowing all properties available for a content entity might not be straightforward. You can start by looking at the baseFieldDefinitions method of the class that defines the content entity to learn how the return value is constructed. There might be calls to the same method in the parent class. Some properties, like published, are added via traits. Others, like workspace, are added dynamically based on which modules are enabled on the site. You can search for online references such as these articles: properties for general content entities and for commerce related ones. For a complete list based on your current installation, you can use the entity_field.manager service to get information about an entity’s base field definitions.

The following Drush command will show the properties for the node entity:


drush php:eval 
"print_r(array_keys(\Drupal::service('entity_field.manager')->getBaseFieldDefinitions('node')));"

Content entities can be fieldable. Drupal fields are used to store discrete pieces of data which can be used for displaying, filtering, and sorting purposes. The main difference with entity properties is that fields are user-defined. That is, the developers working on the content model determine what information to collect and attach fields to entities accordingly, usually from the user interface. Examples of field types include: number, text, email, link, file, and address. Each field type can have multiple widgets and formatters, which determine how the data is collected and presented, respectively. Additionally, each field can have validation rules to enforce data integrity. All of this is provided by the Field API.

Content entities can also have bundles. A bundle is an abstraction used to define variations of an entity type. Bundles allow grouping entities that share similar characteristics or describe the same idea. For the node entity, each content type is a bundle. For the taxonomy term entity, each vocabulary is a bundle. Because each entity bundle can have a different set of fields, you can think of them as templates to collect information.

Note: some entities, like users and files, do not allow bundles by default. Contributed modules can change this behavior. For example, the User bundle module allows bundles to be associated with users. For reference, the table below lists some content entities with a subset of their entity properties and lists whether they are fieldable and allow bundles.

Entity Table

Entity type Entity properties (base field definitions) Fieldable? Allows bundles?
Node nid, vid, langcode, type, status, uid, title, created Yes Yes - content type
Term tid, langcode, vid, status, name, description, weight, parent Yes Yes - vocabulary
Media mid, vid, langcode, bundle, status, uid, name, thumbnail Yes Yes - media type
BlockContent id, langcode, type, status, info Yes Yes - custom block type
Comment cid, langcode, comment_type, status, uid, pid, subject, name Yes Yes - comment type
User uid, langcode, name, pass, mail, timezone, status, roles Yes No, out of the box.
Yes, with User bundle module.
File fid, langcode, uid, filename, uri, filemime, filesize, status No No

From a migration standpoint, having a clear understanding of the content model of the source and destination sites is key. We will also observe that a migration project consists of multiple individual migrations. Each migration should only create one type of entity. That is, a single migration should not create nodes and users at the same time. While not strictly necessary, it is common to have a single migration for each entity bundle. For instance, in the case of nodes, we would have one migration for basic pages and a different one for articles.

The main reason for this is that each content type has a different set of fields. If multiple bundles of the same entity do not have fields, they can share a migration. For example, all taxonomy terms that belong to vocabularies without fields attached to them can share a migration.

Another reason to understand how entities work is that many migration projects require changes to the content model between Drupal 7 and Drupal 10. For example, getting files into media entities. Converting nodes to users. Porting data from Drupal 7 organic groups module into Drupal 10 group module. In some cases, knowing how fields store data in the source and destination sites is important. For example, if you want to combine or split fields attached to an entity bundle.

We quickly covered a lot about Drupal entities and the role they play in data migrations. Understanding entities, their types, and their relationships is important for a successful migration. This is a complex subject with many nuances, so stay tuned as we break it down further in upcoming articles.


Image by Petr from Pixabay