Field API
The Field API is the Drupal core layer for fields: modules extend it with field type, widget and formatter plugins, and Field UI is built on top of it.
The Field API is the part of Drupal core that attaches custom data fields to entities and takes care of storing, loading, editing and rendering their values. Any entity type can use it to become fieldable. It is built on three plugin types: field types, field widgets and field formatters.
How the Field API works in Drupal 11
The core documentation names two main data structures and one grouping concept. A field storage defines a type of data that can be attached to entities. A field is attached to a single bundle. A bundle is a set of fields that belong together on one fieldable entity type. In the configuration system these appear as the field_storage_config and field_config entity types.
The three plugin types share the same shape:
| Plugin type | Attribute | Interface and usual base class | Namespace |
|---|---|---|---|
| Field type | FieldType | FieldItemInterface, FieldItemBase | Drupal\{module}\Plugin\Field\FieldType |
| Field widget | FieldWidget | WidgetInterface, WidgetBase | Drupal\{module}\Plugin\Field\FieldWidget |
| Field formatter | FieldFormatter | FormatterInterface, FormatterBase | Drupal\{module}\Plugin\Field\FieldFormatter |
The attributes live in Drupal\Core\Field\Attribute. A field type class describes its properties in the static propertyDefinitions() method and its storage in schema(). The FieldType attribute can name a default_widget and a default_formatter. A widget decides how the field appears in edit forms; a formatter decides how it appears when the entity is displayed. Plugin managers do the discovery, so the general rules of the Plugin API apply. Modules can change existing definitions with hook_field_info_alter(), hook_field_widget_info_alter() and hook_field_formatter_info_alter().
Plugin attributes arrived in Drupal 10.2. The change record states that all plugin types in core support them as of Drupal 11.2, and the field plugins in core 11.4.8 use them.
Example
Fields you create in the Field UI are configuration. A fieldable entity type can also declare base fields in code, which exist on every bundle. In the static baseFieldDefinitions() method of the entity class:
$fields['subtitle'] = BaseFieldDefinition::create('string')
->setLabel(t('Subtitle'));
Here string is the plugin ID of a field type. Core labels it Short text, and it comes with the widget string_textfield and the formatter string.
Common mistakes
- Treating Field API and Field UI as one thing. The Field UI module is only an interface; the Field API works without it.
- Writing a new field type for a display or input problem. If the data is fine and only the input or output must change, write a widget or a formatter. Both declare the field types they support through their
field_typeskey. - Putting a plugin in the wrong namespace. The documentation says each plugin type must sit in its own
Plugin\Fieldsubfolder. - Copying an old tutorial. The drupal.org page on field types, widgets and formatters still shows docblock annotations and refers to Drupal 8 in its text. Core 11.4.8 defines these plugins with PHP attributes.
For marketing and content teams
You will rarely see the Field API by name. You see its results: each input on an edit form and each value on a page is a field. If the standard field types, widgets and formatters do not cover a need, such as a special price input or a custom display for an address, a developer builds it as a plugin using this API.
Sources
- Drupal core 11.4.8: Field API topic and Field module help (FieldHooks.php)
- Drupal core 11.4.8: Field Types API, Field Widget API and Field Formatter API topics (field.api.php)
- Drupal core 11.4.8: FieldType attribute
- Drupal core 11.4.8: FieldableEntityInterface
- Drupal core 11.4.8: FieldItemInterface
- Drupal core 11.4.8: FieldStorageConfig entity type
- Drupal core 11.4.8: FieldConfig entity type
- Drupal core 11.4.8: StringItem field type
- Drupal.org change record: Plugin implementations should use PHP attributes instead of annotations
- Drupal.org: FieldTypes, FieldWidgets and FieldFormatters